DS18B20Article

If you just have a single One Wire (OW) family type connected to your bus, it is pretty easy to access it using Find() - see the Swordfish example file "DS18B20 DisplayTemp.bas". However, what do you do if you have multiple devices connected to your bus?

Each OW device has a unique ROM ID, which enables you to target a specific device. The first thing you need to do is build and run the example program OWSearch.bas. This program not only serves to test your OW bus, but it also displays the ROM IDs for all devices connected to it. For example,

 FAMILY $28 ($1D) ($0000002CDBAE) <- DS18B20
 FAMILY $28 ($3F) ($0000002CD16E) <- DS18B20
 FAMILY $05 ($F1) ($00000019F75D)
 FAMILY $05 ($90) ($0000001A20B7)
 FAMILY $23 ($CA) ($0000005C62EE)
 5 device(s) found

As you can see, there are two DS18B20 temperature sensors connected to the bus. We can set these as constants in our program, like this

const Sensor_A(8) as byte = ($28, $AE, $DB, $2C, $00, $00, $00, $1D)
const Sensor_B(8) as byte = ($28, $6E, $D1, $2C, $00, $00, $00, $3F)

Looking at the above code, the first byte is the family ID - you can view a list of device families here. The next 6 bytes are the ROM ID followed by the checksum.

Now, we just need to write a generic subroutine which will take a ROM ID and display the temperature...

sub DisplaySensor(byrefconst pID() as byte)
   dim TempA as shortint
   dim TempB as word
   RomID = pID
   Convert
   GetTemp(TempA, TempB)
   USART.Write(DecToStr(TempA),".",DecToStr(TempB,2), $BA, "C",13,10)
end sub

Program Listing

// device and clock speed...
device = 18F452
clock = 20

// import modules...
include "DS18B20.bas"
include "convert.bas"
include "usart.bas"

// FAMILY $28 ($1D) ($0000002CDBAE) <- DS18B20
// FAMILY $28 ($3F) ($0000002CD16E) <- DS18B20
const Sensor_A(8) as byte = ($28, $AE, $DB, $2C, $00, $00, $00, $1D)
const Sensor_B(8) as byte = ($28, $6E, $D1, $2C, $00, $00, $00, $3F)

// display a sensor value...
sub DisplaySensor(byrefconst pID() as byte)
   dim TempA as shortint
   dim TempB as word
   RomID = pID
   Convert
   GetTemp(TempA, TempB)
   USART.Write(DecToStr(TempA),".",DecToStr(TempB,2), $BA, "C",13,10)
end sub

// program start...
SetBaudrate(br115200)
SetPin(PORTC.0)
while true
   DisplaySensor(Sensor_A)
   DisplaySensor(Sensor_B)
   delayms(1000)
wend

The output will look like this. I've clamped my finger to the second sensor, so you can see the value rising...

 21.25ºC
 22.50ºC
 21.50ºC
 23.25ºC
 21.50ºC
 24.75ºC
 21.50ºC
 24.00ºC
 21.75ºC
 25.00ºC
 21.00ºC
 25.75ºC
 21.00ºC
 26.25ºC

The above program sample uses a 20MHz clock, but you may have problems when using a slower clock. For example, 4MHz. This is because the OneWire (OW) library uses indirect addressing to access the OW port pin. If you don't know what indirect addressing means, don't worry - but it does cost many more processor clock cycles than if direct addressing was used. Luckily, the DS18B20 module allows you to use direct addressing. An additional benefit is that direct addressing will generate far less code than direct addressing. Here is how it's done...

// device and clock speed...
device = 18F452
clock = 20

// import modules...
#option OW_PIN = PORTC.0
include "DS18B20.bas"
include "convert.bas"
include "usart.bas"

// FAMILY $28 ($1D) ($0000002CDBAE) <- DS18B20
// FAMILY $28 ($3F) ($0000002CD16E) <- DS18B20
const Sensor_A(8) as byte = ($28, $AE, $DB, $2C, $00, $00, $00, $1D)
const Sensor_B(8) as byte = ($28, $6E, $D1, $2C, $00, $00, $00, $3F)

// display a sensor value...
sub DisplaySensor(byrefconst pID() as byte)
   dim TempA as shortint
   dim TempB as word
   RomID = pID
   Convert
   GetTemp(TempA, TempB)
   USART.Write(DecToStr(TempA),".",DecToStr(TempB,2), $BA, "C",13,10)
end sub

// program start...
SetBaudrate(br115200)
while true
   DisplaySensor(Sensor_A)
   DisplaySensor(Sensor_B)
   delayms(1000)
wend

It's virtually identical to the previous code example, except I've removed the call to SetPin() and put

#option OW_PIN = PORTC.0

before the module includes. Notice the emphasis on before. Options should always be declared before you include a module so that the Swordfish pre-processor can calculate a value before it is used in a module.

Using the OW_PIN option is therefore the preferred method of assigning the OW bus pin, in terms of both execution speed and less program ROM being used. Unless there is a compelling reason to do so, do try and avoid the use of SetPin()