Dallas Temperature Control Library released ;)

Hey guys,

I’ve you have any of the following Dallas ICs then this library is for you.

  • DS18B20
  • DS18S20
  • DS1820

It’s very simple to use, simply create an instance of DallasTemperature and begin on a port of your choice :wink:

/*
DallasTemperature.CPP - Dallas Temperature Control Library 1.0.0
Author: Miles Burton,
Copyright (c) 2009 Miles Burton All Rights Reserved

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

This code has been derived from: http://www.arduino.cc/playground/Learning/OneWire. Unknown author, unknown date

You will need a 4.7K Ohm Resistor to “pull-up” the 1-Wire data line. You may use any combination of resistors 5x1k etc.
If you are using the DS18B20, ground pins 1 and 3. The centre pin is the data line ‘1-wire’.

Devices supported:
DS18B20
DS18S20
DS1820

You may extend this functionality through strategies. Please post on Arduino.cc and contribute to the project

*/

#include <DallasTemperature.h>

DallasTemperature tempSensor; // You may instantiate as many copies as you require.

void setup(void) {
// initialize inputs/outputs
// start serial port
Serial.begin(9600);
tempSensor.begin(12); // Data wire is plugged into port 12 on the Arduino
Serial.println(“Dallas Temperature IC Control Library 1.0. Miles Burton”);
}

void loop(void) {

// Ask the library whether the device is valid
switch(tempSensor.isValid())
{
case 1:
Serial.println(“Invalid CRC”);
tempSensor.reset(); // Attempts to redetect IC
return;
case 2:
Serial.println(“Not a valid device”);
tempSensor.reset(); // Attempts to redetect IC
return;
}

// getTemperature returns a float. Please note, this will always be a positive number.

Serial.print(tempSensor.getTemperature());
Serial.print(“C”);
Serial.println();
Serial.print(DallasTemperature::toFahrenheit(tempSensor.getTemperature())); // Use the inbuild Celcius to Fahrenheit conversion. Returns a float
Serial.print(“F”);
Serial.println();
}

Check out the wiki for more information.

If you’ve got any suggestions or spot any bugs, let me know!

Hi,

Sounds interesting. I was curious about the handling of negative numbers and how it would handle multiple devices on the same bus so looked at your Wiki.

There were no details so downloaded the files to have a good look. But couldnt expand the rar file. Followed the link to unrar and only found a windows application that has to be paid for.

Id like to look at your library but im not going to pay for an archive program. Could you use one of the standard compression types please to make it more accessible. A lot of us dont use windows, but can handle zip and tar. There are a number of freeware applications to do this.

Thanks

Gordon

Rar is nagware and is multiple platform - they do have a "paid" copy, not that I've ever used it. I have some promo copy from several years ago.

I'll put a zipped copy up either way.

As for negative numbers, I don't own a S series so I cannot be sure how that is handled (I was hoping for freeback). The B series converts the number depending on a signed bit; however, I have yet to make it actually negative (bug).

This library isn't designed to use more than one device on the wire. You could but I didn't see the need for "version 1".

Anyway, I'm happy to hear suggestions for a future variant.

Just used you library for the DS1820 (the onewire doesn't work). It worls fine!

Showing negative temperatures would be appreciated as I want to log outisde temperature to understand my heating system alittle better!

Thanks!

Hi Soulid,

good man!

As far as negative temperatures go. It's actually quite an easy modification. If I recall correctly, it DOES show negative temperatures but, deceptively, as unsigned integer so it's hard to tell.

I'll take a look later but the code change wouldn't take long.

Just for you, I've upgraded the library to include support for negative temperatures...

You can access the download version 1.5.0 from here: http://download.milesburton.com/Arduino/MaximTemperature/DallasTemperature_150Test.zip

You can use the same sketch above if you wish or use the included example (Which is essentually the same with the comment removed ;))

Miles:
Briliant!!! Thank you very much for the coding. [smiley=dankk2.gif]
As it was so easy to you, you’ll may recognize that I am not that experienced in coding…

A last question…how do I get the value into a float variable ?

I tried it, but no success…

/*
     DallasTemperature.CPP -  Dallas Temperature Control Library 1.0.0
     Author: Miles Burton, <Removed for privacy>
     Website: http://milesburton.com/wiki
     Copyright (c) 2009 Miles Burton All Rights Reserved

     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
     License as published by the Free Software Foundation; either
     version 2.1 of the License, or (at your option) any later version.

     This library is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     Lesser General Public License for more details.

     You should have received a copy of the GNU Lesser General Public
     License along with this library; if not, write to the Free Software
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

     This code has been derived from: http://www.arduino.cc/playground/Learning/OneWire. Unknown author, unknown date

     You will need a 4.7K Ohm Resistor to "pull-up" the 1-Wire data line. You may use any combination of resistors 5x1k etc.
     If you are using the DS18B20, ground pins 1 and 3. The centre pin is the data line '1-wire'.
     
     Devices supported:
     DS18B20
     DS18S20 - Please note there appears to be an issue with this series.
     DS1820
     
     You may extend this functionality through strategies. Please post on Arduino.cc and contribute to the project
     
*/

#include <DallasTemperature.h>

DallasTemperature tempSensor1; // You may instantiate as many copies as you require.

void setup(void) {
 // initialize inputs/outputs
 // start serial port
 Serial.begin(9600);
 tempSensor1.begin(11); // Data wire is plugged into port 12 on the Arduino
 float temperatur;
 Serial.println("Dallas Temperature IC Control Library 1.0. Miles Burton");
}


