Wenn Sie mit dem Raspberry Pi den Stromverbrauch messen, wissen Sie genau, wie viel ein Stromkreis zieht, wie voll eine Batterie wird und wie viel Energie ein Gerät über den Tag verbraucht. In diesem Tutorial messen Sie Gleichspannung, Strom und Leistung mit einem INA219, integrieren die Werte zu Wattstunden und veröffentlichen alles als JSON über MQTT, damit ein Dashboard oder eine Automatisierung damit arbeiten kann. Außerdem sehen Sie, wie CT-Klemmen-HATs dieselbe Idee auf Wechselstromkreise übertragen.
Sensorwahl: INA219 oder CT-Klemme
| INA219-Breakout | CT-Klemmen-HAT | |
|---|---|---|
| Misst | Gleichspannung (bis 26 V), Strom, Leistung | Wechselstrom über eine Klemme; manche Boards erfassen auch die Wechselspannung |
| Anschluss | In Reihe mit der Last, über einen Shunt-Widerstand | Berührungslos, wird um einen Leiter geklemmt |
| Typischer Einsatz | Solarmodule, 12-V-Batterien, LED-Streifen, Roboter, der Pi selbst | Haushaltsstromkreise, Geräte, Maschinen |
| Schnittstelle | I2C | Meist SPI- oder I2C-ADC auf dem HAT |
| Sicherheit | Nur Kleinspannung | Klemme ist isoliert, die Installation in Netznähe gehört aber in Fachhände |
Dieses Tutorial baut die INA219-Variante komplett auf, denn sie ist günstig, für Gleichstrom-Kleinspannung genau und gefahrlos zum Experimentieren. Wenn Sie Wechselstrom brauchen, bringt ein CT-Klemmen-HAT seine eigene Python-Bibliothek mit; lesen Sie dessen Werte aus und übernehmen Sie den MQTT-Teil des Skripts unverändert. Das ESP32-Pendant für Netzstrom beschreibt die Anleitung zum ESP32-Stromsensor SCT-013.
So funktioniert der INA219
Der INA219 misst den kleinen Spannungsabfall über einem 0,1-Ohm-Shunt-Widerstand in Reihe mit Ihrer Last sowie die Busspannung auf der Lastseite. Aus diesen beiden Werten berechnet er intern Strom und Leistung. Das Standard-Breakout verkraftet bis zu 26 V am Bus und mit der Standardkalibrierung etwa 3,2 A. Weil der Shunt in Reihe liegt, fließt der gesamte Laststrom durch das Breakout. Bleiben Sie also innerhalb der Grenzwerte und verwenden Sie Leitungen, die für den Strom ausreichend dick sind.
Verdrahtung
| INA219-Pin | Verbinden mit |
|---|---|
| VCC | Pi 3,3 V (physischer Pin 1) |
| GND | Pi GND (physischer Pin 6) und Masse der Lastversorgung |
| SDA | GPIO2 (physischer Pin 3) |
| SCL | GPIO3 (physischer Pin 5) |
| VIN+ | Pluspol der Stromquelle |
| VIN- | Pluseingang der Last |
Die Masse des gemessenen Stromkreises muss mit der Masse des Pi verbunden sein, sonst ist der Messwert der Busspannung bedeutungslos. Aktivieren Sie I2C mit sudo raspi-config nonint do_i2c 0 und prüfen Sie mit i2cdetect -y 1, ob der Sensor unter Adresse 0x40 erscheint.
Software installieren
sudo apt update
sudo apt install -y python3-venv i2c-tools
mkdir -p ~/power-monitor && cd ~/power-monitor
python3 -m venv .venv
source .venv/bin/activate
pip install "paho-mqtt>=2.0" adafruit-circuitpython-ina219
Topics und Payload
| Topic | Inhalt | Retained |
|---|---|---|
connectmq/demo/8d20f6/solar/power |
Spannung, Strom, Leistung alle 5 s | Nein |
connectmq/demo/8d20f6/solar/energy |
Aufsummierte Wh, jede Minute | Ja |
connectmq/demo/8d20f6/solar/status |
online / offline |
Ja |
Eine Leistungsnachricht sieht so aus:
{"voltage": 12.84, "current_ma": 412.6, "power_w": 5.3, "ts": 1792161000}
Das Energie-Topic ist retained, damit ein später geöffnetes Dashboard sofort die heutige Summe sieht.
Das Skript zum Messen des Stromverbrauchs
Das Skript tastet einmal pro Sekunde ab, mittelt über das Veröffentlichungsintervall, um Rauschen zu glätten, und integriert die Leistung über die Zeit zu Wattstunden. Den Energiezähler speichert es alle zehn Minuten auf die Festplatte, damit ein Neustart ihn nicht zurücksetzt, ohne bei jedem Messwert auf die SD-Karte zu schreiben. Speichern Sie es als power_monitor.py:
#!/usr/bin/env python3
"""INA219 power monitor publishing to MQTT."""
import json
import os
import time
import uuid
from pathlib import Path
import board
import paho.mqtt.client as mqtt
from adafruit_ina219 import INA219
BROKER = os.getenv("MQTT_HOST", "broker.connectmq.com")
PORT = int(os.getenv("MQTT_PORT", "1883"))
USERNAME = os.getenv("MQTT_USERNAME")
PASSWORD = os.getenv("MQTT_PASSWORD")
CLIENT_ID = os.getenv("MQTT_CLIENT_ID", f"power-{uuid.uuid4().hex[:8]}")
PREFIX = os.getenv("MQTT_PREFIX", "connectmq/demo/8d20f6/solar")
PUBLISH_EVERY = 5 # Sekunden
ENERGY_EVERY = 60 # Sekunden
SAVE_EVERY = 600 # Sekunden
STATE_FILE = Path(os.getenv("STATE_FILE", "energy_wh.txt"))
ina = INA219(board.I2C()) # Standardkalibrierung: Bereich 32 V, 2 A
def load_energy():
try:
return float(STATE_FILE.read_text())
except (OSError, ValueError):
return 0.0
def save_energy(wh):
tmp = STATE_FILE.with_suffix(".tmp")
tmp.write_text(f"{wh:.4f}")
tmp.replace(STATE_FILE) # atomares Umbenennen verhindert halb geschriebene Dateien
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print(f"Connection refused: {reason_code}")
return
print(f"Connected as {CLIENT_ID}")
client.publish(f"{PREFIX}/status", "online", qos=1, retain=True)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.will_set(f"{PREFIX}/status", "offline", qos=1, retain=True)
client.reconnect_delay_set(min_delay=1, max_delay=60)
if USERNAME:
client.username_pw_set(USERNAME, PASSWORD)
if PORT == 8883:
client.tls_set()
client.connect(BROKER, PORT, keepalive=30)
client.loop_start()
energy_wh = load_energy()
samples = []
last_sample = time.monotonic()
last_publish = last_energy = last_save = last_sample
try:
while True:
time.sleep(1)
now = time.monotonic()
voltage = ina.bus_voltage + ina.shunt_voltage # Spannung auf der Versorgungsseite
current_ma = ina.current
power_w = ina.power
if ina.overflow:
print("Warning: INA219 overflow, current exceeds calibrated range")
energy_wh += power_w * (now - last_sample) / 3600.0
last_sample = now
samples.append((voltage, current_ma, power_w))
if now - last_publish >= PUBLISH_EVERY:
n = len(samples)
payload = {
"voltage": round(sum(s[0] for s in samples) / n, 2),
"current_ma": round(sum(s[1] for s in samples) / n, 1),
"power_w": round(sum(s[2] for s in samples) / n, 2),
"ts": int(time.time()),
}
client.publish(f"{PREFIX}/power", json.dumps(payload), qos=0)
samples.clear()
last_publish = now
if now - last_energy >= ENERGY_EVERY:
energy = {"energy_wh": round(energy_wh, 3), "ts": int(time.time())}
client.publish(f"{PREFIX}/energy", json.dumps(energy), qos=1, retain=True)
last_energy = now
if now - last_save >= SAVE_EVERY:
save_energy(energy_wh)
last_save = now
except KeyboardInterrupt:
pass
finally:
save_energy(energy_wh)
client.publish(f"{PREFIX}/status", "offline", qos=1, retain=True).wait_for_publish(2)
client.loop_stop()
client.disconnect()
Starten Sie es mit python power_monitor.py und abonnieren Sie von einem anderen Rechner aus:
mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-8d20f6 \
-t 'connectmq/demo/8d20f6/solar/#' -v
Schalten Sie die Last ein und aus und beobachten Sie, wie current_ma und power_w innerhalb von fünf Sekunden reagieren.
Kalibrierung und Genauigkeit
Die Standardkalibrierung deckt 32 V und 2 A mit brauchbarer Auflösung ab. Ist Ihre Last klein, etwa ein Mikrocontroller mit einigen zehn Milliampere, rufen Sie nach dem Anlegen des Sensors ina.set_calibration_16V_400mA() für eine feinere Auflösung auf. Brauchen Sie mehr als den Bereich des Breakouts, ersetzen Sie den Shunt durch einen niedrigeren Wert und schreiben Sie eine eigene Kalibrierung, oder wechseln Sie zu einem Sensor für höhere Ströme.
Prüfen Sie die Werte mit einem Multimeter in Reihe zur Last. Kleine Offsets sind normal; ein gleichbleibender prozentualer Fehler deutet meist auf die Shunt-Toleranz hin, die Sie per Skalierungsfaktor in der Software korrigieren können. Ein negativer Strom bedeutet, dass VIN+ und VIN- vertauscht sind, was sogar nützlich sein kann: Ein Batteriemonitor kann über das Vorzeichen Laden und Entladen unterscheiden.
Anwendungsfälle
Dasselbe Skript passt zu vielen Projekten; nur Topic-Präfix und Kalibrierung ändern sich. Weil Abonnenten nur JSON mit Feldern für Spannung, Strom, Leistung und Energie sehen, können Sie den Sensor später austauschen oder einen zweiten INA219 unter Adresse 0x41 für einen weiteren Stromkreis ergänzen, ohne das Dashboard oder die Automatisierung anzufassen, die die Daten verarbeitet.
- Solar- und Batteriesysteme: Moduleistung und Batteriespannung verfolgen und einen Alarm veröffentlichen, wenn die Batterie unter einen sicheren Wert fällt.
- Eigene Pi- oder ESP32-Projekte vermessen: den INA219 zwischen Versorgung und Gerät setzen, um den realen Verbrauch bei WLAN-Spitzen und im Schlafmodus zu sehen.
- Roboter und Fahrzeuge: Motorstrom überwachen, um Blockaden zu erkennen.
- 12-V-Beleuchtung und Pumpen: bestätigen, dass eine Last tatsächlich eingeschaltet hat und nicht nur ein Relais geklickt hat.
Für die Überwachung eines ganzen Hauses mit CT-Klemmen und Langzeitdiagrammen zeigt unser Artikel zum Energiemonitor für zu Hause mit MQTT die Abonnentenseite, und die Anleitung Raspberry Pi mit Grafana und InfluxDB speichert die Werte über Monate. Bei knappem Energiebudget läuft dasselbe Skript gut auf einem Raspberry Pi Zero 2 W als MQTT-Knoten. In der Werkhalle lassen sich so auch Kleinspannungsverbraucher an Maschinen erfassen und als Teil des Energiemonitorings bereitstellen.
Vom Labortisch zur festen Installation
Auf dem öffentlichen MQTT-Broker unter broker.connectmq.com kann jeder Ihre Topics mitlesen. Für einen Test am Labortisch ist das in Ordnung, in einer echten Wohnung oder Werkstatt verrät es jedoch Nutzungsmuster. Wechseln Sie vor der festen Installation auf einen privaten Broker mit TLS. Mit ConnectMQ erhalten Sie generierte Zugangsdaten pro Gerät; setzen Sie MQTT_PORT=8883 sowie MQTT_USERNAME=YOUR_USERNAME, MQTT_PASSWORD=YOUR_PASSWORD und MQTT_CLIENT_ID=YOUR_CLIENT_ID in einer systemd-Umgebungsdatei und starten Sie neu. Legen Sie anschließend im ConnectMQ-Portal eine Schwellwert-Alarmregel an, zum Beispiel Spannung unter 11,8 V auf dem Leistungs-Topic, damit Sie gewarnt werden, bevor eine Batterie Schaden nimmt.
Wenn Sie noch nicht wissen, was ein MQTT-Broker macht oder wie man ein Skript als Dienst ausführt, beginnen Sie mit dem Raspberry Pi MQTT Tutorial und kehren danach zu diesem Aufbau zurück.
Fehlerbehebung
ValueError: No I2C device at address: 0x40: SDA und SCL prüfen, I2C aktivieren undi2cdetect -y 1ausführen.- Spannung liegt nahe null: VIN+ oder VIN- ist nicht mit dem gemessenen Stromkreis verbunden, oder die Massen sind nicht verbunden.
- Stromwerte schwanken stark: wie im Skript über das Veröffentlichungsintervall mitteln und die Shunt-Leitungen kurz halten.
- Energiesumme wird nach dem Neustart zurückgesetzt: Die Zustandsdatei ist nicht beschreibbar, oder das Skript wurde vor dem Speichern beendet; Berechtigungen des Arbeitsverzeichnisses prüfen.
Starten Sie mit ConnectMQ
Senden Sie Ihre Energiedaten an einen Cloud-MQTT-Broker, den Dashboards und Alarme von überall erreichen. Erstellen Sie Ihren kostenlosen ConnectMQ-Broker im Serverless-Plan, ohne Kreditkarte, und verbinden Sie sich per TLS mit MQTT 3.1.1 oder 5.0. Der Live-Topic-Explorer zeigt jeden Messwert, sobald er eintrifft.
Häufig gestellte Fragen
Kann ein INA219 Netzwechselstrom messen?
Nein. Der INA219 ist ein Gleichstromsensor für bis zu 26 V. Verwenden Sie für Wechselstromkreise einen CT-Klemmen-HAT oder einen zertifizierten Energiezähler und lassen Sie Arbeiten am Netz von einer Elektrofachkraft durchführen.
Wie genau misst ein Raspberry Pi mit INA219 den Stromverbrauch?
Nach einem Abgleich mit einem Multimeter genau genug für die meisten Hobby- und Überwachungsaufgaben. Die Shunt-Toleranz ist die Hauptfehlerquelle und lässt sich mit einem Skalierungsfaktor korrigieren.
Warum wird die Energie als Retained Message veröffentlicht?
Damit jedes Dashboard und jeder Abonnent, der sich später verbindet, sofort die aktuelle Summe erhält, statt bis zu einer Minute auf das nächste Update zu warten.
Wie oft sollte ich Leistungswerte veröffentlichen?
Alle paar Sekunden genügt für Dashboards. Tasten Sie lokal schneller ab, bilden Sie den Mittelwert und veröffentlichen Sie diesen, um den Datenverkehr gering zu halten.



