====== Projekt DS18B20 digitaler Temperatursensor ======
[[python| ☚ zurück]]
//In diesem Projekt wird ein digitaler Temperaturfühler vom Typ DS18B20 am Raspberry Pi per 1-Wire-Schnittstelle betrieben. Nach Aktivierung der 1-Wire-Schnittstelle liefert der Kernel die Messwerte über das //Sysfs-Interface//. Ein Python-Modul liest diese Werte ein und gibt die aktuelle Temperatur in Grad Celsius auf der Kommandozeile aus.
//
====== Überblick ======
* Voraussetzungen
* 1-Wire aktivieren
* Hardware ansteuern
* Messprinzip
* Software
* Environment aktivieren
* Beispiel Programm
----
====== Details ======
===== Voraussetzungen =====
|{{ :raspberry_pi:wire-1.png?550 |}}|
| In ''raspi-config'' wird die 1-Wire-Schnittstelle aktiviert. Danach ist das Verzeichnis ''/sys/bus/w1/devices'' vorhanden. Hier erscheint dann der Sensor, falls er korrekt angeschlossen wurde.|
===== Hardware ansteuern =====
Der DS18B20 kommuniziert über die 1-Wire-Schnittstelle. Dabei erfolgt die gesamte Datenübertragung seriell über die DATA-Leitung (**GPIO4**) mit einem Pull-Up-Widerstand gegen 3.3 V.
|{{ :raspberry_pi:ds18b20.png?350 |}}|
| Für Einsteiger sind die //etwas teureren Fertigmodule// sinnvoller, da die benötigten Zusatzbauteile (hier insbesondere der 4,7 kΩ Pull-Up-Widerstand) bereits integriert sind. Dadurch kann der **DS18B20** mit nur drei Leitungen **(VCC, GND, DATA)** direkt angeschlossen und getestet werden.|
Verdrahtung:
^ Modul ^ Raspberry Pi GPIO ^
| GND | beliebigen GND |
| DATA | **GPIO4** (Pin 7) |
| VCC | **3.3 V ** |
**Wichtig**
Es kann nicht jeder beliebige GPIO-Pin verwendet werden. Standardmäßig ist dafür GPIO4 vorgesehen. Andere Pins müssen explizit über das Device-Tree-Overlay konfiguriert werden; dies wird hier nicht behandelt.
Beim DS18B20 gilt:
* Auflösung: 0,0625 °C (12 Bit)
* Genauigkeit: ±0,5 °C
* Messbereich −55 °C bis +125 °C
==== Messprinzip ====
Das Messprinzip ist unter Linux sehr einfach.
**Ein Programm muss lediglich die Datei ''w1_slave'' auslesen.**
|{{ :raspberry_pi:w1_device.png?600 |}}|
|Mit ''cat w1_slave'' kann die Temperatur ausgelesen werden. Hier entspricht **t=21500** einer Temperatur von **21.500 °C**. |
++++ Hintergrund |
Nach Aktivierung von 1-Wire über ''raspi-config'' stellt der Kernel die Temperatur als Datei im ''Sysfs'' bereit, z. B.: ''/sys/bus/w1/devices/28-000000714b90/w1_slave''
Der Name ''28-000000714b90'' ist die eindeutige ''64-Bit-ROM-ID'' des **DS18B20** und ist bei jedem Sensor unterschiedlich (Familiencode 28).
Die gesamte 1-Wire-Kommunikation übernimmt der Kernel.
* Bei jedem Lesezugriff auf diese Datei stößt der Kernel automatisch eine neue Temperaturumwandlung an.
* In der ersten Zeile signalisiert „YES“, dass die CRC-Prüfung erfolgreich war.
* In der zweiten Zeile steht der Temperaturwert hinter „t=“ in Milligrad Celsius.
++++
===== Software =====
=== Programmstruktur ===
|{{ :raspberry_pi:temperature_test.png?450 |}}|
|Im Projektordner „course_temp_reader“ befinden sich im Verzeichnis ''src'', die beiden Dateien „hardware.py“, welche den Sensor anspricht und den Temperaturwert ausliest, sowie das kleine Testprogramm „temp_reader.py“ als Demonstration.|
==== Environment aktivieren ====
**Aktiviere die Python-Environment**
Die Programmierung erfolgt nun immer mit der gewählten Umgebung!
source ~/devel/projects/course_env/bin/activate
==== DS18B20 API ====
Unsere Beispiel-API ist bewusst einfach gehalten und unterstützt hier nur einen einzelnen Sensor. Bei Bedarf kann die Implementierung problemlos auf mehrere Sensoren erweitert werden; darauf wird in diesem Projekt jedoch verzichtet.
import glob
import time
# -----------------------------
# API-Funktionen ds18b20
# -----------------------------
SENSOR_TIMEOUT = 1 # Sekunden
def is_sensor():
"""Prüft, ob mindestens ein DS18B20 Sensor angeschlossen ist"""
sensors = glob.glob("/sys/bus/w1/devices/28-*")
return len(sensors) > 0
def get_sensor():
"""Gibt den ersten DS18B20 Sensor zurück oder None"""
if not is_sensor():
return None
sensors = glob.glob("/sys/bus/w1/devices/28-*")
return sensors[0] + "/w1_slave"
def get_temperature():
"""Liest Temperatur vom ersten Sensor aus, None bei Fehler oder Timeout"""
sensor_file = get_sensor()
if sensor_file is None:
return None
start_time = time.time()
while True:
with open(sensor_file, "r") as f:
lines = f.readlines()
if lines[0].strip().endswith("YES"):
break
if time.time() - start_time > SENSOR_TIMEOUT:
return None
time.sleep(0.1)
temp_line = lines[1]
temp_str = temp_line.split("t=")[1]
return float(temp_str) / 1000.0
==== Temperature ====
#!/usr/bin/env python3
from hardware import get_temperature
def main():
temp = get_temperature()
if temp is not None:
print(f"Temperatur: {temp:.2f} °C")
else:
print("Sensor nicht gefunden!")
if __name__ == "__main__":
main()
==== Ausführen des Programms ====
Nach dem Programmstart wird auf der Kommandozeile die Temperatur in Grad Celsius ausgegeben, sofern der Sensor korrekt erkannt wurde und die Messung erfolgreich war.
cd ~/devel/projects/course_temp_reader/src
chmod 755 temp_reader.py
./temp_reader.py
# Beispielausgabe:
Temperatur: 21.25 °C