void loop(void) {

   // Ask the library whether the device is valid
   switch(tempSensor1.isValid())
   {
       case 1:
           Serial.println("Invalid CRC");
                 tempSensor1.reset(); // Attempts to redetect IC
           return;
       case 2:
           Serial.println("Not a valid device");
                 tempSensor1.reset(); // Attempts to redetect IC
           return;
   }

 // getTemperature returns a float. 
 temperatur = (tempSensor1.getTemperature());
 Serial.print(tempSensor1.getTemperature());
 Serial.print("C");
 Serial.println();
 Serial.println();
}

Followed the link to unrar and only found a windows application that has to be paid for.

FWIW, RAR format archives are supported by 7Zip. Not sure why anyone actually uses RAR though, aside from the pirate scene where there are some historic reasons.

You've made your temperature variable within the scope of "main". You either need to put it as a global variable (stick it outside of all functions) or declare it in the loop() function. But that, ofcourse, will be continually reset and you may run into memory problems :)

Just for you, I've upgraded the library to include support for negative temperatures...

Which file(s) did you "upgrade"?

"DallasTemperature.cpp"

It was litrally a two token addition. Nothing major.

You might be interested in a clarification of the way DS18x20 family handles temperature values that I have posted here:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1249672740/0#0

Ah I'll take a look. I've not touched it as of yet as I dont actually have that device to test.

Indeed, I’ve never understood the “gyrations” that have been coded
for getting the temperature from the DS18x20 devices. FWIW, DS18x20
refers to either DS1820, DS18B20, and DS18S20 – it’s not a specific
device.

For instance:

  // Originally you would read all n bytes (12~). We only need the first two
  byte lowByte = pDataWire->read();
  byte highByte = pDataWire->read();

  int reading = (highByte<<8) + lowByte; // Concat word

I’m OK to here.

This chunk of code is unnecessary:

  bool isSubZero = false;
  // If sub-zero temperature
  if (reading & 0x8000)
  {
      isSubZero = true;
      reading = (reading ^ 0xffff) + 1; // 2's comp
  }

First off, the temperature in ‘reading’ is already a two’s complement
number (albeit, fixed point representation) as read from the sensor.
Second, ‘reading’ could have been tested for negativity with simply:

if (reading < 0)

Third, unnecesarily converting to a positive value could have been done
with reading = -reading

AND there’s no need for this either.

  float temp = (6 * reading) + reading / 4;    // multiply by (100 * 0.0625) or 6.25

  if(isSubZero) temp = 0 - temp; // Make negative

  return temp/100;    // Divide by 100 to gain decimal.

All the code after obtaining the value in ‘reading’ can be replaced with

return ((float)reading * 0.0625);

Then again, the configuration register in the 18B20 should be consulted
earlier to determine which of the last four bits are needed and what
factor to multiply by before returning. The 1820 and 18s20 only require
a multiply of 0.5.

Amen. ;)

Hey Rusty,

Much of the code was nothing more than a refactor of the existing "OneWire" library. I just cleaned it up and made it a little more flexible and "easy to use".

I'll take a look at the bits you picked up on and see if the code can be cleaned up.

Oh, I don't doubt that... and I don't really think I "picked on" anybody in particular except the actual code itself. It's just those "bad" parts that EJ and I really find distasteful. We 'preciate the clean up! If you need s'more soap, just lemme know. :-)

Excellent

@Rusty

I didn't suggest you were "picking on" anyone.. I meant picked up on, ie you found some problems ;). I'm far to old for play ground talk.

I'm just refactoring the library now. In your post you mentioned

"Then again, the configuration register in the 18B20 should be consulted earlier to determine which of the last four bits are needed and what factor to multiply by before returning. The 1820 and 18s20 only require a multiply of 0.5"

...are you referring to the result when the temperature reaches zero? iirc you need to include or discard the MSBs. Can you clarify what you mean?

Cheers

@Miles/TeamMCS

OK, just making sure you knew I wasn't picking on anyone. Some British phrases don't always translate to Texan too well. :-)

In the 18B20 one of the scratchpad registers determines the resolution of the temperature conversion in the sensor. Resolution goes from nine to twelve bits. For 12-bits, all bits are valid and the LSB has a value of 0.0625 (or 1/16). For 11 thru 9 bits of resolution 1 or more of the LSBits become undefined and need to be masked from the reading.

For example, in pseudocode:

if (sensor is 18B20) then
   switch (bits_resolution) 
   case 12:
       temp = (float)reading * 0.0625;
       break;
   case 11:
       temp = (float)(reading >> 1) * 0.125; 
       break;
   case 10:
       temp = (float)(reading >> 2) * 0.25;
       break;
   case 9:
        temp = (float)(reading >> 3) * 0.5;
        break;
    endswitch
else    // sensor is 18S20 or 1820
        temp = (float)reading * 0.5;
endif

return temp;

The if statement may not be needed if another routine handles obtaining the temperature for the other devices.

Optimize the switch statement as prudent and reasonable.

You always keep the MSBs since your variable 'reading' is already in two's complement form.

I think if you look at pages 3 and 4 of the DS18B20 manual you should understand why I'm doing the above. If not, lemme know... OK?

Oh, to get the configuration register for the 18B20, you'll need to read three more byte after the temperature. The first two after the temperature can be disgarded; the next byte is the configuration register. See page 7 of the 18B20 manual. You could keep that value handy for the next temperature conversion.

One nice thing about knowing the resolution... it can shorten the wait for the temperature conversion. The sensor powers up with all 12-bits of resolution selected. For 9-bits, you wait less than 100-millisecs for the temperature conversion.