Temperature Measurement using the Dallas DS18B20 - PICAXE-08M

copyright, Peter H Anderson, Baltimore, MD, Sept, '04


Introduction

This discussion offers a number of techniques to implement various temperature measurement systems using the lowcost PICAXE-08M (nominally $3.25) and the Dallas DS18B20 1-W temperature sensor.

Note that when used with the PICAXE, the DS18B20 must be powered with +5 VDC. My recommendation is to run two twisted pairs to each DS18B20, one to provide +5VDC and GRD and the other DQ and GRD. With the second pair, it is suggested the GRD be grounded only on the PICAXE side and not at the DS18B20 to avoid ground loops. An obvious implementation is to use CAT-5 cable which includes a number of pairs of twisted cable and is readily available and relatively inexpensive.

An obvious question is how far the DS18B20 units may be located from the PICAXE. I have designed manny temperature measurement modules where I had the ability to actually implement the various aspects of the 1-W protocol. In advertising these units, I suggest a maximum of 200 feet as I have tested all of my designs using a length of 200 foot cable and am willing to guarantee operation to this length. If the customer finds they can go two or three times farther, they are happy. In fact, separate runs of 200 feet from a single PICAXE is probably adequate in most installations. If you have to go further, give it a try.

Program DS18B20_08M_1.Bas.

This program interfaces with three DS18B20 sensors on separate twisted pair runs. It performs measurements on each of the three sensors and sends the result in the of the device number (1, 2, 3) and the temperature with two digits after the decimal point. For example;

1 23.76
2 16.97
3 -10.78
This data is sent to the PC using the SerTxD command, which is 4800 baud for the PICAXE-08M. Clearly, you could modify this for 2400 using the SerOut command.

In this implementation, the ReadTemp12 command is used to read the temperature into word variable TReading. If the most significant bit is a one, the reading is negative and the twos compliment of the reading is performed. This is then multiplied by 100 times 0.0625. The whole and fractional parts are separated and each is output to the terminal separated by a decimal point.

In this implementation, the three measurements are performed and the results sent to the PC or similar, followed by a pause. I didn't really want to wait around for hours to see the results and thus set the pause for nominally 20 secs. However, once debugged, you can easily modify this for an hour or more. Indeed, the accuracy may not be perfect, but if you want a system to monitor temperatures every hour, do you really care if this is 3605 seconds as opposed to precisely 3600 seconds.

' DS18B20_08M_1.Bas - PICAXE-08M
'
' Illustrates an interface with the DS18B20.
'
' Continually measures the temperature and displays to two significant digits on the
' terminal.  This is repeated for DS18B20 temperature sensors on IN1/OUT1, IN2/OUT2
' and IN4.OUT4.
'
' Note that a 4.7K pullup to +5 VDC is required on each DQ lead.  +5 VDC is required on the
' V+ terminal of the DS18B20.
'
'  08M					DS18B20
'
' IO1 (term 7) ------------------ DQ (term 2)
' IO1 (term 6) ------------------ DQ (term 2)
' IO1 (term 3) ------------------ DQ (term 2)
'
' Uses 118 of 256 bytes.
'
' copyright, Peter H Anderson, Baltimore, MD, Sept, '04


    Symbol TReading = W0
    Symbol Whole = B2
    Symbol Fract = B3
    Symbol SignBit = B4
    Symbol Dig = B5
    Symbol TempC_100 = W4
    Symbol DevNum = B6


Top:
    For DevNum = 1 to 3	' 1, 2, 3
       Branch DevNum, (Invalid, Dev1, Dev2, Dev3)

Invalid:

Dev1:
       ReadTemp12 1,TReading
       Goto CalcT

Dev2:
       ReadTemp12 2,TReading
       Goto CalcT

Dev3:
       ReadTemp12 4,TReading
       Goto CalcT		' this statement not really necessary

CalcT:

       SignBit = TReading / 256 / 128
       If SignBit = 0 Then Positive
       ' its negative
       TReading = TReading ^ $ffff + 1 ' take twos comp

Positive:

       TempC_100 =  TReading * 6		' TC = value * 0.0625
       TReading = TReading * 25 / 100
       TempC_100 = TempC_100 + TReading

       GoSub DisplayTemp
    Next

    Pause 20000
    GoTo Top

