DS18x20 Temperature Register format comment

There seems to be a misconception about the DS18x20 Temperature Register format that has continued to propagate from the official OneWire library through various "improvements" to the libraries. This misconception results in the unnecessary conversion of negative temperature values.

In the three variants of the part in common use, the DS18B20, DS18B20PAR, and the DS18S20, the contents of the Temperature Register is already a C/C++ int. Therefore, no conversion is necessary to properly compute and display negative temperature values.

For example, for a DS18B20, if the Temperature Register reads 0xFC90, that is decimal -880 and multiplied by the 12-bit conversion factor, 0.0625, yields the correct -55.00 degrees Celsius.

The DS18S20 Temperature Register contains an int as well and has a conversion factor of 0.5.

If one is using the DS18B20 in any of the three lower resolution / lesser conversion time modes all is well, too. Since the right shift, >>, operator is arithmetic in nature, it maintains the sign bit extension and one only has to use it to eliminate the undefined bits in the lower resolution modes.

I will gladly edit the OneWire page in on the playground as soon as I get a little experience editing in the sandbox. :slight_smile:

Libraries that are derivative works of the official library will have to be the responsibility of their respective authors if they want to take the time to edit them. While in most cases the unnecessary conversion does no harm, it does suggest a misunderstanding of the device and is certainly confusing to a new user that bothers to read the data sheet.

-EJ

For example, for a DS18B20, if the Temperature Register reads 0xFC90, that is decimal -880 and multiplied by the 12-bit conversion factor, 0.0625, yields the correct -55.00 degrees Celsius.

How would you code for the above then without using floating point math?

Well, I want to ask why would you want to but that might be impolite. :slight_smile:

Maybe I'm missing something but the method used in the OneWire example would work fine without the unnecessary conversion of the TReading from a negative integer to a positive integer + sign flag.

On the other hand, since print supports 2-place floats now I guess the only reason you'd want to do that is for memory usage reasons.

Or what was the point you had?

I'm sorry, that didn't really answer your question. I'd probably edit the example on the playground similarly to this:

...
LowByte = data[0];
HighByte = data[1];
int TReading = (HighByte << 8) + LowByte;
int Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

int  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
int  Fract = Tc_100 % 100;
  Serial.print(Whole);
  Serial.print(".");
  if (Fract < 0) Fract = -Fract;
  if (Fract < 10)
  {
     Serial.print("0");
  }
  Serial.print(Fract);

  Serial.print("\n");

I've been using the following code for printing temperatures with 1 decimal precision:

void PrintDS()
{
  byte data[9];
  
  ds.reset();
  ds.select(ds_addr);    
  ds.write(0xbe);         // Read Scratchpad
 
  for (char i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }/*for*/
  if (data[8]!=OneWire::crc8(data,8)) return;

  int   t1,t2;
  t1=*(int *)data;
  if (t1<0) {
    Serial.print('-');
    t1=-t1;
  }/*if*/
  t2=t1&0x0f;
  t1=t1>>4;
  t2=(t2*625+500)/1000;  // round to 1 decimal accuracy
  //t2=(t2*625+50)/100;  // round to 2 decimal accuracy
  Serial.print(t1,DEC);
  Serial.print('.');
  Serial.println(t2,DEC);

  //float t;
  //t=*(int *)data * 0.0625;  // convert to float
  //Serial.println(t);
}/*PrintDS*/

Always eager to learn however I'm wondering then how your proposed change would improve on the above? :slight_smile:

Added: Sorry - didn't see your follow up before replying. Your proposal looks good to me.

I'm not interested in improving on your code unless you wrote the example on the playground. :slight_smile:

The code you just posted implies that you understand that the value read from the device is a signed integer and the way you have dealt with it is fine, although my way I don't have to print the minus sign as a separate character.

Added: Sorry - didn't see your follow up before replying. Your proposal looks good to me.

Edit: Ah, okay, nevermind. :slight_smile:

EmilyJane,
would you please explain the protocol of library code updating?.
You mentioned possibly changing the OneWire library...
Who is allowed to do this?.

The page Arduino Playground - OneWire also mentions a separate library Miles Burton is working on.

How will two libraries evolving in parallel be integrated in Arduino release 18?.

PS: if the answers are obvious, please forgive me, I am a newbie.