by Floris Wouterlood – The Netherlands
Introduction
One of the components of a weather station is a device that measures the temperature of the environment. Traditional analog instruments are based on the physical principle of expansion as a function of temperature. An affordable electronic solution with reasonably accurate sensing is the Dallas DS18B20 temperature sensor manufactured by Maxim. Their accuracy is about 0.5 oC and they can be used to measure temperatures between -10 oC and +85 oC. These devices can be bought ‘bare’ or encapsulated in a waterproof casing, a real ‘probe’ so to speak. As the ‘bare’ version is much faster in its response to higher temperatures than the encapsulated ‘waterproof’ DS18b20 we will further deal with the ‘bare version’ (fig 1).
The DS18B20 is compatible with the Arduino microcontroller. Its enormous advantage compared with other temperature sensors is that it operates in a ‘single bus’ environment, that is that multiple sensors (up to 127) can be connected to an Arduino while only one data wire is necessary. A DS18B20 can even draw power from the data bus (so-called parasitic power) which means that two wires: data and GND, are sufficient to support a large number of (nearly) simultaneous temperature measurements. For instance, monitoring temperatures in different compartments of the home (living room, kitchen, bedrooms, attic, garage, basement) can easily be performed with multiple DS18B20s connected to one Arduino. Distances of up to 50 meter wire length are no problem.
The one-wire bus works as follows. Each individual DS18B20 probe has its unique ID. This ID consists of a 64-bit number (8 bytes). The microcontroller calls a unique ID, and the corresponding DS18B20 responds by returning two bytes that carry temperature information. All the other DS18B20s connected to the bus remain silent because their ID is not called. The process of one DS18B20 recognizing its ID call and responding to it by sending the data bytes takes about 750 msec. This means that one measuring cycle of, say, 10 temperature sensors takes 7,5 seconds, with the response from sensor #10 seven and a half seconds later than that of sensor #1. That delay is the price to be paid for having only one bus to carry all up- and downstream signals.
Electronic components needed
1x Dallas DS18B20 sensor, 1x Arduino Uno or Nano, 1x 4.7 kΩ resistor, breadboard, jumper wires.
Wiring
Figure 2: Wiring of a DS18B20, in this example to pin D10 of the Arduino Nano. A 4.7 kΩ pull up resistor is mandatory. The 5V power supply to the sensor can be omitted. With multiple DS18B20s a stable configuration requires power supply to all sensors.
Figure 2 shows the wiring of the DS18B20. Here we connect the DATA pin of the DS18B20 with pin 10 of the Arduino, but any other digital pin will work as well. Multiple sensors can be connected in parallel. A 4.7 kΩ pull up resistor is required; without this resistor the sensor will not work. The 5V wire is not absolutely necessary when a single sensor is applied because the DS18B20 can use power from the data wire when it is set ‘high’ by the microcontroller, that is, the moment that the microprocessor starts sending an ID call. This ‘parasitic’ power is enough for a DS18B20 to do its work. When multiple temperature sensors are used it is advised to use a power supply because all DS18B20’s then have their own power supply instead of in ‘parasitic mode’ draining away all power from the data line. A robust and stable multisensor configuration requires a robust power supply. With multiple sensors a 10 kΩ potentiometer can be applied instead of a single 4.7 kΩ resistor, for the fine tuning of the pull up resistance.
Sketches
Because every DS18B20 has its own unique ID it is necessary to know what that ID is. For this purpose a sketch exists named DS18B20_address_reporter.ino.
Furthermore, for the compilation of the sketch into binary Arduino instructions a library is necessary named OneWire.h.
The sketch DS18B20_address_reporter.ino (or a similar sketch) can be found in the public domain:
/* DS18B20_address_reporter
this sketch looks for one-wire devices and
prints their ID address (8 bytes)
to Serial Monitor, in a format that is useful in Arduino sketches
*/
#include <OneWire.h>
#define onewirepin 10 // DATA pin of DS18B20 wired to pin 10 of Arduino
OneWire ds(onewirepin);
void setup(void) {
Serial.begin(9600);
reportOneWireDevices();
}
void reportOneWireDevices(void) {
byte i;
byte present = 0;
byte data[12];
byte addr[8];
Serial.println (“DS18B20 address reporter”);
Serial.print (“Looking for 1-Wire devices…\n\r”);
while (ds.search(addr)) {
Serial.print (“\n\rFound \’1-Wire\’ device with address:\n\r”);
for( i = 0; i < 8; i++) {
Serial.prin t(“0x”);
if (addr[i] < 16) {
Serial.print (‘0′);
}
Serial.print(addr[i], HEX);
if (i < 7) {
Serial.print (“, “);
}
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print (“CRC is not valid!\n”);
return;
}
}
Serial.print (“\n\r\n\rThat’s it.\r\n”);
ds.reset_search ();
return;
}
void loop(void) {
// empty nothing to do here
}
With the DATA pin of the temperature sensor connected to pin 10 of the Arduino, and with the pull up resistor in place, Serial Monitor will present an output like that in Figure 3.
Figure 3. Serial Monitor output for the sketch DS18B20_address_reporter.ino
The Device address is important because this is the ID of the temperature sensor. The sketch reading the temperature from the DS18B20 needs this address to call the correct sensor with the correct unique ID.
Now the ID (Device Address) is revealed we can complete the real sketch, DS18B20_sensor.ino. Also this sketch is published in the public domain:
/* DS18B20_sensor
based on a sketch by Rik Kretzinger
this sketch reads temperature from one DS18B20 sensor
and reports to Serial Monitor
public domain
*/
#include <OneWire.h>
#include <DallasTemperature.h>
#define onewirepin 6
OneWire oneWire(onewirepin);
DallasTemperature sensors(&oneWire);
// find the DeviceAddress of your DS18B20 with the sketch DS18B20_address_reporter
// then replace the 8-byte ID below with the reported one
DeviceAddress Probe = { 0x28, 0xFF, 0x0A, 0x75, 0xA3, 0x15, 0x04, 0xBC };
void setup(){
Serial.begin (9600);
Serial.print (“Initializing Temperature Control Library Version “);
Serial.println (DALLASTEMPLIBVERSION);
sensors.begin (); // Initialize the sensor and set resolution level
sensors.setResolution(Probe, 10);
delay(1000);
Serial.println();
Serial.print (“Number of Devices found on bus = “);
Serial.println (sensors.getDeviceCount());
Serial.print (“Getting temperatures… “);
Serial.println ();
}
void loop()
{
sensors.requestTemperatures(); // Command all devices on bus to read temperature
Serial.print(“Temperature is: “);
printTemperature(Probe);
Serial.println();
delay(1000);
}
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00)
{
Serial.print (“Error getting temperature “);
}
else
{
Serial.print (“C: “);
Serial.print (tempC);
Serial.print (” F: “);
Serial.print(DallasTemperature::toFahrenheit(tempC));
}
}
The output of Serial Monitor is shown in Figure 4. Because the measurement is within the loop of the sketch the measurement goes on for ever. The instruction delay(1000) makes sure that looping time is greater than the time for the sensor to respond to an ID-temperature call.
Figure 4. Serial Monitor output for the sketch DS18B20_sensor.ino. Note that at a certain point the sensor was gently touched “pinched” between thumb and finger.
Download; zipped file DS18B20.zip that contains both sketches in this article.