DisplayTemp:

   SerTxD (#DevNum, " ")
   Whole = TempC_100 / 100
   Fract = TempC_100 % 100
   If SignBit = 0 Then DisplayTemp_1
   SerTxD ("-")

DisplayTemp_1:

   SerTxD (#Whole, ".")
  ' be sure the fractional is two digits
   Dig = Fract / 10
   SerTxD (#Dig)
   Dig = Fract % 10
   SerTxD (#Dig, 13, 10)

   Return


Program DS18B20_08M_2.Bas

This differs from the previous routine in that a single temperature measurment sequence is only performed when the input at Pin3 goes high.

The PICAXE is configured for a polled interrupt, high on Pin3. On interrupt, the program enters the Interrupt routine and waits until Pin3 goes low. Byte variable IntOccurred is then set to 1, the interrupt is again configured and the program return to the main routine. As, variable IntOccurred is at 1, the program breaks out of the loop, clears the IntOccurred variable to zero and performs a single measurement on each of the three DS18B20s and then returns to await another polled interrupt.

My idea in using a logic 1 to cause the interrupt was to provide a simple interface with a PC, which would allow a user to hit a single key and thus cause one measurement sequence to occur.

Thus, one might program the PICAXE-08M with the shunt 10K resistor to ground and series 22K to terminal 2 of the PICAXE.

Once programmed, the connection which was at terminal 2 of the PICAXE, might be moved to terminal 4 (Pin3). Remember to tie the PICAXE programming terminal 2 to ground. Thus, the TxD from the PC is now connected to the PIN3.

Then, use HyperTerm or similar, configured for a direct connection, 4800 baud, no parity and no flow control Normally PIN3 is at a logic zero. When a character a character is received, it momentarily goes high, interrupting the processor and causing a single temperature measurement sequence to be performed.

Note that it is important to use the shunt 10K, series 22K resistor configuration on PIN3 (term 4) as the RS232 levels from the PC are not compatible with PIC.

' DS18B20_08M_2.Bas - PICAXE-08M
'
' Illustrates an interface with a number of DS18B20 temperature sensors.
'
' Uses the polling interrupt to detect a high on Pin3.
'
' Idles until logic one appears on Pin3.
'
' Performs a single temperature measurement and displays to two significant digits on the
' terminal.  This is repeated for DS18B20 temperature sensors on IN1/OUT1, IN2/OUT2
' and IN4.OUT4.
'
' The unit then again idles until a logic one appears on Pin3.
'
' Note that a 4.7K pullup to +5 VDC is required on each DQ lead.  +5 VDC is required on the
' V+ terminal of the DS18B20.
'
'  08M					DS18B20
'
' IO1 (term 7) ------------------ DQ (term 2)
' IO1 (term 6) ------------------ DQ (term 2)
' IO1 (term 3) ------------------ DQ (term 2)
'
' Uses 140 of 256 bytes.
'
' copyright, Peter H Anderson, Baltimore, MD, Sept, '04


    Symbol TReading = W0
    Symbol Whole = B2
    Symbol Fract = B3
    Symbol SignBit = B4
    Symbol Dig = B5
    Symbol TempC_100 = W3
    Symbol DevNum = B8
    Symbol IntOccurred = B9

    SetInt %000010000, %000010000	' Pin 3, High
    IntOccurred = 0

Top:
    If IntOccurred = 0 Then Top

    IntOccurred = 0
    For DevNum = 1 to 3	' 1, 2, 3
       Branch DevNum, (Invalid, Dev1, Dev2, Dev3)

Invalid:

Dev1:
       ReadTemp12 1,TReading
       Goto CalcT

Dev2:
       ReadTemp12 2,TReading
       Goto CalcT

Dev3:
       ReadTemp12 4,TReading
       Goto CalcT		' this statement not really necessary

CalcT:

       SignBit = TReading / 256 / 128
       If SignBit = 0 Then Positive
       ' its negative
       TReading = TReading ^ $ffff + 1 ' take twos comp

Positive:

       TempC_100 =  TReading * 6		' TC = value * 0.0625
       TReading = TReading * 25 / 100
       TempC_100 = TempC_100 + TReading

       GoSub DisplayTemp
    Next

    GoTo Top

DisplayTemp:

   SerTxD (#DevNum, " ")
   Whole = TempC_100 / 100
   Fract = TempC_100 % 100
   If SignBit = 0 Then DisplayTemp_1
   SerTxD ("-")

DisplayTemp_1:

   SerTxD (#Whole, ".")
  ' be sure the fractional is two digits
   Dig = Fract / 10
   SerTxD (#Dig)
   Dig = Fract % 10
   SerTxD (#Dig, 13, 10)

   Return


Interrupt:

   Pause 100
   If Pin3 = 1 then Interrupt
   IntOccurred = 1
   SetInt %000010000, %000010000
   Return


Program DS18B20_08M_3

Discussion to be added.

' DS18B20_08M_3.Bas - PICAXE-08M
'
' Illustrates an interface with the DS18B20 in monitoring two temperatures.  An alarm
' is associated with with one of the temperatures.
'
' Continually measures the temperature and displays to two significant digits on the
' terminal.  This is repeated for DS18B20 temperature sensors on IN1/OUT1 and IN2/OUT2.
'
' If the temperature measured on the DS18B20 associated with IN1 is abve HighTrip, a relay
' on Out4 (term 3) is operated.  It is released when the temperature falls below LowTrip
'
' Note that HighTrip and LowTrip are specified as the temperature plus 60 degrees C to avoid
' working with negative numbers.
'
'
' Note that a 4.7K pullup to +5 VDC is required on each DQ lead.  +5 VDC is required on the
' V+ terminal of the DS18B20.
'
'  08M					DS18B20
'
' IO1 (term 7) ------------------ DQ (term 2)
' IO2 (term 6) ------------------ DQ (term 2)
'
'                               ALM LED
' OUT4 (term 3) ------- 330 ----->|---- GRD
'
' Uses 138 of 256 bytes.
'
' copyright, Peter H Anderson, Baltimore, MD, Sept, '04

    Symbol TReading = W0
    Symbol Whole = B2
    Symbol Fract = B3
    Symbol SignBit = B4
    Symbol Dig = B5
    Symbol TempC_100 = W3
    Symbol DevNum = B8
    Symbol Temp_8 = B9

    Symbol HighTrip = 90	' 30 + 60 - adjust as necessary
    Symbol LowTrip = 88       ' 28 + 60

    Low 4	' turn off alarm
Top:
    For DevNum = 1 to 2	' 1, 2
       Branch DevNum, (Invalid, Dev1, Dev2)

Invalid:

Dev1:
       ReadTemp12 1,TReading
       ReadTemp 1, Temp_8		' read the high 8 bits
       Goto CalcT
Dev2:
       ReadTemp12 2,TReading
       Goto CalcT

CalcT:
       SignBit = TReading / 256 / 128
       If SignBit = 0 Then Positive
       ' its negative
       TReading = TReading ^ $ffff + 1 ' take twos comp

Positive:

       TempC_100 =  TReading * 6		' TC = value * 0.0625
       TReading = TReading * 25 / 100
       TempC_100 = TempC_100 + TReading

       GoSub DisplayTemp
    Next

    ' now deal with the alarm
    Temp_8 = Temp_8 + 60	' to avoid negative numbers
    If Temp_8 > HighTrip Then OperateAlarm
    If Temp_8 < LowTrip Then ReleaseAlarm
    ' else
    Goto SequenceDone

OperateAlarm:
    High 4
    Goto SequenceDone

ReleaseAlarm:
    Low 4
    Goto SequenceDone

SequenceDone:
    Pause 20000
    GoTo Top

DisplayTemp:

   SerTxD (#DevNum, " ")
   Whole = TempC_100 / 100
   Fract = TempC_100 % 100
   If SignBit = 0 Then DisplayTemp_1
   SerTxD ("-")

DisplayTemp_1:

   SerTxD (#Whole, ".")
  ' be sure the fractional is two digits
   Dig = Fract / 10
   SerTxD (#Dig)
   Dig = Fract % 10
   SerTxD (#Dig, 13, 10)

   Return