de|en

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

Martin Kompf

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).

1, 2 oder 3 Drähte?

Die Bezeichnung 1-wire ist natürlich irreführend. Es ist mindestens noch eine zweite Leitung für das Bezugspotential GND notwendig. 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.

Es ist aber auch möglich, den DS1820 mit einer aktiven Stromversorgung zu betreiben. Dazu benötigt man dann eine dreiadrige Leitung, die zusätzlich VDD mit der Betriebsspannung von 3 bis 5 Volt verbindet.

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

Die Entscheidung, ob man parasitäre oder aktive Stromversorgung wählt, sollte man vor Beginn des Projektes treffen und sich sehr genau überlegen. Für die parasitäre Speisung spricht der geringere Materialaufwand für das zweiadrige Kabel. Allerdings kann es hier zu Problemen bei vielen parallelen Sensoren am Bus, hohen Temperaturen und langen Leitungen kommen. Auch gab und gibt es manchmal Probleme mit bestimmten Versionen des 1-wire Kerneltreibers unter Linux aufgrund des bei parasitärer Speisung kritischeren Timings.

Im Zweifelsfall und bei hohen Anforderungen an die Zuverlässigkeit würde ich mich immer für eine aktive Speisung und dem dafür notwendigen dreiadrigen Kabel entscheiden.

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.

Passive parasitäre Speisung (zweiadriges Kabel)

Stromlaufplan Anschluss DS1820 an GPIO
Anschluss des DS18020 an den GPIO Port des Raspberry Pi mit parasitärer Speisung (zweiadriges Kabel)

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 Widerstand von 4,7 k zwischen dem 3,3 Volt Anschluss 3V3 und GPIO4.

Aktive Speisung (dreiadriges Kabel)

Stromlaufplan Anschluss DS1820 an GPIO (aktive Speisung)
Anschluss des DS18020 an den GPIO Port des Raspberry Pi mit aktiver Speisung (dreiadriges Kabel)
Zusatzplatine mit Steckverbinder
Auf der Lochrasterplatte ist noch jede Menge Platz für Erweiterungen

Den Datenanschluss DQ des DS1820 verbindet man auch hier direkt mit dem Anschluss GPIO4 der GPIO-Schnittstelle des Raspberry Pi. GND liegt am Masseanschluss GND, wogegen VDD mit dem 3,3 Volt Anschluss 3V3 verbunden ist. Der Widerstand zwischen 3V3 und GPIO4 dient jetzt lediglich als Pullup-Widerstand zur Einstellung eines definierten Potentials auf der Datenleitung.

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 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 Raspberry Pi OS.

Zunächst ist die Aktivierung des Device Tree Overlay für 1-wire notwendig. 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

Der Parameter pullup=on ist nur bei parasitärer Speisung notwendig, bei aktiver Stromversorgung (3-Draht) lautet die Zeile dementsprechend:

dtoverlay=w1-gpio,gpiopin=4

Nach dem erforderlichen Reboot vergewissert man sich mittels des Kommandos lsmod, ob die erforderlichen Kernelmodule w1_gpio und w1_therm geladen sind:

lsmod | grep w1

w1_therm               20480  0
w1_gpio                16384  0
wire                   36864  2 w1_gpio,w1_therm

Ist das nicht der Fall, dann muss man die Module manuell laden. Bei älteren Versionen von Raspbian OS war dies noch regelmäßig erforderlich:

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

Auch hier ist der Parameter pullup=1 nur bei einer parasitären Speisung notwendig. Damit der Kernel die Module in Zukunft automatisch beim Systemstart lädt, sollte man sie jetzt noch in die Datei /etc/modules eintragen:

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

Wie gesagt, das ist nur bei älteren Versionen von Raspbian notwendig, beim aktuellen Raspberry Pi OS lädt der Kernel die Module selbständig, wenn die oben gezeigte dtoverlay Option in der config.txt 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.

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 installiert man RRDtool unter Zuhilfenahme des Packagemanagers auf dem Raspberry Pi:

sudo apt install rrdtool python-rrdtool

Python 2 oder 3?
Das zweite installierte Paket python-rrdtool ist das Python 2 Interface für RRDtool, welches später zur Anwendung kommt. In der aktuellen Raspberry Pi OS Version basierend auf Debian bullseye gibt es das Paket nicht mehr. Außerdem ist hier explizit festzulegen, ob Python in der Version 2 oder 3 der Standardinterpreter ist. Daher sollte man in dieser Situation die Pakete python3-rrdtool und python-is-python3 installieren.

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 as 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. Eine 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 vielen Jahren zuverlässig mit zwei Sensoren und einem zweiadrigen Kabel von etwa zehn Metern Länge.