Thursday, January 7, 2016

DS18B20 temperature sensor with the Raspberry Pi

The Raspberry Pi is an ideal device as the central component in DIY projects like home automation or a weather station. One of the key sensors in these projects is a temperature sensor. In this blog post a tutorial will be provided on how to get started with some of these temperature sensors. This tutorial is a follow-up on my previous post about installing python 3.5.1 on the Raspberry Pi. However, in this tutorial I'm not (yet) using features of python that are not supported by the system installed version (3.4.2).

There are a lot of cheap temperature sensors available for these kind of projects on eBay. The first sensor that will be used in this tutorial is the  DS18B20. This component provides 9-bit to 12-bit Celsius temperature measurements, it also has an alarm function with nonvolatile user-programmable upper and lower trigger points. The DS18B20 communicates over a 1-Wire bus. If used in parasite power mode, this bus only needs 2 lines (data and ground) but power can also be provided by the third line. It measured temperature in the range of -55°C to +125°C and is accurate to ±0.5°C over the range of -10°C to +85°C. This component can be found in two versions a "normal" version (it looks like a transistor) and a waterproof version. The last one is nice for outdoor projects!

For this tutorial, the sensor is connected to the raspberry pi as follows:

  • PIN1: GND (pin 6)
  • PIN2: GPIO4 (pin 7) and with a 4.7k resistor to 3V3 (pin 1)
  • PIN3: 3V3 (pin 1)
As the latest raspbian is used, the drivers for the one-wire protocol are installed. They only need to be loaded on boot. Therefore, you need to add the following line to the file /boot/config.txt and reboot:

dtoverlay=w1-gpio

If you correctly connected the sensors, they should be detected by the system. Every one-wire sensor can be identified with its unique 64-bit identifier. In my case, I have two DS18B20 sensors connected in parallel (only one 4.7k resistor is needed). You can see which sensors are connected on the filesystem with the following command:

$ ls -als /sys/bus/w1/devices/
total 0
0 drwxr-xr-x 2 root root 0 Jan  7 21:57 .
0 drwxr-xr-x 4 root root 0 Jan  1 20:19 ..
0 lrwxrwxrwx 1 root root 0 Jan  2 12:57 28-0115153376ff -> ../../../devices/w1_bus_master1/28-0115153376ff
0 lrwxrwxrwx 1 root root 0 Jan  7 21:57 28-0215649194ff -> ../../../devices/w1_bus_master1/28-0215649194ff
0 lrwxrwxrwx 1 root root 0 Jan  7 21:57 w1_bus_master1 -> ../../../devices/w1_bus_master1

The sensor data can be gathered by reading the w1_slave file in each sensor folder. This file handle provides the most recent sensor data if the CRC check is valid. The value provided divided by 1000 is the temperature in °C. In this case, the sensor measures 20.75 °C.

$ cat /sys/bus/w1/devices/28-0115153376ff/w1_slave
4c 01 55 00 7f ff 0c 10 be : crc=be YES
4c 01 55 00 7f ff 0c 10 be t=20750

So a very basic python program that scans for available one-wire temperature sensors and dumps the current temperature is:

$ cat blog-temp.py 
import os

DEVICE_ROOT_DIR = '/sys/bus/w1/devices/'

def read_temp (device):
  full_filename = '{}{}/w1_slave'.format (DEVICE_ROOT_DIR, device)
  if not os.path.isfile (full_filename):
    raise IOError ('Temperature device {} not found on one-wire'.format (device))
  with open ('{}{}/w1_slave'.format (DEVICE_ROOT_DIR, device)) as f:
    lines = f.readlines ()
    status = lines[0][-4:-1]
    if status == 'YES':
      tempstr = lines[1][-6:-1]
      return float (tempstr) / 1000
    else:
      return None

def scan ():
  for filename in os.listdir (DEVICE_ROOT_DIR):
    if filename.startswith ('28-'):
      yield filename

if __name__ == '__main__':
    for device in scan ():
        print ("Temperature {}: {} °C".format (device, read_temp (device)))

If you run this program you can get the following output:

$ python3 blog-temp.py 
Temperature 28-0215649194ff: 18.187 °C
Temperature 28-0115153376ff: 20.812 °C

So, this was an introduction to the first temperature sensor. In a next blogpost, I will provide more information on the DHT11 sensor. This sensor also measures the humidity. However, it needs a bit more work to be used with a Raspberry Pi.

No comments: