Part 3 --
A lot of folks have asked how to use the DS18B20 in 12-bit mode, and how to display the results of the DS18B20 temperature readings in °C & °F. Here's a quick code example that displays the temperature in both °C & °F, with 1/16 °C resolution, and ± 0.5°C [0.9°F] accuracy from -10°C to +85°C. The RAW temperature data is shown in 16-bit binary format for verification of the temp conversion calculations.
This is a very simple application, but it uses some of the advanced features of the PicBasic Pro compiler version 2.4 to calculate precise temperatures, and uses the Skip ROM command since we're only using a single 1-wire device.
The conversion calculation from °C to °F shown here works "Full-Range"; from +125°C to -55°C, however, doing this in integer math requires a few tricks. As you'll see, the PicBasic Pro version 2.4 DIV32 function lets us cheat a little.
The code shown below may be confusing until you understand how the DIV32 command works, so spend a little time becoming familiar with this particular command. The DIV32 function allows us to do 16-bit x 16-bit multiplies yielding a 32-bit result. This comes in handy since floating-point math isn't possible using integer math.
Example: The default resolution of the DS18B20 is 0.0625 or 1/16 °C. The compiler & integer math can't understand 0.0625, but it does know what 625 is. By moving the decimal point to the right or the making the number "whole", we can then work with the larger number using integer math. Since the compiler only supports 16-bit variables, other methods have to be used to get results larger than 16-bits. This is where the DIV32 function comes into play.
A temperature reading from the DS18B20 of +25.0625°C or 77.1125°F will look like this: 0000 0001 1001 0001. If you use your calculator, you'll see this 16-bit binary value works out to 401 decimal. Since the resolution of the DS18B20 is in 0.0625 °C, we know that a result of 401 would be; 401 x 0.0625 = 25.0625. The temperature is therefore 25.0625 °C.
Integer math says that we can't use 401 x 0.0625, or get results like 25.0625, but we can use 401 x 625. With the limitations of 16-bit variable storage, 401 x 625 = 250,625 is larger than 65,535, and too big to fit into a 16-bit variable. DIV32 allows us to use these much larger numbers. The only thing left to do after DIV32 is to extract each digit from the result, and place the decimal point where appropriate.
NOTE: 250,625.000 is beyond the 0-4 limitations of the DIG modifier to extract the high digit of 2, so we divide the result by 10 leaving a number we can work with of 25,062. DIG 4 will be the high digit #2. DIG 0 is the lower digit #2, DIG 1 is the #6, etc,,.
The calculation from °C to °F works a little differently. A resolution of 0.0625 °C works out to a resolution of 0.1125 °F, so we use 401 x 1125 / 100 +3200 = 7,711.25 "our modified version of 77.1125 °F". Since 401 x 1125 = 451,125, then 451,125 / 100 = 4,511.25, then 4,511.25 + 3200 = 7,711.25 or 77.11 °F once we have extracted each digit using the DIG function. The larger the number, the greater the precision, hence DIV32 makes this all possible with a minimum of math & effort by allowing us to first make the floating-point number a whole number by increasing the numbers size [moving the decimal point to the right], and work with larger 32-bit results.
The upper 4-bits of the binary value read from the DS18B20 have no significance. The Sign-bit [bit 11] indicates the temperature is either +°C or -°C. The code sample below reads bit 11, and uses this value to decide whether or not to display the negative sign indicator -, or print a + on the LCD for positive temperatures.
You can also remove the routine that displays the temperature value in 16-bit binary format. This was included purely for illustration purposes to show the RAW value being used for the conversion process.
This is a down-&-dirty project showing how to get immediate results with the DS18B20. For more details, including how to identify 1-wire devices, control 1-wire switches, and more, visit the first two article pages here. Reading 1-wire device ROM codes & Communicating with multiple 1-wire devices
PortC.0 is used to communicate with the DS218B20 [as shown above]. PortB.0 is used to send temperature readings to a serial LCD for display. You can easily change the port-pin assignments to any I/O-pins you have available on the PIC microcontroller you're using.
Note: The DS18B20 is referred to as a 12-bit temperature device, but only 11-bits are actually used for the temperature resolution. Bit-11 is the sign-bit, and used to indicate above 0°C "0", and below 0°C "1".
Below is an example of the temperature results read from the DS18B20. The blue-bit "bit-11" is the sign-bit. The remaining red-bits are the actual temperature result. The four high-bits in black are simply ignored, and serve no useful purpose. The example below indicates a temperature of +25.0625°C or 77.1125°F.
The DS18B20 resolution [in 12-bit mode] is 0.0625 or 1/16 °C.
This code sample shows how to achieve very precise results using this temperature sensor, and uses several PicBasic Pro tricks for the conversion process like the new DIV32 command, the DEC/DIG modifiers to extract individual temperature digits from the result for displaying on the LCD.
Until the next project - have fun & and play safe...;o]