Benutzer-Werkzeuge

Webseiten-Werkzeuge


projekt:python_ds18b20_logger

Dies ist eine alte Version des Dokuments!


DS18B20 – Temperaturdaten loggen und visualisieren

☚ zurück

In diesem Projekt wird ein Temperatur-Logger mit dem digitalen 1-Wire-Sensor DS18B20 am Raspberry Pi realisiert. Ergänzend zur reinen Temperaturauslese werden Messwerte kontinuierlich in einer Textdatei protokolliert und aus diesen Daten automatisch ein Temperaturverlauf als Grafik erzeugt. Der Logger lässt sich über ein Kommandozeilen-Interface steuern und speichert Messdaten sowie Diagramm lokal oder zur Anzeige im Webserver-Verzeichnis.

Überblick

  • Voraussetzungen
    • Hardware
    • Environment
    • Programmstruktur anlegen
  • Software
    • Quellcode
    • Webseite

Details

Voraussetzungen

Das Projekt DS18B20 digitaler Temperatursensor muss zuvor vollständig durchgeführt und erfolgreich getestet worden sein. Da hier dieselbe Hardware verwendet wird, sind damit alle Voraussetzungen bereits erfüllt.

Environment

Aktiviere die Python-Environment

Die Programmierung erfolgt nun immer mit der gewählten Umgebung!

source ~/devel/projects/course_env/bin/activate

Pakete & Bibliotheken installieren

Jetzt die ENV aktivieren (falls noch nicht geschehen) und dann erst installieren:

pip install matplotlib

Programmstruktur

(course_env) pi@raspi88:~/devel/projects/course_temp_curve $ tree
.
├── data
│   ├── temperature.png       # wird automatisch erstellt
│   └── temperature.txt       # wird automatisch erstellt
└── src
    ├── core
    │   ├── hardware.py       # aus dem vorherigen Projekt! 
    │   ├── __init__.py
    │   └── temperature_logger.py  # Program
    └── temp_curve.py

Software

Im folgenden Abschnitt wird die vollständige Software zur Datenerfassung, Speicherung und grafischen Darstellung der Temperaturwerte beschrieben.

Quellcode

hardware.py

Die Datei hardware.py (API) bleibt unverändert und wird hier der Vollständigkeit halber erneut vollständig aufgeführt.

hardware.py
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_logger.py

In der Datei temperature_logger.py kann die Variable MODE die Werte local oder web annehmen.

  • local Das erzeugte Bild wird im lokalen Projektverzeichnis gespeichert.
  • web Das erzeugte Bild wird im Webverzeichnis gespeichert und kann über den Webserver angezeigt werden.
Hinweis

Die dafür notwendigen Voraussetzungen wurden bereits in einem vorherigen Projekt (DokuWiki) geschaffen: Der Benutzer pi ist Mitglied der Gruppe www-data. Dadurch besitzt er die erforderlichen Schreibrechte, um die Datei in das angegebene Webverzeichnis zu speichern.

temperature_logger.py
import time
import threading
from datetime import datetime
from pathlib import Path
 
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
 
from core.hardware import get_temperature
 
 
# MODE = "local" oder "web"
MODE = "local"
 
if MODE == "local":
    DATA_DIR = Path("~/devel/projects/course_temp_curve/data").expanduser()
elif MODE == "web":
    DATA_DIR = Path("/var/www/html/temp_curve").expanduser()
else:
    raise ValueError("MODE muss 'local' oder 'web' sein")
 
 
DATA_DIR.mkdir(parents=True, exist_ok=True)
DATA_FILE = DATA_DIR / "temperature.txt"
PLOT_FILE = DATA_DIR / "temperature.png"
 
INTERVAL = 5  # Sekunden (Auflösung / Messintervall)
 
running = False
thread_started = False
lock = threading.Lock()
 
 
def set_interval(seconds: int):
    global INTERVAL
    if seconds < 1:
        seconds = 1
    INTERVAL = seconds
 
 
def generate_plot():
    times = []
    temps = []
 
    if DATA_FILE.exists():
        with open(DATA_FILE, "r") as f:
            for line in f:
                parts = line.strip().split()
                if len(parts) == 2:
                    times.append(parts[0])
                    temps.append(float(parts[1]))
 
    plt.figure()
    plt.title("Temperaturverlauf")
    plt.xlabel("Zeit")
    plt.ylabel("Temperatur (°C)")
 
    if temps:
        plt.plot(times, temps)
        plt.xticks(rotation=45)
    else:
        plt.text(
            0.5,
            0.5,
            "Keine Messdaten",
            ha="center",
            va="center",
            transform=plt.gca().transAxes,
        )
 
    plt.tight_layout()
    plt.savefig(PLOT_FILE)
    plt.close()
 
 
def worker():
    global running
 
    while True:
        with lock:
            active = running
            interval = INTERVAL
 
        if active:
            temp = get_temperature()
            if temp is not None:
                now = datetime.now().strftime("%H:%M:%S")
 
                with open(DATA_FILE, "a") as f:
                    f.write(f"{now} {temp}\n")
 
                generate_plot()
 
            time.sleep(interval)
        else:
            time.sleep(0.2)
 
 
def ensure_thread():
    global thread_started
    if not thread_started:
        t = threading.Thread(target=worker, daemon=True)
        t.start()
        thread_started = True
 
 
def start():
    ensure_thread()
    global running
    with lock:
        running = True
 
 
def stop():
    global running
    with lock:
        running = False
 
 
def reset():
    stop()
    DATA_FILE.write_text("")
    generate_plot()

Hauptprogramm

Das eigenständige Programm temp_curve.py dient als Kommandozeilen-Interface zur Steuerung des Temperatur-Loggers.

Es ermöglicht das Starten und Stoppen der Messung, das Setzen des Messintervalls sowie das Zurücksetzen der gespeicherten Daten.

Während der Laufzeit werden die erfassten Messwerte in die Datei data/temperature.txt geschrieben. Zusätzlich wird nach jeder Messung automatisch eine Grafik (data/temperature.png) erzeugt bzw. aktualisiert, die den Temperaturverlauf darstellt.

Quellcode ''temp_curve.py''

projekt/python_ds18b20_logger.1771754935.txt.gz · Zuletzt geändert: von torsten.roehl