de|en

1-wire Temperatursensor DS1820 am Raspberry Pi (GPIO-direkt)

Raspberry Pi mit 1-wire Interface Platine

Zur Messung der Zimmer- oder Außentemperatur mit dem Raspberry Pi gibt es mehrere Möglichkeiten. Dieser Artikel beschreibt die Variante mit dem minimalen Aufwand an externen Bauelementen. Basis hierfür sind der Temperatursensor DS18S20 und die Softwareemulation des 1-wire Protokolls.

Temperatursensor DS1820

1-wire Temperatursensor DS1820

Beim DS18S20 und den verwandten DS18B20 sowie DS1822 handelt es sich um integrierte Schaltkreise im TO-92 Gehäuse, die Temperatursensor, Analog-Digitalwandler und 1-wire Interface enthalten. Die genannten Typen sind Anschluss- und Softwarekompatibel, sie unterscheiden sich im Wesentlichen in der Messgenauigkeit und im Preis. Die drei Anschlüsse (siehe Bild links) sind Masse (GND, Pin 1), Daten (DQ, Pin 2) und Betriebsspannung (VDD, Pin3). Man kann VDD und GND verbinden und so den Sensor mit einer parasitäre Stromversorgung von 3 bis 5 Volt betreiben. Der Anschluss des Schaltkreises ist dadurch mit einer einfachen zweiadrigen verdrillten Leitung möglich.

An dieser Leitung - dem 1-wire Bus - lassen sich ohne weitere Maßnahmen mehrere DS1820 parallel betreiben. Zur Identifikation besitzt jeder Sensor einen vom Hersteller vergebenen eindeutigen Code.

Raspberry Pi und 1-wire

Temperaturmessung mit dem Raspberry Pi und dem 1-wire Temperatursensor DS1820 enthält eine Aufstellung verschiedener Möglichkeiten, einen 1-wire Bus vom Raspberry Pi aus anzusteuern. Der vorliegende Artikel beschreibt nun die Lösung (1) mit dem geringsten Aufwand an externer Beschaltung. Sie benötigt neben den Sensoren lediglich einen einzigen Widerstand, da sie das 1-wire Protokoll komplett in Software nachbildet.

Nur ein Widerstand

Stromlaufplan Anschluss DS1820 an GPIO
Anschluss des DS18020 an den GPIO Port des Raspberry Pi
Zusatzplatine mit Steckverbinder
Auf der Lochrasterplatte ist noch jede Menge Platz für Erweiterungen

Den Datenanschluss DQ des DS1820 verbindet man direkt mit dem Anschluss GPIO4 der GPIO-Schnittstelle des Raspberry Pi. GND und VDD liegen am Masseanschluss GND. Die parasitäre Stromversorgung bewerkstelligt ein Pullup-Widerstand von 4,7 kΩ zwischen dem 3,3 Volt Anschluss 3V3 und GPIO4.

Den Widerstand, eine Buchsenleiste zum Aufstecken auf den GPIO-Port sowie den 1-wire Anschluss lötet man auf eine kleine Lochrasterplatte, die direkt auf dem GPIO-Port sitzt. Den 1-wire Anschluss kann man platzsparend mit einer abgewinkelten Buchsenleiste realisieren. Das alles bringt man ohne weiteres mit im TEK-BERRY Gehäuse des Raspberry Pi unter.

1-wire Softwaretreiber

Die für die Ansteuerung des 1-wire Temperatursensors erforderlichen Kernelmodule sind Bestandteil der Linux-Distribution Raspbian "wheezy", man muss sie allerdings explizit laden:

Neuere Versionen des Raspbian Betriebssystems ab Kernel 3.18 (Februar 2015) erfordern zusätzlich die Aktivierung des Device Tree Overlay für 1-wire. Dazu editiert man (per sudo nano oder einem anderen Editor Ihrer Wahl) die Datei /boot/config.txt und fügt folgende Zeile hinzu:

dtoverlay=w1-gpio,gpiopin=4,pullup=on

Nach dem erforderlichen Reboot gelingt nun das Laden der erforderlichen Module per Kommandozeile:

sudo modprobe w1-gpio pullup=1
sudo modprobe w1-therm

Wichtig ist der Parameter pullup=1, der dem Modul mitteilt, dass eine parasitäre Speisung über einen Pullup-Widerstand vorhanden ist.

