Endlich ist es soweit: Ich lese den Stromverbrauch von unserer Wohnung mit einem Raspberry Pi aus und lasse mir von meinem Monitoring Server (MRTG + Routers2) schöne Graphen malen. Hierfür verwende ich einen Stromzähler mit einer S0-Schnittstelle, welchen ich direkt in der Unterverteilung eingebaut habe. Die Impulse des “Smart Meters” wertet eine Interruptroutine am Pi aus. Der Monitoring Server wiederum fragt den Pi per SNMP ab. Viele kleine Schritte also, die ich in diesem Blogpost ausführlich erläutern möchte. Viel Spaß damit!
Die Idee
Folgenden “Pfad” nehmen die Stromdaten vom Zähler bis zum Monitoring System:
- Der Stromzähler (3 Phasen) erzeugt 800 Impulse pro kWh und gibt diese an einer S0-Schnittstelle aus. Sprich: Ein Optokoppler, der bei jedem Impuls kurzschließt.
- Mit zwei Adern geht’s dann zum Raspberry Pi, welcher einfach nur eine Textdatei mit einem Counter bei jedem Impuls um eins hoch setzt. (Der Interrupt löst ein kleines Programm aus, welches die Datei beschreibt.)
- Der bereits vorhandene Monitoring Server fragt schlussendlich den Pi per SNMP ab, sprich: es wird ein zusätzlich Skript gestartet, welches einfach den Inhalt der Textdatei ausgibt und in einer OID per SNMP transportiert.
Die Hardware
Hier ein paar Bilder von der Hardware. Ich habe einen Drehstromzähler von Eltako gekauft, genaue Bezeichnung: DSZ12E-3x80A. Kostenpunkt: ca. 90,- €. Dieser Stromzähler ist NACH dem geeichten und offiziellen Stromzähler der Stadtwerke im Keller eingebaut. Somit gibt es keine Probleme mit der Stromabrechnung. Mit einer Standard Telefon-Doppelader (oben rechts im Bild, gelb und weiß aus dem Sicherungskasten) geht die S0-Schnittstelle dann an den Raspberry Pi.
Die Software
Eine erste Googelei hatte mich auf ein Projekt von volkszaehler mit dem Artikel S0-Impuls Zähler direkt über RS232 auswerten gebracht. Dabei bin ich der Anleitung in dem grünen Kasten, der speziell für den Raspberry Pi gedacht ist, gefolgt. Also den GPIO Port auf die Alternative Funktion 3 umbiegen und dann die
sttyund
straceBefehle. Leider hatte das nicht funktioniert. Und da ich nicht genügend Lust hatte, ewig weiter zu testen, habe ich eben weiter gegoogelt.
S0-Auswertung am Pi
Erfreulicherweise bin ich dann über den Artikel S0-Stromzähler am RaspberryPi gestoßen, welcher exakt das beschreibt, was ich vor hatte. Und das hat sogar ziemlich einfach funktioniert. Juchu! Also:
- S0+ und S0- an die richtigen Ports anschließen (gar nicht so einfach, da die Benennung der GPIO-Ports variiert und ungleich der Zählung der Anschlüsse auf dem Pi ist, sowie die Zählung der Ports für Wiring Pi noch mals verschieden ist). Bei mir ist es folgendermaßen: Stromzähler Pin 20 = S0+ (weißes Kabel) = GPIO 3 -> Pin 5, sowie: Stromzähler Pin 21 = S0- (gelbes Kabel) = GND -> Pin 6. Uff.
- Wiring Pi per git clonen.
- Die ISR.c Datei mit dem richtigen #define kompilieren. (Bei mir ist es
#define BUTTON_PIN 9
). Achtung: Nicht die isr.c Datei in dem Unterordner “examples” von Wiring Pi verwenden, sondern die, die hinter dem Link steckt.
Um aber den Zählerstand korrekt in eine Datei zu schreiben, muss die C Datei noch etwas angepasst werden (Link: Datei schreiben): Im main Bereich noch eine Variable deklarieren:
FILE *datei;und dann anstelle der printf Ausgabe folgendes hinzufügen, damit der aktuelle Counter-Wert in die Datei geschrieben wird:
// printf (" Done. counter: %5d\n", globalCounter) ; datei = fopen ("/var/strom/stromcounter", "w"); fprintf (datei, "%d\n", globalCounter); fclose (datei);
Ich habe dann noch einen Ordner für die Logdatei erstellt:
sudo mkdir /var/strom, das Programm kompiliert:
gcc -lwiringPi -o stromzaehler stromzaehler.cund verschoben:
sudo mv stromzaehler /usr/local/bin/. Per
sudo stromzaehlerlief es dann.
Nun muss das Programm noch per Autostart beim Booten vom Pi ausgeführt werden (Link: Dienste). Dabei habe ich mich an diese Anleitung gehalten. Folgende Datei habe ich als “/etc/init.d/stromzahler” angelegt (
sudo nano /etc/init.d/stromzaehler):
#! /bin/sh ### BEGIN INIT INFO # Provides: Stromzaehler starten: S0-Schnittstelle per ISR auswerten und Textdatei schreiben # Required-Start: # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Kurze Beschreibung # Description: Längere Bechreibung ### END INIT INFO # Author: Johannes Weber (johannes@webernetz.net) # Aktionen case "$1" in start) /usr/local/bin/stromzaehler & # /opt/beispiel start ;; stop) killall stromzaehler # /opt/beispiel stop ;; restart) killall stromzaehler /usr/local/bin/stromzaehler & # /opt/beispiel restart ;; esac exit 0
Und dann (wie in dem Link beschrieben) erst die Rechte auf die Datei korrekt vergeben, damit sie ausführbar ist:
sudo chmod 755 stromzaehler, und den Runlevel für das automatische Ausführen beim Booten hinzufügen:
sudo update-rc.d stromzaehler defaults. (Jetzt befindet sich unter anderem im Ordner /etc/rc2.d ein symbolischer Link mit dem Namen “S01stromzaehler” auf die eben erstellte stromzaehler Datei im init.d Ordner.)
Mit den folgenden Befehlen kann man nun den Service stoppen, starten, oder restarten (wobei das gar nicht nötig ist, da er ja beim Booten automatisch startet und immerzu laufen soll) [Außerdem stelle ich gerade fest, dass der "restart" gar nicht richtig funktioniert. Der Dienst wird zwar abgeschossen, aber nicht wieder gestartet. Hm. Egal, ich will ja nur, dass es beim Booten automatisch läuft]:
sudo service stromzaehler stop sudo service stromzaehler start sudo service stromzaehler restart
Den aktuellen Stromzählerwert (Erinnerung: 800 Impulse/kWh) bekommt man so:
cat /var/strom/stromcounter
LÄUFT! Juchu.
(Wen es übrigens noch genauer interessiert: Ich finde den Unterschied der beiden von mir verlinkten Programme interessant: Während das erstere einfach Spannung an die S0-Schnittstelle anlegt und dann auf der anderen Leitung misst, wann Spannung ankam, verwendet das zweite Projekt einen Interrupt per Pull-Down. Sprich: Es liegt konstant Spannung an, und per S0-Schnittstelle wird diese Spannung auf 0 gezogen. Während bei erstem also der zweite Pin eine Spannung wahrnimmt, registriert der Pi bei zweiterem den Spannungsverlust am ersten Pin.)
Auslesen via SNMP
Um auf den Inhalt der Textdatei via SNMP zuzugreifen muss lediglich ein extended Skript in der snmpd.conf eingebunden werden. Dies hatte ich bei meinem Temperatursensor genau so schon mal gemacht. Also bitte dort für weitere Details nachlesen. Hier nur kurz die Anleitung:
Konfigurationsdatei auf dem Pi öffnen:
sudo nano /etc/snmp/snmpd.confund unter “EXTENDING THE AGENT” folgende Zeile hinzufügen:
extend-sh stromcounter cat /var/strom/stromcounter
Danach den snmpd service neustarten:
sudo service snmpd restart. Unter welcher OID der Wert dann steht findet man z.B. mit snmpwalk oder dem von mir schon oft angepriesenen iReasoning MIB Browser heraus.
Einbinden in MRTG
Hier die Konfigurationszeilen für MRTG und Routers2.cgi. Als Farbe habe ich mich für ein sattes Schwarz entschieden. Dies hatte ich noch nirgends anders verwendet und irgendwie passt es auch zur Erzeugung des Stroms durch Kohle.
routers.cgi*Icon: house-sm.gif routers.cgi*ShortDesc: Stromverbrauch #OID per snmpwalk herausgefunden Target[strom-fdorf]: 1.3.6.1.4.1.8072.1.3.2.4.1.2.12.115.116.114.111.109.99.111.117.110.116.101.114.1&PseudoZero:d83lykUUdiqhdz@192.168.86.5:::::2 #800 Impulse pro kWh -> MaxBytes (pro Sekunde) auf 5 gesetzt = 3600*5/800 entspricht 22,5 kW (das sollte reichen ;)) MaxBytes[strom-fdorf]: 5 Title[strom-fdorf]: Stromverbrauch Friedrichsdorf #Gespeichert wird in Raw, also 800 Impulse pro kWh. Anzeige aber in Wh, daher mal 1.25. Somit entspricht einem faktorisiertem Impuls genau 1 Wh. Factor[strom-fdorf]: 1.25 #Ausgabe aber immer in Leistung pro Stunde (und nicht pro Sekunde) Options[strom-fdorf]: perhour Colours[strom-fdorf]: BLACK#000000, YELLOW#FFD600, RED#FF0000, ORANGE#FC7C01 YLegend[strom-fdorf]: Watt Legend1[strom-fdorf]: Leistung Legend3[strom-fdorf]: Peak Leistung LegendI[strom-fdorf]: Leistung: ShortLegend[strom-fdorf]: W routers.cgi*Options[strom-fdorf]: nomax noo routers.cgi*TotalLegend[strom-fdorf]: Wh routers.cgi*ShortDesc[strom-fdorf]: Fdorf #Kommentar unter jedem Graph, weil ich mir das sonst nicht merken kann: routers.cgi*Comment[strom-fdorf]: 1x Peak Waschmaschine, 2x Peak Spülmaschine
An dieser Stelle sei noch erwähnt, dass MRTG lediglich alle 5 Minuten per SNMP den Zählerstand vom Pi holt. Sprich: Es wird immer nur der Durchschnittswert der letzten 5 Minuten gespeichert. Ein ernsthafter Peak im Stromverbrauch von beispielsweise 5 kW über eine Minute würde doch nur als 1 kW über 5 Minuten angezeigt werden. Aber gut, damit kann ich leben.
Das Ergebnis
Hier drei Beispielgraphen von meinem Monitoring Server. Die ersten beiden in der “Daily” Ansicht und mit ein paar Infos zu den verwendeten Stromverbrauchern. Der letzte dann in der “Monthly” Ansicht mit der roten Kennlinie für die Peaks und dem schwarzen Block weiterhin für den Durchschnitt. Man sieht schön, in welcher Woche wir im Urlaub waren und an welchen Tagen weder Spül- noch Waschmaschine liefen, da kein Peak über 1 kW geht. (Leider sieht man auch, an welchen Tagen ich den Pi aus Versehen nicht am Laufen hatte. Pech.)
Die Zukunft
Tja, also konsequent wäre es jetzt noch, die Wasserzähler auch gegen solche mit S0-Schnittstelle auszutauschen. Leider ist das alles andere als einfach. Entweder müsste man einen geeichten/offiziellen Zähler einbauen lassen (was teuer wäre), oder man müsste einen zusätzlichen Wasserzähler mit S0 einbauen (was ich nicht selber kann). Außerdem haben wir in unserer Mietwohnung insgesamt vier Wasserzähler (2x kalt, 2x warm, jeweils in Küche und Bad). Also wird das wohl nichts. Oder zumindest erst im Eigenheim. Aber das kann auch noch dauern. Dann aber auch bitte mit Temperatursensoren am Vor- und Rücklauf, usw.