Raspberry Pi als Logging-Modul mit Datenbank und Webserver für Mikrocontroller

Beim Logging von Sensorwerten mit einem Mikrocontroller muss man mit verschiedenen Einschränkungen leben:
- fehlende Echtzeituhr
- begrenzter Speicher
- umständlichen Zugriff auf die Daten
- keine Auswertung der Daten möglich
Natürlich könnte man sich ein Programm schreiben oder schreiben lassen, dass über diese Leistungsmerkmale verfügt. Aber warum so umständlich, wenn es eine viel bessere Lösung gibt.
Wie wäre es, wenn die Daten in einer Datenbank gespeichert werden und über einen Webserver abrufbar wären.
Durch einen Raspberry Pi als Logging-Modul wird aus einer einfachen Messwert-Erfassung ein System mit Logging, Speicher, und einer Weboberfläche übers Netzwerk. Das kann ein Mikrocontroller alleine kaum leisten.
Anleitung: Raspberry Pi als Logging-Modul mit Datenbank und Webserver
- Betriebssystem aktualisieren und vorbereiten
- Systemkonfiguration
- Virtuelle Python-Umgebung einrichten
- Programmcode auf dem Raspberry Pi für das Logging
- Autostart-Service für das Logging einrichten
- Programmcode auf dem Raspberry Pi für den Webserver
- Autostart-Service für den Webserver einrichten
- Verkabelung mit dem Mikrocontroller
- Programm für den Raspberry Pi Pico (Beispiel)
Betriebssystem aktualisieren und vorbereiten
Nach dem Erzeugen einer frischen Speicherkarte mit Raspberry Pi OS, sollte man das Betriebssystem und die Software aktualisieren. Danach wird man das System vermutlich nie wieder aktualisieren.
sudo apt update sudo apt upgrade
Vorab installieren wir folgende Software:
sudo apt install libsystemd-dev python3-serial python3-systemd python3-pip
Systemkonfiguration
Im Konfigurationstool für den Raspberry Pi müssen wir noch ein paar Einstellungen vornehmen.
sudo raspi-config
Die serielle Schnittstelle muss eingeschaltet werden.
Im Menü hangelt man sich durch folgende Optionen: Interface Options / Serial Port
- Login shell over serial? NO
- Enable serial port hardware? YES
Hinweis: Der Login über die serielle Schnittstelle MUSS abgeschaltet (NO) sein, weil diese Schnittstelle sonst nicht genutzt werden kann.
Wenn man das Konfigurationstool beendet, dann wird normalerweise ein Reboot angeboten. Das ist sinnvoll.
Virtuelle Python-Umgebung einrichten
Für Python erstellen wir eine virtuelle Umgebung mit „venv“ (Virtual Environment), in die zusätzliche Python-Pakete installiert werden.
Zuerst legen wir in unserem Home-Verzeichnis „/home/pi“ ein Projektverzeichnis mit dem Namen „log“ an und wechseln dorthin.
mkdir /home/pi/log cd /home/pi/log
In diesem Verzeichnis erstellen wir eine virtuelle Python-Umgebung, in die wir anschließend alles installieren, ohne das System zu verändern.
python3 -m venv venv
Die Umgebung aktivieren:
source venv/bin/activate
Ab jetzt steht vor der Eingabeaufforderung „(venv)“.
Im nächsten Schritt installieren wir zusätzliche Pakete in die virtuelle Umgebung. Dafür verwenden wir pip (Package Installer for Python).
pip install pyserial flask
Danach können wir die virtuelle Umgebung wieder deaktivieren.
deactivate
Programmcode auf dem Raspberry Pi für das Logging
Das folgende Python-Programm macht 3 Dinge:
- Überwacht die serielle Schnittstelle.
- Erstellt bei Bedarf eine SQLite-Datenbank für die Daten.
- Speichert eingehende Daten mit einem Zeitstempel in der Datenbank.
Dazu öffnen wir eine neue Datei:
nano uart_log.py
In dem sich öffnenden Editor fügen wir folgenden Programmcode ein:
import serial
import sqlite3
from datetime import datetime
DB_NAME = '/home/pi/log/data.db'
# Datenbank
try:
conn = sqlite3.connect(DB_NAME)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME, data TEXT)''')
conn.commit()
except KeyboardInterrupt:
print("Logger gestoppt.")
finally:
conn.close()
# Serielle Schnittstelle initialisieren
ser = serial.Serial("/dev/serial0", 115200, timeout=1)
# Hauptprogramm
try:
while True:
line = ser.readline().decode("utf-8").strip()
if line:
print('Daten empfangen:', line)
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
conn = sqlite3.connect(DB_NAME)
cursor = conn.cursor()
cursor.execute("INSERT INTO logs (timestamp, data) VALUES (?, ?)", (now, line))
conn.commit()
conn.close()
print(f"Gespeichert: {now} - {line}")
except KeyboardInterrupt:
print("Logger gestoppt.")
finally:
ser.close()
Mit Strg + O, Return und Strg + X die Datei speichern und schließen.
Dann kannst du das Programm testweise starten:
venv/bin/python3 uart_log.py
Mit Strg + C kann man das Programm beenden.
Damit der Programmcode automatisch beim Systemstart gestartet wird, sollte eine systemd-Service-Unit eingerichtet werden, mit der man das Programm steuern kann.
Autostart-Service für das Logging einrichten
Hinweis: Den Service sollte man nur dann einrichten, wenn das Programm fehlerfrei funktioniert.
Dazu erstellen wir eine neue Datei:
sudo nano /etc/systemd/system/uart_log.service
Und tragen in diese Datei folgende Zeilen ein:
[Unit] Description=UART Logging Service (/dev/serial0) Requires=dev-serial0.device After=dev-serial0.device [Service] Type=simple User=pi ExecStart=/home/pi/log/venv/bin/python3 /home/pi/log/uart_log.py Restart=on-failure RestartSec=5 StartLimitBurst=5 [Install] WantedBy=multi-user.target
Mit Strg + O, Return und Strg + X die Datei speichern und schließen.
Den neu eingerichteten Service einlesen:
sudo systemctl daemon-reload
Danach kann man das Python-Programm als Service manuell starten und stoppen. Außerdem kann man den automatischen Start bei einem System-Neustart aktivieren.
Wichtige Kommandos zum Steuern
Service-Status anzeigen:
sudo systemctl status uart_log.service
Service starten:
sudo systemctl start uart_log.service
Service stoppen:
sudo systemctl stop uart_log.service
Service bei einem Neustart automatisch starten:
sudo systemctl enable uart_log.service
Automatischer Start abschalten:
sudo systemctl disable uart_log.service
Hinweis: Bevor man den Programmcode ändert, sollte man den Service immer stoppen und deaktivieren. Wenn man im Programmcode Mist baut und es deshalb zum Neustart kommt, dann kann das zu einer Reboot-Schleife führen, die sich nicht unterbrechen lässt.
Programmcode auf dem Raspberry Pi für den Webserver
Um die aufgezeichneten Daten per Webbrowser abrufen zu können, muss ein Webserver eingerichtet werden. Das kann man ganz bequem mit Python machen.
Dieser Webserver greift auf die Datenbank zu und zeigt die letzten 20 Einträge in einer einfachen Tabelle an.
Dazu öffnen wir eine neue Datei:
nano web_log.py
In dem sich öffnenden Editor fügen wir folgenden Programmcode ein:
from flask import Flask, render_template_string
import sqlite3
app = Flask(__name__)
DB_NAME = '/home/pi/log/data.db'
# Einfaches HTML-Template als String
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>
<title>UART Logger Dashboard</title>
<style><!--
body { font-family: sans-serif; margin: 40px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
th { background-color: #f4f4f4; }
tr:nth-child(even) { background-color: #fafafa; }
//--></style>
</head>
<body>
<h2>Letzte 20 Datensätze</h2>
<table>
<tr><th>ID</th><th>Zeitstempel</th><th>Datensatz</th></tr>
{% for row in rows %}
<tr><td>{{ row[0] }}</td><td>{{ row[1] }}</td><td>{{ row[2] }}</td></tr>
{% endfor %}
</table>
</body>
</html>
'''
@app.route('/')
def index():
conn = sqlite3.connect(DB_NAME)
cursor = conn.cursor()
# Die letzten 20 Einträge abrufen
cursor.execute("SELECT * FROM logs ORDER BY id DESC LIMIT 20")
rows = cursor.fetchall()
conn.close()
return render_template_string(HTML_TEMPLATE, rows=rows)
if __name__ == '__main__':
# Startet den Server auf Port 80, erreichbar im Netzwerk
app.run(host='0.0.0.0', port=80)
Mit Strg + O, Return und Strg + X die Datei speichern und schließen.
Dann kannst du das Programm testweise starten:
venv/bin/python3 web_log.py
Mit Strg + C kann man das Programm beenden.
Damit der Programmcode automatisch beim Systemstart gestartet wird, sollte eine systemd-Service-Unit eingerichtet werden, mit der man das Programm steuern kann.
Autostart-Service für den Webserver einrichten
Hinweis: Den Service sollte man nur dann einrichten, wenn das Programm fehlerfrei funktioniert.
Dazu erstellen wir eine neue Datei:
sudo nano /etc/systemd/system/web_log.service
Und tragen in diese Datei folgende Zeilen ein:
[Unit] Description=Flask App Service After=network.target [Service] ExecStart=/home/pi/log/venv/bin/python3 /home/pi/log/web_log.py Restart=on-failure RestartSec=5 StartLimitBurst=5 [Install] WantedBy=multi-user.target
Mit Strg + O, Return und Strg + X die Datei speichern und schließen.
Den neu eingerichteten Service einlesen:
sudo systemctl daemon-reload
Danach kann man das Python-Programm als Service manuell starten und stoppen. Außerdem kann man den automatischen Start bei einem System-Neustart aktivieren.
Wichtige Kommandos zum Steuern
Service-Status anzeigen:
sudo systemctl status web_log.service
Service starten:
sudo systemctl start web_log.service
Service stoppen:
sudo systemctl stop web_log.service
Service bei einem Neustart automatisch starten:
sudo systemctl enable web_log.service
Automatischer Start abschalten:
sudo systemctl disable web_log.service
Hinweis: Bevor man den Programmcode ändert, sollte man den Service immer stoppen und deaktivieren. Wenn man im Programmcode Mist baut und es deshalb zum Neustart kommt, dann kann das zu einer Reboot-Schleife führen, die sich nicht unterbrechen lässt.
Verkabelung mit dem Mikrocontroller