Die Module legen im Verzeichnis /sys/bus/w1/devices jeweils ein Unterverzeichnis für jeden gefundenen Sensor an. Der Name des Verzeichnisses setzt sich aus dem Family-Code des Sensors und seiner eindeutigen Identifikationsnummer zusammen. Sensoren vom Typ DS1820 und DS18S20 haben den Family-Code 10, DS18B20 den Code 28 und DS1822 die 22. In jedem Unterverzeichnis gibt es die Datei w1_slave, die Sensorstatus und gemessenen Temperaturwert enthält:

cd /sys/bus/w1/devices
cd 10-000801b5*
cat w1_slave

0f 00 4b 46 ff ff 06 10 0c : crc=0c YES
0f 00 4b 46 ff ff 06 10 0c t=7375 

Die Datei besteht aus zwei Zeilen, die jeweils den hexadezimalen Registerdump des Sensor-ICs enthalten. Am Ende der ersten Zeile steht die Prüfsumme (CRC) und die Information, ob es sich um einen gültigen Messwert handelt (YES). Die zweite Zeile endet mit dem Temperaturmesswert in tausendstel Grad Celsius. Im Beispiel beträgt die Temperatur also 7,375 °C. Die Genauigkeit auf drei Stellen hinter dem Komma ist natürlich nur scheinbar; dem Datenblatt des DS18S20 entnimmt man zum Beispiel, dass die Messgenauigkeit ±0,5 °C beträgt. Die tatsächliche Temperatur liegt also irgendwo zwischen 6,8 und 7,9 °C.

Wenn alles soweit funktioniert, dann sollte man die beiden erforderlichen Module in die Datei /etc/modules eintragen, damit sie der Kernel in Zukunft automatisch beim Systemstart lädt:

# /etc/modules
w1-gpio pullup=1
w1-therm

Round Robin Datenbank RRDtool

Für eine langfristige Aufzeichnung der Temperaturmesswerte und die komfortable Erzeugung von Grafiken bietet sich die Verwendung von RRDtool an. Die Artikel Wetterdatenerfassung mit dem USB-WDE1 und Temperaturmessung mit dem Raspberry Pi (USB-seriell) stellen dieses Tool ausführlich vor.

Zuerst muss man RRDtool unter Zuhilfenahme des Packagemanagers auf dem Raspberry Pi installieren:

sudo apt-get install rrdtool python-rrdtool

Das zweite installierte Paket python-rrdtool ist ein Python Interface für RRDtool, welches später zur Anwendung kommt. Am Beginn der Arbeit mit RRDtool steht die Definition der Datenbank. Das folgende Beispiel legt eine Datenbank für zwei Temperatursensoren temp0 und temp1 an. Dabei soll pro Viertelstunde (900 Sekunden) jeweils ein Wert gespeichert werden. Nach zehn Tagen (= 960 Werte) erfolgt eine Reduzierung auf jeweils einen Durchschnitts-, Minimal-, und Maximalwert pro Tag. Die Aufbewahrungszeit der Tageswerte beträgt zehn Jahre (= 3600 Werte):

rrdtool create temperature.rrd --step 900 \
DS:temp0:GAUGE:1200:-40:80 \
DS:temp1:GAUGE:1200:-40:80 \
RRA:AVERAGE:0.5:1:960 \
RRA:MIN:0.5:96:3600 \
RRA:MAX:0.5:96:3600 \
RRA:AVERAGE:0.5:96:3600

Datenerfassung mit Python

Ein Pythonscript übernimmt die Auswertung der Special-Files w1_slave und das Einfügen der Temperaturwerte in die Round Robin Datenbank:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import re, os, rrdtool, time

# function: read and parse sensor data file
def read_sensor(path):
  value = "U"
  try:
    f = open(path, "r")
    line = f.readline()
    if re.match(r"([0-9a-f]{2} ){9}: crc=[0-9a-f]{2} YES", line):
      line = f.readline()
      m = re.match(r"([0-9a-f]{2} ){9}t=([+-]?[0-9]+)", line)
      if m:
        value = str(float(m.group(2)) / 1000.0)
    f.close()
  except (IOError), e:
    print time.strftime("%x %X"), "Error reading", path, ": ", e
  return value

# define pathes to 1-wire sensor data
pathes = (
  "/sys/bus/w1/devices/10-000801b5a7a6/w1_slave",
  "/sys/bus/w1/devices/10-000801b5959d/w1_slave"
)

# read sensor data
data = 'N'
for path in pathes:
  data += ':'
  data += read_sensor(path)
  time.sleep(1)

