Jump to content
OzGrant

[Energia Library] OneWire DS18B20 (430 & Stellaris)

Recommended Posts

After a bit of research I have found that the Tiva C Peripheral Driver code provides OneWire functions but these are designed to use the 1-Wire modules available in the TM4C129X MCUs used in the development kit DK-TM4C129X. The TM4C1294NCPDT MCU used in the Connected LaunchPad doesn't contain the 1-Wire module however.

I think I can probably create some equivalent code to bit-bang the 1-Wire interface using the GPIO module calls and in turn create an appropriate Energia OneWire library for the LaunchPad in the next few days (I'm currently between jobs and have some time).

I'll let you know how I get on.

 

Jeff

Share this post


Link to post
Share on other sites

Pavel,

Will have a TM4C129 in a couple of days and check it out.

Grant

 

 

After a bit of research I have found that the Tiva C Peripheral Driver code provides OneWire functions but these are designed to use the 1-Wire modules available in the TM4C129X MCUs used in the development kit DK-TM4C129X. The TM4C1294NCPDT MCU used in the Connected LaunchPad doesn't contain the 1-Wire module however.

I think I can probably create some equivalent code to bit-bang the 1-Wire interface using the GPIO module calls and in turn create an appropriate Energia OneWire library for the LaunchPad in the next few days (I'm currently between jobs and have some time).

I'll let you know how I get on.

 

Jeff

 

Grant and Jeff

 

Sounds promissing, thanks and happy to help with testimg.

 

P

Share this post


Link to post
Share on other sites

Hi guys,

 

Well I finally got some time to work on getting Grant's code to work on the TM4C1294XL LaunchPad. I have attached my DS18B20 on PortE-3 (BoosterPack pin X8-12) with a 4.7K pullup resistor to 5V on pin X8-2 and GND on X8-4.

 

I managed to get it working with minimal mods to Grant's demo program. I had to use a seperate member function to initialise the pin port and bitmask variables as it didn't seem to like doing that in the constructor. This InitGPIO() function also allows for an error return if the pin description used (eg. PE-3) is invalid. I also found a situation where the reset() function error value (2) for a stuck line was being interpreted as finding two devices, so I have changed this to have a value of 99. I have provided a modified example with the minor changes.

 

Everything seems to work now although I haven't tested it on the other TM4C LaunchPad board - I might try that tomorrow. I have called the library TM4C_DS18B20 to show that it is currently a different architecture and needs to be placed in the libraries directory under the lm4f hardware directory.

 

Try it out and let me know if there are any issues.

 

Cheers.

 

Jeff

TM4C_DS18B20.zip

Share this post


Link to post
Share on other sites

I have tested the TM4C_DS18B20 library on the TM4C123GXL LaunchPad and it works ok. The only thing to know is that the BoosterPack pinouts for 5V and GND are J3-1 (VBUS) and J3-2 and the signal pin for PE-3 is J3-9. Note that the equivalent boosterPack pin as used on the TM4C1294XL (X8-12 = J3-6) is actually pin PE-5 on this board.

 

There does still appear to be an issue with the temperature reading showing 0 C every now and then. This appears to be a timing issue somewhere in the readOW() function after each data byte is read. I will try to find out if it just requires tuning of the points in the read cycle. There may be some delays introduced when the serial port interrupt overrides the timing in the readbyte() code.

 

Jeff

Share this post


Link to post
Share on other sites

 

 

Try it out and let me know if there are any issues.

 

Cheers.

 

Jeff

 

Hi Jeff,
 
Good job, thank you! (Since the library is now for Tiva series you might consider to start new thread in http://forum.stellarisiti.com/ forum.)
 
My observations with TM4C1294XL LaunchPad and one DS18B20, the same pinout:
 
It works :smile: , zeros were showing randomly. I implemented decimal places by jxlbbb from above (I believe two are not relevant for the sensor precision but anyhow) and Serial.begin (115200) which had some influence on zeros on its own.
 
By playing with delay (1000) in tempCMD I guess the sensor needs to recover (I recollect some two seconds for DHT11 - will have a look at datasheet for DS18B20). By setting it to delay (1500) I did not get single zero with some 2k+ outputs so far.
 
Regards
Pavel

TM4C_OneWire_DEC2.zip

Share this post


Link to post
Share on other sites

Hi Pavel,

 

I'm still getting issues. Using your code, at 115200 baud, I don't get any response from the DS18B20 and at 38400 baud I get 4095.93 degC errors instead of zeroes ! I will need to track this issue down as something's not quite right somewhere. Once I find out what's going on I'll repost on the Tiva forum as suggested.

 

Cheers.

 

Jeff

Share this post


Link to post
Share on other sites

Grant,

 

Thanks for a great library - saved me a bunch of time. 

 

I added the following function so now I can read temperatures from multiple sensors on the same wire.  Seems "GetData" and "GetData10" functions are designed to read from a single sensor on the bus.  WIth multiple sensors, all the sensors try to respond and step on each other.  The function "GetNodeData" fixes that.

 

Thanks again,

Jim

int32_t DS18B20::GetNodeData( uint8_t rom[8] )
{
    uint8_t i;
    uint16_t temp;
    reset();

    write_byte(0x55);            // Choose ROM
    for ( i = 0; i < 8; i++ ) write_byte(rom[i]);

    //write_byte(0xcc); // skip ROM command
    write_byte(0x44); // convert T command
    OW_HI
    delay(750);        // had incorrectly used delayMicroseconds()

    reset();

    write_byte(0x55);            // Choose ROM
    for ( i = 0; i < 8; i++ ) write_byte(rom[i]);

    //write_byte(0xcc); // skip ROM command
    write_byte(0xbe); // read scratchpad command
    temp = ReadDS1820();

    int16_t stemp = (int16_t)temp;
    return((int32_t)stemp*625/1000);
}

Share this post


Link to post
Share on other sites

The following code works even better if you have multiple sensors on the same bus.  The following code also handles negative values.  Simply call CmdT() first - all the sensors on the bus make a temperature measurement at the same time.  Then, call GetNodeData( addr[] ) for each sensor on the bus.  With several sensors on the bus this method is much faster.  I'm reading three sensors in under a second.

 

Jim

void DS18B20::CmdT( void ) {

    reset();
    write_byte( 0xCC ); // skip ROM command
    write_byte( 0x44 ); // convert T command
    OW_HI
    delay( 750 );        // Delay in milliseconds.
}

int32_t DS18B20::GetNodeData( uint8_t rom[8] ) {
    int32_t stemp;

    reset();
    write_byte( 0x55 );            // Choose ROM
    for ( uint8_t i = 0; i < 8; i++ ) write_byte( rom[i] );

    write_byte( 0xBE );     // read scratchpad command
    uint16_t temp = ReadDS1820();

    if ( temp & 0xF800 )    
        // Handle negative values.
        stemp = ((int32_t)(~temp) + 1) * -1;
    else                    
        stemp = (int32_t)temp;

    // Return value as degrees C times 10.
    return( stemp * 625 / 1000 );
}

Share this post


Link to post
Share on other sites

This might be cool too.  Call CmdT() to start a temperature conversion.  Inside CmdT() a timestamp is set to record millis() which returns the system milliseconds since powerup.  Then, in GetNodeData() a check is made that a minimum of 750 milliseconds has elapsed.  This would allow an application to call CmdT() to start a conversion, do some other processing, and then return later to collect the results.  The code, I think - untested, would look like the following.

 

Just an idea to allow other things to happen while a temperature conversion is happening on the bus.

uint32_t convertTimestamp;

void DS18B20::CmdT( void ) {
    reset();
    write_byte( 0xCC ); // skip ROM command
    write_byte( 0x44 ); // convert T command
    OW_HI
    convertTimestamp = millis();  // Set timestamp
}

int32_t DS18B20::GetNodeData( uint8_t rom[8] ) {
    int32_t stemp;

    // Wait for temp conversion to complete.
    while( convertTimestamp + 750 > millis() );

    reset();
    write_byte( 0x55 );            // Choose ROM
    for ( uint8_t i = 0; i < 8; i++ ) write_byte( rom[i] );

    write_byte( 0xBE );     // read scratchpad command
    uint16_t temp = ReadDS1820();

    if ( temp & 0xF800 )    
        // Handle negative values.
        stemp = ((int32_t)(~temp) + 1) * -1;
    else                    
        stemp = (int32_t)temp;

    // Return value as degrees C times 10.
    return( stemp * 625 / 1000 );
}

Share this post


Link to post
Share on other sites

I have made this simplified code to easily enable continuous reading of a single DS18B20 sensor. It reads the value and starts a fresh conversion so you can just periodically (greater then 1s period) call the function to get temperature.

// TM4C1294XL One-Wire - One sensor continuous
// Have used arrays to hold retrieved information, so that it can be easily addressed by your code
// This sketch plus StellarisDS18B20.h will run as is on 430 & Stellaris LaunchPads
// Do a reset to view the One Wire ROM addresses. Have Fun.
// Grant Forest 29 Jan 2013.
// Had confusion with library names. Lib now called GFDS18B20
// GF 6 Feb 2913  cleaned up a bit of code.
// JM 8 Apr 2014 modified for TM4C1294XL LaunchPad
// Musti 14 June 2014 derived for simpel continuos reading of a single sesnsor

#include <TM4C_DS18B20.h>

#define OWPIN  PE_3      // 1-wire signal with 4.7K pullup on pin X8-12 (PE-3), 5V on X8-2, GND on X8-4

byte addr[8] ;

DS18B20 ds(OWPIN);  // currently on PIN 11

void setup(void) 
{
  Serial.begin(115200);
  ds.InitGPIO();
  ds.search(addr);
  //start conversion
  ds.reset();
  ds.write_byte(0xcc);  // was ds.select(work); so request all OW's to do next command
  ds.write_byte(0x44);  // start conversion, with parasite power on at the end
}

void loop(void) {

  Serial.print("OW");
  Serial.print(" = ");
  Serial.print(measure_DS18bB20());      
  Serial.println(" degC");
  
  delay(1000);

}

float measure_DS18bB20(){
  byte data[12];
  float result;
  //read
   ds.reset();
   ds.select(addr);
   ds.write_byte(0xBE);         // Read Scratchpad
   for ( char i = 0; i < 9; i++) {   // need 9 bytes
    data[i] = ds.read_byte(); 
  }
  
  result = (int32_t)((data[1] << 8) | data[0]);
  result*=0.0625;
  
  //start next conversion  
  ds.reset();
  ds.write_byte(0xcc);
  ds.write_byte(0x44);
  
  //check if received data is invalid, return 0
  if(data[0]==0xFF & data[1]==0xFF){
    result=0;
    return result;
  }
  
  return result;
}

Share this post


Link to post
Share on other sites

Hello,
I am trying to connect a Ds18s20 sensor to msp430g2553 , i have connected the ground pin to the common ground and the data pin to pin8, and get the following message :ret= (3) No more addressess. Please help :)

after this step i plan to use the pfatfs library to use as a datalogger with an sd card, and thankfully that part is alright...but i need to get the temperature right! :)post-37428-0-57071900-1402905119_thumb.png

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×