Understanding DS18B20 Temperature Data

EDIT: Thanks el_supremo and jimmus!! Questions updated with answers.

Hey all, I'm currently playing with some DS18B20P temperature sensors and the OneWire library and the DS18x20 example and am confused with how the temperature is retrieved. According to the datasheet, the data is stored in the scratch pad in an LS byte and a MS byte.

First question, what is LS/MS? Answer: Least Significant / Most Significant

Next, one wire displays the retrieved data as 28 01 4B 46 1F FF 08 10 DC.

Second question: why do we need to retrieve so many bytes if the temp is only two bytes? Answer: We don't need to, but it may be faster to retrieve the other bytes than to cancel it.

Next, in the code, the temperature is extracted from the first and second byte and stored in a int16_t. The second byte is used as the more important bit, so it is fed to the int16_t (raw) as 01 28, which in decimal is 296. Next, the code gets what is refereed to as cfg from the data and then does a bitwise and with 0x60.

Third question: why does it modify the configuration data with 0x60? Answer: This removes other information and only retains the two bits which control resolution.

Next, based on the cfg value, it has a few options. For whatever reason I don't know yet, the execution branch I'm seeing is cfg == 0x00, so then the code has raw = raw & ~7.

Fourth question: what is raw = raw & ~7? I've found info on bitwise & and bitwise ~, but not both. Answer: 7 is binary 111, ~7 is 1111111111111000, which masks off the lower three bits not in use for 9 bit resolution.

Finally, the result is divided by 16. In the datasheet it indicates the value is stored as a two-compliments value, so I'm guessing the division has something to do with that, but the examples I've found for twos-compliment doesn't divide by 16, it uses bitwise to flip the digits and add or subtract 1.

Fifth question: why is the result divided by 16? Answer: Highest resolution is 1/16th of a degree Celsius, decimals take more bits to store, so actual temp is stored as temp multiplied by 16. Have to reverse the multiplication to get the decimals back.

Least Significant/Most Significant.

28 01 4B 46 1F FF 08 10 DC is not the temperature, it is the ROM address which is described in the datasheet.

That part of the config register holds the two bits which control the resolution of the temperature reading. Figure 7 and Table 3 in the datasheet.

7 is binary 111. ~7 is the 16-bit binary 1111111111111000. Then the & with this masks off the lower three bits.

Figure 3 and Table 2 on page 4 of the datasheet show that the lowest 4 bits of the temperature are the 4-bit fraction. To convert that from an integer to a floating point number you divide by 16.

Pete

docdockstader:
Next, one wire displays the retrieved data as 28 01 4B 46 1F FF 08 10 DC.

Second question: why do we need to retrieve so many bytes if the temp is only two bytes?

Actually, we don't. If all we want is the temperature, and we already know the configuration data, and we don't care about the checksum, we could get by with 2 bytes. From the spec sheet: "The master may issue a reset to terminate reading at any time if only part of the scratchpad data is needed." I don't know how to do that using one-wire since I have never needed to. It takes 750 mS before I can read my data in high-res mode, so the extra 6 bytes are not a big deal.

The other bytes are for other capabilities of the chip. You can set alarms so it alerts you when the temp gets too low or too high. Or you can use those bytes to store data across power cycles. Three of the bytes are reserved. The last one is the checksum.

Finally, the result is divided by 16. In the datasheet it indicates the value is stored as a two-compliments value, so I'm guessing the division has something to do with that, but the examples I've found for twos-compliment doesn't divide by 16, it uses bitwise to flip the digits and add or subtract 1.

It uses twos-complement to store negative numbers.

The resolution in high-res mode is 1/16ths of a degree Celsius. So a temperature of 1 degree will give a raw reading of 16, and 100 degrees will give a raw reading of 1600. like el_supremo says, you have to divide it by 16 if you want to get the actual temp.

el_supremo:
28 01 4B 46 1F FF 08 10 DC is not the temperature, it is the ROM address which is described in the datasheet.

I made double sure this was the data being returned by the sensor, not the address, as that's what I thought at first as well. The address of this particular sensor is 28 CA CB E2 03 00 00 B6.

Thank you for the other answers!!

Cut and paste the output that you're talking about and post the code that generated it (in code tags).

Re: 28 01 4B 46 1F FF 08 10 DC
That has the format of a ROM address. The 28 indicates that the device is a DS18B20 and the CRC (DC) of the entire thing is valid. Therefore it is a ROM address.

Pete

It really, really isn't a ROM address. ROM addresses are only 8 bytes anyways, and I have the exact ROM address because I'm calling the sensor specifically by address when pulling the temperature. I appreciate your help on the other questions though.

28 01 4B 46 1F FF 08 10 DC
Ahhh. You're right. This is the whole scratchpad which just happens to start with 0x28 which makes it look like a ROM address. But, as you say, a ROM address is 8 bytes.

28 01 is the LS and MS bytes of the temperature which works out to 18.5C.
1F is the configuration register. The bottom 5 bits are always 1. The next two are zero indicating that the DS18B20 is set for 9 bits of temperature resolution.

Pete