Allgemeines Aufbau Der optische Sensor / Sensor-Modul Betrachtungen zur Messgenauigkeit Leistungs-Messung / Berechnung Funktionstest Halterung Einlesen der Werte mit dem Raspi ioBroker-Integration Download
Viele Haushalte haben noch herkömmliche Stromzähler mit einer Drehscheibe. Aus Sicht des Datenschutzes sind diese herkömmlichen Ferraris-Stromzähler den modernen "Smartmetern" haushoch überlegen. Aber manchmal interessiert einen doch der momentane Stromverbrauch des eigenen Haushaltes. Da gibt es z.B. Lösungen bei denen der Zähler mit einer
Kamera überwacht wird, und mit einem Neuronalen Netz der
Zählerstand ausgewertet wird, aber es geht auch deutlich
einfacher. Mein einfacher Sensor misst die Drehgeschwindigkeit der
Zählerscheibe, und errechnet daraus den momentanen
Verbrauch. Das Ergebnis wird via RS232 ausgegeben. Für
eine komfortable Protokollierung und Anzeige, habe ich den
Sensor in ioBroker (Hausautomatisation) eingebunden. |
RS232-Emulation
/ USB-Wandler Der Sensor besitzt einen RS-232-Ausgang am Port GP4 (Pin 3). Letzterer ist eine Softwareemulation, da der PIC12F675 keine RS-232-Hardware besitzt. Die Polarität des RS-232-Ausgangs kann mit dem Jumper JP1 am Port GP3 (Pin 4) eingestellt werden. Wird hier GP3 mit GND verbunden (JP1: 2-3), dann kann der RS232-Ausgang direkt mit dem RX-Pin eines normalen RS232-Einganges verbunden werden. Der Höhe des erzeugten Signalpegels entspricht zwar nicht der RS232-Spezifikation, aber moderne Computer kommen damit erfahrungsgemäß problemlos zurecht (9600 Baud, 8 Bit, 1 Startbit, 1 Stopbit, keine Flusskontrolle). Oft werden heute aber RS232-USB-Wandlerplatinen günstig angeboten, die keinen RS232-Treiberchips haben und stattdessen mit TTL-Pegel arbeiten. Dafür ist dann eine inverse Polarität nötig. Die gibt der Sensor aus, wenn man GP3 mit 5V verbindet (JP1: 1-2). Im Stromlaufplan ist so eine TTL_Pegel-Wandlerplatine angedeutet, wie ich sie auch einsetze. Ein Foto sieht man rechts. Auf der Platine ist ein Jumper, den man auf "5V" setzen muss, damit der Sensor über das "VCC"-Pin mit 5V versorgt wird. Der Sensor gibt zyklisch (etwa alle 20ms ... 50ms) einen Textstring mit der momentanen Leistung und mit der Zahl der Scheibendrehungen aus: "W=00820W Ro:000075" |
An das Ergebnis hänge ich dann noch eine Null an, und bekomme ein Ergebnis in Watt.
Beispiel:
Die Dauer einer Rotation der Drehscheibe sei 60 Sekunden. Der
Zähler zählt in dieser Zeit bis 29296 (29296 x 2,048ms = 59,998
s).
Die Berechnung ergibt 2343750/ 29296 = 80.
Dieser Zahlenwert wird in eine vierstellige Dezimalzahl (0080)
gewandelt und mit einer angehangenen Null über RS232
ausgegeben: W=00800W.
#!
/usr/bin/perl # script zum Auslesen des Wattmeter-Sensors via RS232-USB # aufrufen mit "read_wattmeter.sh > /run/shm/PowerMeter_Power.txt 2>&1 #W=00840W Ro:545092 open ($fd, "< /dev/ttyUSB0") or die "cannot open serial port"; # warten auf = # das ist das 2. Zeichen im String und es ist eindeutig while (getc($fd) ne "=") {} # auf Zeilenanfang $c=""; $output="W="; while($c ne "\n"){ $c = getc($fd); $output = $output.$c; } close ($fd); #davor die Zeit schreiben my $CTIME_String = localtime(time); print "$CTIME_String "; #Wed Jan 1 01:16:01 2014 W=00840W Ro:545092 print "$output"; |
* * * * * /opt/iobroker/iobroker-data/files/0_userdata.0/read_wattmeter.sh > /run/shm/PowerMeter_Power.txt 2>&1 |
var fs = require('fs'); var fn = '/run/shm/PowerMeter_Power.txt'; var idPowermeterMeldung = 'Wattmeter.Meldung'; var idPowermeterPower = 'Wattmeter.Leistung_W'; var idPowermeterRotations = 'Wattmeter.Drehungen'; var idPowermeterRotationsNight = 'Wattmeter.DrehungenMitternacht'; var idPowermeterTime = 'Wattmeter.ZeitPunkt'; var idPowermeterEnergie = 'Wattmeter.EnergieGestern_Wh'; var idPowermeterKosten = 'Wattmeter.KostenGestern_Ct'; var idPowermeterTarif = 'Wattmeter.Cent_kWh'; function getPowerMeter() { // Leistung in Watt fs.readFile(fn, 'utf8', function(error, data) { if(error) log('Fehler beim Lesen von ' + fn, 'error'); //Sun Apr 10 13:20:01 2022 W=00520W Ro:002115 else { setState(idPowermeterMeldung, data); const words = data.split(' '); var S1, S2, S3, S4; var P = 0; S1 = words[3]; // Zeit S4 = words[4]; // Jahr P = data.indexOf('W='); S2 = data.substr(P+2, 5); P = data.indexOf('Ro:'); S3 = data.substr(P+3, 6); //Wed Apr 13 07:57:01 2022 W=00600W Ro:005105 setState('Wattmeter.Str_Zeit', S1); //07:57:01 setState('Wattmeter.Str_Power', S2); //00600 setState('Wattmeter.Str_Drehungen', S3);//005105 // Zeit setState(idPowermeterTime, S1); // Power setState(idPowermeterPower, parseFloat(S2)); // Drehungen setState(idPowermeterRotations, parseFloat(S3)); } }); } function getDaylyEnergy() { var DrehAlt=0, DrehNeu=0, Energie=0, Tarif=0, Kosten=0, PowerAvg=0; // alten und aktuellen Drehungswert lesen, ist ein 6-stelliger Dezimalzähler DrehAlt = getState(idPowermeterRotationsNight).val; DrehNeu = getState(idPowermeterRotations).val; // Tarif in Cent pro kWh lesen Tarif = getState(idPowermeterTarif).val; // neuen Drehungswert speichern setState(idPowermeterRotationsNight, DrehNeu); // TagesEnergie berechnen und speichern, 75 U/kWh, außer bei Zählerüberlauf if (DrehNeu > DrehAlt) { Energie = (DrehNeu - DrehAlt)* 1000 / 75; Kosten = Math.round(Energie * Tarif / 1000); // cent Energie = Math.round(Energie); setState(idPowermeterEnergie, Energie); setState(idPowermeterKosten, Kosten); Kosten = Kosten/100; // Euro setState('Wattmeter.str_KostenGestern_E', Kosten.toFixed(2)); PowerAvg = Energie/24; PowerAvg = Math.round(PowerAvg); Energie = Energie/1000; // kWh setState('Wattmeter.str_EnerieGestern_kWh', Energie.toFixed(3)); setState('Wattmeter.PowerGesternAvg_W', PowerAvg); } } schedule('*/1 * * * *', getPowerMeter); // Jede Minute schedule('11 0 * * *', getDaylyEnergy); // um 0:11 |