# insert data into round-robin-database
rrdtool.update(
  "%s/temperature.rrd" % (os.path.dirname(os.path.abspath(__file__))),
  data)

Das Auslesen von w1_slave erfolgt in der Funktion read_sensor. Sie testet zunächst, ob die erste Zeile mit YES endet und somit eine valide Prüfsumme existiert. Wenn ja, dann extrahiert die Funktion den Temperaturwert aus der zweiten Zeile der Datei und gibt den Wert in Grad Celsius zurück. Im Fehlerfall liefert sie dagegen den Wert U zurück, den RRDtool als »Unknown« interpretiert.

Im Hauptprogramm stehen als erstes die Definitionen der Pfade zu den Temperatursensoren - diese müssen Sie natürlich ändern! Dann liest das Script nacheinander alle Sensoren durch Aufruf der Funktion read_sensor aus. Die Wartezeit von einer Sekunde soll das Einschwingverhalten der parasitären Stromversorgung auf dem Datenbus verbessern. Am Ende erfolgt das Einfügen der Messwerte in die Round Robin Datenbank. Die Konstruktion des Pfades zur Datenbank geht davon aus, dass sich das Script und die Datenbank im gleichen Verzeichnis befinden.

Das Script speichert man in die ausführbare Datei gettemp.py und führt es per Kommandozeile aus. Das Ergebnis lässt sich mittels rrdtool lastupdate überprüfen. Das gibt den Zeitstempel und die Werte des letzten Datenbankupdates aus:

chmod +x gettemp.py
./gettemp.py
rrdtool lastupdate temperature.rrd 
 temp0 temp1

1386777156: 18.937 5.687

Damit man sich in Zukunft nicht immer am Raspberry Pi einloggen und die Kommandozeile bemühen muss, ist es sinnvoll, den Scriptaufruf in seine crontab einzutragen:

echo '2-57/5 * * * * $HOME/temperature/gettemp.py >> $HOME/temperature/gettemp.log 2>&1' | crontab -

Mit dieser Definition führt der cron Daemon alle fünf Minuten, beginnend mit der zweiten Minute nach der vollen Stunde, das Script aus. Eine Ausgabeumleitung schickt eventuelle Fehlermeldungen in die Datei gettemp.log. Da die Datenbank als kleinstes Messintervall 15 Minuten definiert, erfolgt somit eine Durchschnittsbildung über jeweils drei Messwerte.

Grafik und mehr

Haben Hard- und Software eine Zeit lang fleißig Temperaturmesswerte gesammelt, dann kann RRDtool nette Grafiken erzeugen, zum Beispiel den Temparaturverlauf der letzten Woche als Liniendiagramm visualisieren:

rrdtool graph tempweek.png \
  -s 'now - 1 week' -e 'now' \
  DEF:temp0=temperature.rrd:temp0:AVERAGE \
  LINE2:temp0#00FF00:Innen \
  DEF:temp1=temperature.rrd:temp1:AVERAGE \
  LINE2:temp1#0000FF:Außen
Temperatur in der letzten Woche
Mit rrdtool graph erzeugtes Diagramm der Temperatur der letzten Woche

Mehr zum Thema »Grafik mit RRDtool« bis hin zum Aufbau einer Webapplikation zur Präsentation der Daten finden Sie in den Artikeln Wetterdatenerfassung mit dem USB-WDE1 und Temperaturmessung mit dem Raspberry Pi.

Fazit

Das vorgestellte Projekt realisiert eine Temperaturmessstation auf Basis des Raspberry Pi mit minimaler externer Hardware. Die verwendete parasitäre Stromversorgung der Sensoren erfordert lediglich ein zweiadriges Kabel, jedoch dürfte die maximal mögliche Leitungslänge gegenüber einer aktiven Speisung eingeschränkt sein. Sind Temperaturen oberhalb von etwa 70° Celsius zu messen, dann sollte man auf jeden Fall eine aktive Stromversorgung mit einem dreiadrigen Kabel vorsehen. Die GPIO-Anschlüsse des Raspberry Pi sind ohne weitere Pufferung mit dem 1-wire Bus verbunden. Daher ist insbesondere die Einkopplung von Störspannungen durch parallel verlegte Stromleitungen unbedingt zu vermeiden! Beim Autor funktioniert die Lösung seit mehreren Wochen zuverlässig mit zwei Sensoren und einer Gesamtkabellänge von etwa zehn Metern.