NEWS
[gelöst]S0 Schnittstelle mit oPi Zero auslesen (Stromzähler)
-
Hallo,
ich möchte gern meine beiden konventionellen Stromzähler in mein Smarthome einbinden.
Ich habe nun einen optischen Lesekopf gefunden, der die rote Markierung auf der Ferraris-Scheibe im Stromzähler erkennt und entsprechende Impulse über eine galvanisch getrennte S0-Schnittstelle ausgibt.
da ich hier noch einen Orange Pi zero rumliegen habe, würde ich diesen gern zur Auswertung der Impulse nutzen. soweit ich das jetzt verstanden habe, kann ich den S0+ auf den GPIO25/GPIO26 vom OPi zero schalten und S0- auf GND.
Was mich jetzt beschäftigt, muß ich noch einen Pull-Up wiederstand vorschalten und das Signal entprellen?
Für die Umsetzung auf einem Rpi gibt es ja schon einiges im Netzt zu finden nur nicht so richtig für den OPi zero.
Gruß
Sveni_lee
-
Ich weiß, das beantwortet deine Frage nicht aber falls du die Seite noch nicht kennst kannst du ja mal schauen wie Eugen das macht:
-
@sweni_lee
ich habe ein S0-Zähler am laufen. Allerdings nutze ich ein Wemo dazu und kein RPI. Ein paar Bilder von dem Projekt kannst Du unten sehen….
Deine Frage ist schon berechtigt.... Womit willst Du die Stromzählerscheibe auslesen?
Ich nutze dazu einen modifizierten TCRT5000, da die originale Schaltung dort drauf mächtig am schwingen ist.
Auf dem Wemo läuft noch ein angepasster Sketch, was auf die erste Flanke reagiert und den Ausgang einige sek. auf dem Pegel hällt.
Das hat sich bei mir sehr bewährt. Der Impulsgeber aus dem Link tut es bestimmt auch. Aber es geht einfach billiger, ich habe den TCRT5000 in China für nen Euro bekommen, dazu kam noch ein Gehäuse für 4€.
Mit einem Script vom looxer Link: http://forum.iobroker.net/viewtopic.php … &start=200
kannst Du alles umrechnen. Lese dir mal dort alles genau durch.Da habe ich einiges beschrieben.
1526_1.1.jpg
1526_2.2.jpg -
moin,
ja, ich hate genau an den von wendy2702 verlinken lesekopf gedacht.
diesen würde ich dann and die beiden gennanten GPIO anschließen und genau
wie knopers1 beschrieben hat mit einem sketch die anzahl der Umdrehungen auswerten.
Ich war/bin mir halt nur nicht sicher ob das so ohne weiteres gehen würde. ich hatte irgendwo
gelesen, dass das Signal entprellt werden muß und ein pullup benötigt wird.
Aber dann werde ich wohl einfach mal wieder basteln und testen
-
Ich war/bin mir halt nur nicht sicher ob das so ohne weiteres gehen würde. ich hatte irgendwo
gelesen, dass das Signal entprellt werden muß und ein pullup benötigt wird.
Aber dann werde ich wohl einfach mal wieder basteln und testen `
das hängt wirklich nur von der Hardware (die Schaltung) ab, was an der Zählerscheibe drann klebt. Wenn es ein sauberes Hi/LOW an dem Digitalausgang liefert, brauchst Du theoretisch kein pullup. Hier ist eben der Hund begraben, da es optisch ausgewertet wird. Nicht jede Zählerscheibe ist gleich und reflektiert konstant über den roten Streifen. Die Kunst ist es dies zu erkennen und zu beseitigen dass es auch plausible Werte liefert.
-
okay, laut dem Anbieter ist es möglich den S0-Impuldzaähler an einen Arduino, WeMos oder einem Rapberry anzuschließen.
hier ist der Link wie die BEschaltung erfolgen sollte.
-
so ich habe jetzt zwei funktionieren s0-Impulsgeber von Eugen bei mir…
Um diese nun an den orangePi zero anzuschließen wollte ich mich der https://github.com/vladikoms/WiringOP-Zero bedienen. die installation hat auch geklappt. Aber nun komm ich nicht weiter…
Es gibt einige Beispiele eines davon ist auch für interupt geeignet... also hab ich das nun umgeschrieben.
! ````
#include <stdio.h>#include <string.h>#include <errno.h>#include <stdlib.h>#include <wiringpi.h>// What GPIO input are we using?
// This is a wiringPi pin number
! #define BUTTON_PIN 9
! // globalCounter:
// Global variable to count interrupts
// Should be declared volatile to make sure the compiler doesn't cache it.
! static volatile int globalCounter = 0 ;
! /*- myInterrupt:
*/
! void myInterrupt (void)
{
++globalCounter ;
}
! /*
- main
*/
! int main (void)
{
int myCounter = 0 ;
! if (wiringPiSetup () < 0)
{
fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno)) ;
return 1 ;
}
! if (wiringPiISR (BUTTON_PIN, INT_EDGE_FALLING, &myInterrupt) < 0)
{
fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)) ;
return 1 ;
}
! for (;;)
{
printf ("Waiting ... ") ; fflush (stdout) ;
! while (myCounter == globalCounter)
delay (100) ;
! printf (" Done. counter: %5d\n", globalCounter) ;
myCounter = globalCounter ;
}
! return 0 ;
}</wiringpi.h></stdlib.h></errno.h></string.h></stdio.h>danach dann compiliert:
gcc stromzaehler1.c -o stromzaehler -lpthread -lwiringPi
und siehe da, es funktioniert… Die Frage ist nun. wie mache ich weiter? ich würde jetzt die zähler in eine Datei schreiben.. also```` printf (" Done. counter: %5d\n", globalCounter) ;
ersetzen durch:
datei = fopen ("/var/strom/stromzähler1", "w"); fprintf (datei, "%d\n", globalCounter); fclose (datei);
sollte ich dann das berechnen des Stromverbrauchs in iobroker machen oder lieber direkt auf dem Pi?
DEN zählerstand würde ich mir über snmp holen…
-
hallo,
ist hier jemand der sich mit mit c auskennt?
bei meinem Stromzähler Programm habe ich das "Problem" das der Zähler nach jedem Neustart wieder bei 0 anfängt, weil
das ja im Programm so deklariert ist
static volatile int globalCounter = 0
gibt es die Möglichkeit globelcounter zum start des Programms aud der Datei /var/strom/stromzähler1 auszulesen?
-
soooo… dank der Hilfe eines sehr geduldugen Users aus dem ubuntuuser-Forum habe ich jetzt eine finale Lösung mit der ich zufrieden bin.
Mein ziel war es einen Counter zu haben der der eine s0-Schnittstelle, und den Wert fortlaufend schreibt und mir die Möglichkeit der Korrektur bietet.
Um auf die GPIO entsprechend zugreifen zu können habe ich mir der https://github.com/vladikoms/WiringOP-Zero Bibliothek bedient. Netter Weise werden auch gleich Code-Bespiele (isr.c) mitgeliefert. Allerding wird der Counter hier immer bei 0 gestartet, was mir nicht gefällt da ich ja den fortlaufenden Counter haben möchte. Dieser wert soll in einer "log-Datei" gespeichert werden und auch on the fly an ioBroker via simpleApi übergeben werden. das hat den Vorteil, das ich einen Echtzeit-Wert (soweit bei konventionellen Zählern mit Ferrisscheibe möglich) in ioBroker habe ohne Zeitverzögerung. Und hier kam der User seahawk1986 ins Spiel. Mit ihm habe ich die Beispiel isr.c so geändert, dass der log-Wert bei jedem neustart geladen wird und von dort an weiter gezählt wird.
gpio Abfrage und schreiben der log.Datei
sudo nano stromzaehler.c
folgender Inhalt
! ````
#include <stdio.h>#include <string.h>#include <errno.h>#include <stdlib.h>#include <wiringpi.h>// What GPIO input are we using?
// This is a wiringPi pin number
! #define BUTTON_PIN 9
! // globalCounter:
// Global variable to count interrupts
// Should be declared volatile to make sure the compiler doesn't cache it.
! static volatile int globalCounter = 0 ;
! /*- myInterrupt:
*/
! void myInterrupt (void)
{
++globalCounter ;
}
! int parse_value_from_file(const char *filename, int *value)
{
FILE fd = fopen(filename, "r");
if (fd == NULL) {
fprintf(stderr, "could not open %s\n", filename);
return 1;
}
int count = fscanf(fd, "%d", value);
fclose(fd);
if (count != 1) {
fprintf(stderr, "could not parse %s successfully\n", filename);
return 2;
}
return 0;
}
! /
- main
*/
! int main (void)
{
const char filename[] = "/var/strom/stromcounter";
int myCounter;
int error = parse_value_from_file(filename, &myCounter);
! if (error) {
myCounter = 0;
fprintf(stderr, "unable to read initial value from %s, starting at %d", filename, myCounter);
}
! globalCounter = myCounter;
! if (wiringPiSetup () < 0)
{
fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno)) ;
return 1 ;
}
! if (wiringPiISR (BUTTON_PIN, INT_EDGE_FALLING, &myInterrupt) < 0)
{
fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)) ;
return 1 ;
}
! for (;;)
{
// printf ("Waiting ... ") ; fflush (stdout) ;
! while (myCounter == globalCounter)
delay (100) ;
! FILE * datei = fopen (filename, "w");
fprintf (datei, "%d\n", globalCounter);
fclose (datei);
fprintf (stdout, "%d\n", globalCounter);
fflush(stdout);
myCounter = globalCounter ;
! }
! return 0 ;
}</wiringpi.h></stdlib.h></errno.h></string.h></stdio.h>nun die Datai kompilieren
gcc -Wall stromzaehler.c -o stromzaehler -lpthread -lwiringPi
das kompilierte Programm verschieben:
sudo mv stromzaehler /usr/local/bin/
Pfad für die log-Datei erstellen
sudo mkdir /var/strom
skript für das übertragen des Zählerstandes erstellen
code (simpleApi.Pfad anpassen und Datenpunkt in ioBroker anlegen):
#!/bin/bash
/usr/local/bin/stromzaehler | while read -r counter; do
curl "http://192.168.1.142:8082/set/javascript.0.Stromzaehler.Normalstrom.Zaehlerstand_input?value=${counter}"
donedas Programm ausführbar machen
chmod zaehlerstandexport.sh
und wieder verschieben
sudo mv stromzaehlerexport.sh /usr/local/bin/
jetzt noch den Autostart
sudo nano /etc/systemd/system/electric-meter.service
code:
[Unit]
Description=electric meter
After=network-online.target[Service]
ExecStart=/usr/local/bin/stromexport.sh[Install]
WantedBy=multi-user.targetimmer nach Änderungen an der service-Datei ausführen, damit Systemd die neu einliest
sudo systemctl daemon-reload
damit der Dienst beim Booten gestartet wird
sudo systemctl enable electric-meter.service
startet den Dienst sofort
sudo systemctl start electric-meter.service
es wird eine Datei stromcounter im erstellten log-Verzeichniss angelegt. diese kann editiert werden um den Zählerstand zu korrigieren. Es werden aber nur Anzahl der Umdrehungen protokolliert und nicht der Zählerstand ansich. eventuell kann der ein oder Andere ja damit was anfangen… ich habe auf meinem OrangePi Zero Ubuntu Server 16.04 installiert. Gruß Sveni_Lee