Die Darstellung sieht die Verkabelung von einen Raspberry Pi 3 und einem Raspberry Pi Pico vor. Das soll aber nur ein Beispiel sein. Es kann im Prinzip jeder Raspberry Pi und jeder Mikrocontroller sein.
- In diesem Beispiel wird der Raspberry Pi Pico über die GPIO-Pinleiste des Raspberry Pi mit Strom versorgt.
- Der ganze Aufbau funktioniert nur dann zuverlässig, wenn beide über eine gemeinsame Masse-Verbindung (GND) verbunden sind.
- Als einzige wirkliche Datenverbindung dient die Verbindung vom GPIO15 (Raspberry Pi UART-RX) nach GPIO0 (Raspberry Pi Pico UART-TX). Die Verbindung für den Rückweg brauchen wir nicht.
- Bei Mikrocontrollern, die 5-Volt-Pegel haben, muss man einen Pegelwandler (Logic Level Shifter) dazwischenschalten. Der Raspberry Pi verträgt nur einen 3,3-Volt-Pegel.
- Die Geschwindigkeit der Schnittstelle ist beim Raspberry Pi auf 115200 Baud eingestellt.
Programm für den Raspberry Pi Pico (Beispiel)
Der folgende Programmcode initialisiert die serielle Schnittstelle (UART) des Raspberry Pi Pico und sendet anschließend in einer Endlosschleife jede Minute die Temperatur des integrierten Temperaturfühlers über diese Schnittstelle.
# Bibliotheken laden
from machine import Pin, UART, ADC
import time
# Initialisierung des ADC4 (integrierter Temperatursensor)
sensor = ADC(4)
time.sleep(1)
# UART initialisieren
LOG = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
# Funktion: Text über UART senden
def logging(text):
print(text)
LOG.write(text)
# Hauptprogramm
while True:
# Sensor lesen
value = sensor.read_u16()
spannung = value * 3.3 / (65536)
temperatur = 27 - (spannung - 0.706) / 0.001721
logging(f"temp={temperatur}")
time.sleep(60)
Wenn man diesen Programmcode mit dem Dateinamen „main.py“ speichert, dann wird die Datei automatisch beim Neustart ausgeführt.
Wie erreicht man den Webserver?
Es gibt zwei Möglichkeiten:
- Über die IP-Adresse des Raspberry Pi.
- Über den Hostnamen des Raspberry Pi.
Über das folgende Kommando bekommt man die Informationen, welche Adresse man im Webbrowser in die Adresszeile eingeben muss und ob der Webserver gestartet ist.
sudo systemctl status web_log.service
Weitere verwandte Themen:
- Raspberry Pi als Logging-Modul für Mikrocontroller
- Python: Logging mit journald
- Raspberry Pi OS: Logging mit journald
Elektronik-Set Raspberry Pi Edition
Elektronik erleben mit dem Raspberry Pi mit Python und GPIO Zero
- Leichter Einstieg ins Hardware-nahe Programmieren mit Python und GPIO Zero
- Experimentieren und Programmieren ohne Vorkenntnisse
- Sofort Loslegen mit All-in-one-Set
Hardware-nahes Programmieren mit dem Raspberry Pi, Python und GPIO Zero
Das "Elektronik-Set Raspberry Pi Edition" ist ein Bauteile-Sortiment mit Anleitung zum Experimentieren und Programmieren mit Python und GPIO Zero.
- LED: Einschalten, ausschalten, blinken und Helligkeit steuern
- Taster: Verschiedene Zustände auswerten und anzeigen lassen
- LED mit Taster einschalten und ausschalten
- Relais-Board steuern
- LED, Relais-Board und Motor über ULN2003A steuern
- Ampel- und Lauflicht-Steuerung
- Herunterfahren per Taster
- Reaktionsspiel mit Tastern und LEDs
- Eigene Steuerungen programmieren
Elektronik-Fibel
Elektronik einfach und leicht verständlich
Die Elektronik-Fibel ist ein Buch über die Grundlagen der Elektronik, Bauelemente, Schaltungstechnik und Digitaltechnik.


