Anfänger Fragen zu S0 Logging und Standby Killer

Liebe Arduino-Profis,

ich habe nun seit einigen Tagen einen UNO und einen MEGA plus viel Zubehör zu Hause liegen. Mich interessiert besonders das Thema Stromzähler mittels S0-Bus.. und komme aber nicht so richtig weiter mit meinem Anfänger-Wissen und wende mich deshalb an Euch! Bitte seht mir nach wenn ich mal nicht so perfekt alles mache oder nochmal nachfrage ;-)

Leider scheitere ich allerdings schon etwas vorher, beim eigentlich (vermutlich) ganz simplen richtigen verkabeln... Bei mir tauchen Probleme wie bereits hier http://forum.arduino.cc/index.php/topic,130970.msg985026.html beschrieben auf.

Da ich mir mit den Beschreibung dort hart getan habe, habe ich mal gezeichnet... vielleicht kann mir jemand sagen was ich falsch mache.... (Der Widerstand soll ein 10kOm sein...) oder ob es eigentlich so richtig ist??

Ansonsten habe ich mir folgendes (durch Suche im Forum und Internet) herausgelesen:

Grundsätzlich ist es wohl ganz einfach den S0-Bus bzw. die Impulse zu zählen. Ich habe verschiedene Ansätze gefunden, wobei mir die Vor- und Nachteile noch nicht ganz klar sind. Manche hier schreiben, das Zählen per Interrupt wäre das einzig perfekte, andere überwachen einfach so den Status des S0-Busses... Nachdem ich den Verbrauch z.B. eines Gerätes beobachten möchte und auch wissen möchte was es so im Standby macht abe ich mir vorgenommen, jeden Impuls mit einem Zeitstempel in einer TXT-Datei auf einer SD-Karte zu speichern. Dann möchte ich auswerten, wie lange die Spanne zwischen zwei Impulsen ist, und mir dann einen Eindruck davon verschaffen was "Ruhe/Standby-Phasen" und was "Aktivitäts-Phasen" sind.

Aber alles nach einander... zuerst das richtige Verkabeln des S0-Buses an den Arduino..

Vielen Dank für Euer Verständnis und Euere Tipps schon mal im Voraus!

Moin Parador,

afaik sind das zwei unterschiedliche Dinge: Impulse zählen (der blinkenden LED an der Front Deines Zählers) und/oder den S0-Bus auslesen. Was genau möchtest Du tun?

Eine Lösung für das Impulse zählen hätte ich (mit Mega, LCD-Display, RealTimeClock, Ethernet-Shield zum Datenabruf im Netzwerk und mit permanenter Datanaufzeichnung auf SD-Karte), S0-Bus auslesen habe ich nix.

Hallo Parador,

ich habe derzeit eine S0 Zählung auf einem UNO laufen und bin mit dem Ergebnis sehr zufrieden. Mein Zähler liefert 10000Imp/kWh mit einer Impulsdauer von 2ms. Ich zähle mittels Interrupt am Pin 2 des Arduino.

Deine Schaltung aus dem Bild solltest Du ändern, weil so wie sie jetzt ist funktioniert das nicht wirklicht.

Ich habe einen Widerstand von 4,7kOhm zwischen +5V und Pin2 geschaltet. Der S0 Kontakt ist dann zwischen Pin2 und GND geschaltet. Der S0-Impuls zieht also den Arduino Eingang von high nach low.

Oft sind die S0-Ausgänge der Zähler keine mechanische Schaltkontakte sondern Transistor- oder Optokopplerausgänge. Dann muss man beim Anschluss des Zählerausgangs auf die Polung achten. Pin2 auf + des Zählers und GND an den -Anschluss.

Wenn es Dir hilft kann ich die für meinen Zähler relevanten Sketchteile hier posten.

Je nach Leitungslänge und Kabeltyp zwischen Zähler und Arduino kann diese einfache Verschaltung aber Probleme machen.

Habe in meinem Post oben die S0- mit der D0-Schnittstelle verwechselt. S0 und Impulse zählen ist doch das selbe Thema. Aber: S0 ist meist open collector, also bitte die Hinweise von peter_de beachten.

Hallo Peter, Hallo Reinhard,

vielen Dank für Euere Posts, ich bin vermutlich mehr der optische Typ und habe deshalb die Schaltung nochmal gezeichnet. Vielleicht schaut Ihr nochmal drauf, ob es nun so passt.

Wenn ich dass mit der Verkabelung erstmal richtig hinbekomme, würde ich erstmal selber wieder probieren den Sketch vorwärts zu bringen und mich dann nochmal melden, wenn ich auf Probleme stoße... aber vielen Dank für das Angebot (nehme es gerne später in Anspruch ;-) will aber noch probieren ...)

Ihr könntet mir nur noch einen Tipp gegeben welchen Ansatz ich besser nutze, den mit den Interrupts oder ohne... Wie gesagt, will bei jedem Impuls einen timestamp auf die SD-Karte schreiben lassen... und vielleicht gleich die Sekunden zwischen zwei Impulsen mit dazu (berechnen und speichern)... Später will ich dann in Abhängigkeit von diesen Abständen vielleicht ein Relais die Verbindung kappen lassen, mal sehen....

Hallo Parador, erst mal zum Bild der Schaltung. Es fehlt dort eine Brücke vom rechten Anschluss des Widerstandes zum Eingang des Arduino. Also von Spalte 26 nach spalte 34.

Ich würde Dir grundsätzlich empfehlen die Impulserfassung über eine Interruptfunktion zu erledigen. Alle anderen Möglichkeiten werden irgendwann mit zunehmender Komplexität des Programmes zu Problemen führen indem nicht mehr alle Impulse erkannt werden. Es ist wichtig zu wissen wie lange ein Impuls vom Stromzähler dauert und wie hoch die maximal zu erfassende Leistung ist. Kennst Du diese beiden Angaben für deinen Fall?

Mein Zähler liefert 10000 Imp/kWh mit einer Dauer von 2ms. Bei einer Leistung an meinem Zähler von bis zu 9 kW sind das 90000 Imp/h oder 25 Imp/s. Mit der Erfassung über eine Interruptfunktion funktioniert das bei mir obwohl der UNO noch umfangreiche andere Aufgaben gleichzeitig erfüllt.

Hallo Peter,

danke für den Hinweis, da ist beim Zeichnen wohl was untergegangen… jetzt sollte es dann eher passen!

Über meinen S0-Bus-Zähler habe ich folgendes gefunden:

Impuls Anschluss:
Schaltspannung 5-27VDC, Strom?27mA?100mW, Impulsweite 90ms, Impulsausgang an Klemme 20 und 21, max. Länge des Anschlusskabels 20m

Die maximal zu erfassende Leistung, gute Frage! Da es vermutlich um den Max.-Wert geht…gehe ich im Moment von nicht mehr als 2000-3000Imp/h (eher 1000-1500 ImP/h) also weniger als 1 Impuls in der Sekunde aus…wobei es natürlich sein kann, dass es zu “Spitzen” kommt… nachdem mich aber ja die längeren “Pausen” zwischen zwei Impulsen interessieren, ist weniger als 1 Sekunde nicht ganz so wild…

Ich habe bisher ein Beispiel mit Interrupts gefunden:

const int SoeinsPin     =2;       // Initalisierung S0 für Zähler 1
volatile int impuls=0;             // Impulsarray zum Zählen der Impulse {S0<1>,S0<2>,S0<3>)
int ausgabe = 50000; 

void setup() {
 pinMode(SoeinsPin, INPUT);        // Definieren was SoeinsPin ist (Ein o. Ausgang)
 Serial.begin(9600);
 attachInterrupt(0, zaehleneins, FALLING);  //Interrupt wird ausgelößt bei Positiver Flanke und 
                                            //springt in Programm zaehlen1 0 = Digital 2
}

void loop() 
 { 
   //Wenn ein Impuls kommt, folgendes Auslösen     
   if(digitalRead(SoeinsPin) ==1)
   {
     Serial.print("Impulse = " );                       
     Serial.print(impuls);      
     Serial.print("\t KWh = ");      
     Serial.println(impuls/1000);  
   }
 }

void zaehleneins()                              //Unterprogramm zum Impulse Zählen
 {
 impuls++;
 }

Wo würdest Du nun die “Speicher auf SD-Karte” Zeilen reinpacken? Mit in die Funktion oder in den Loop? Das ist mir noch nicht ganz klar?

Moin Parador,

Parador: Wenn ich dass mit der Verkabelung erstmal richtig hinbekomme, würde ich erstmal selber wieder probieren den Sketch vorwärts zu bringen und mich dann nochmal melden, wenn ich auf Probleme stoße... aber vielen Dank für das Angebot (nehme es gerne später in Anspruch ;-) will aber noch probieren ...)

das ist genau die richtige Einstellung! Nimm die von Peter vorgeschlagene Schaltungskorrektur vor und Du hast die richtige Voraussetzung für die Nutzung des Interrupt-Verfahrens geschaffen. Beim UNO sind die Input-Pins 2 und 3 interruptfähig, solltest Du später auf den Mega wechseln wollen, müsstest Du das nochmal überprüfen.

Wo würdest Du nun die "Speicher auf SD-Karte" Zeilen reinpacken? Mit in die Funktion oder in den Loop? Das ist mir noch nicht ganz klar?

Hier wird Impuls einfach hochgezählt, wenn du einen Bezug kw/h zum Zeitstempel haben will must du Beispielsweise Impuls eine Stunde incrementieren, diesen Wert mit dem Zeitstempel abspeichern und auf 0 setzen.

Ich nehme dazu ein externes EEprom die Speicheradresse wird aus vergangenen Stunden des Jahres ermitteln und Impuls dort gespeichert.

Bei Verwendung einer SD, evtl alle Stunde das Log File öffnen, zur Sicherheit den Zeitstempel und Impuls schreiben und File wieder schließen

Hallo rudirabbit, hallo Reinhardt,

ich versuche nun mal Eure beiden Posts zusammen der Reihe nach zu beantworten... @Reinhardt Die Schaltungskorrektur müsste eigentlich in meinem Post von "Today at 12:38:04 pm" schon erfolgt sein, habe hier den Widerstand verlängert, deshalb sieht man das im kleinen Bild vermutlich nicht so gut... @rudirabbit das in dem Beispiel oben nur hochgezählt wird, hatte ich verstanden, ich will ja aber bei jedem Impuls eine neue Zeile in meiner Logdatei also zum Beispiel folgendes Datum, Uhrzeit, Summe Impulse, Abstand zum letzen Impuls in Sekunden 2014-03-08;19:09:00;1;-- 2014-03-08;19:09:05;2;5 2014-03-08;19:09:30;3;25 2014-03-08;19:10:45; 4;75 Bin mir deshalb nicht sicher, ob das Speichern in einem externen EEProm der richtige Weg ist? Ich hätte halt die Codezeilen zum Speichern auf SD entweder in den Loop oder in die Hochzähl-Funktion mit reingepackt...

Mit Deinem Vorschlag würde ich "nur" sehen wieviele Impulse pro Stunde (jede Stunde des Jahres) in Summe angefallen sind, oder?

@Parador: Wenn du es so willst must du theoretisch immer bei if(digitalRead(SoeinsPin) ==1) das File öffnen Daten Schreiben und wieder schließen. Könnte für die SD schon etwas Stress bedeuten. Wie willst du die Daten später auswerten ?

Mit Deinem Vorschlag würde ich "nur" sehen wieviele Impulse pro Stunde (jede Stunde des Jahres) in Summe angefallen sind, oder?

So ist es, war ja nur ein Vorschlag :-) Ich logge damit den Strom Verbrauch meiner Wohnung mit Aufösung einer Stunde über ein Jahr.

;-) Bitte nicht falsch verstehen, bin dankbar für jeden Vorschlag! Versuche nur immer noch alles richtig zu verstehen ;-) Stellt dann der SD-Schreibbefehl ein zeitliches Problem dar? oder sollte das klappen?

;-) Bitte nicht falsch verstehen

Passt schon :) Wegen der SD und Zeit, habe ich wenig Erfahrung kann ich also nicht viel sagen.

Wo würdest Du nun die “Speicher auf SD-Karte” Zeilen reinpacken?

Ich würde es in Loop erledigen. In die Interruptfunktion sollste man nur das nötigste reinpacken.
Frage am Rande: Woher kennt der Arduino Datum und Uhrzeit?

Hallo Peter,

danke für den Hinweis mit dem Loop, ich werde mir jetzt mal Gedanken machen wie ich es angehe. Vielleicht kannst Du mir trotzdem noch einen Tip geben, was der Vorteil ist das Zählen der Impulse wie im Beispiel oben in einer Funktion zu ereldigen, dann aber den Zeitstempel und das Schreiben im Loop.. Oder hatte ich das falsch verstanden und Du würdest auf die Funktion verzichten und alles im Loop erledigen lassen... Zu Datum und Uhrzeit: Ich habe bereits ein RTC Modul Ds3231 bei mir liegen und werde es dafür nutzen ;-)

Die Interruptfunktion wird halt immer dann ausgeführt wenn das Ereignis eintritt.
Dein Programm muss also nicht ständig in der Loop anfragen ob sich der Pegel von 1 auf 0 geändert hat.

In deinem Programm würde bei

if(digitalRead(SoeinsPin) ==1)
   { impuls++;
     Schreibe auf SD
}

Impuls öfter als einmal pro Ereignis aufaddiert werden, je nachdem wie lange SoeinsPin auf High steht.
Auch der Pseodocode (Schreibe auf SD) ebenfalls. Hier müsste ein Flag gesetzt werden, etwa so

const int SoeinsPin     =2;       // Initalisierung S0 für Zähler 1
volatile int impuls=0;             // Impulsarray zum Zählen der Impulse {S0<1>,S0<2>,S0<3>)
int ausgabe = 50000; 
volatile boolean OK=false;  

void setup() {
 pinMode(SoeinsPin, INPUT);        // Definieren was SoeinsPin ist (Ein o. Ausgang)
 Serial.begin(9600);
 attachInterrupt(0, zaehleneins, FALLING);  //Interrupt wird ausgelößt bei Positiver Flanke und 
                                            //springt in Programm zaehlen1 0 = Digital 2
}

void loop() 
 { 
     
   if(OK)
   {
     Serial.print("Impulse = " );                       
     Serial.print(impuls);      
     Serial.print("\t KWh = ");      
     Serial.println(impuls/1000);  
     OK=false;
   }
 }

void zaehleneins()                              //Unterprogramm zum Impulse Zählen
 {
 impuls++;
 OK=true;
 }

Etwa so. Wie schon gesagt, normalerweise addiert man Impuls eine definierte Zeit lang auf und setzt es dann auf 0. Wenn dir das Stunden Interval zu grob ist, kannst z.b alle Minute machen.

50000 geht allerdings nicht in einen int. Entwender unsigned int oder gleich unsigned long nehmen

Serenifly:
50000 geht allerdings nicht in einen int.

ausgabe wird in dem Code eh noch nicht benutzt, hatte einfach den Code vom Eingangsposting genommen.
Auch wird impuls irgendwann überlaufen.

@Parador: Wie willst du deine Daten später anzeigen ?
Ich mache das via Webinterface (ethernet shield) und google charts, schaut so aus.
google charts ist ein einfacher Weg Diagramme darzustellen.

Hi Zusammen,

das mit den 50000 ist lustig, ich hatte den CodeSchnipsel ja auch gefunden, im ursprünglichen Sketch wurde damit die Ausgabe gesteuert… habe ich jetzt inzwischen schon entfernt.

Zur Auswertung: Im Moment bin ich noch dabei, dass mit dem Speichern auf SD ordentlich zu machen und auch mal ein externes EEprom für Summen (wie weiter oben ja schon mal vorgeschlagen) zu nutzen… das wird mich heute Abend noch ein wenig beschäftigen :wink: Mein erster Gedanke war, erstmal im CSV-Format auf der Karte zu speichern, und dann die Datei am PC auszuwerten… Bin noch nicht sicher ob ich überall wo ich es am Ende einsetzen will ein Netzwerkkabel (oder WLAN) verfügbar ist…
Mal sehen…
Der Chart über Google schaut aber schon sehr gut nett und damit verführerisch aus :wink:

LG

Hallo mal wieder nach einigen Tagen des testens....

Ich habe nun einen Sketch auf Grundlage der Tipps hier geschrieben, der mittels eine Funktion die Impuls zählt, dann im Loop auch noch die Zeit zwischen den Impulsen misst, dann die 6 längsten Zwischenräume zwischen zwei Impulsen und die 3 kürzesten Zwischenräume ermittelt und im Anschluß pro Impuls eine Zeile mit Datum und Uhrzeit in eine Datei auf einer SD-Karte schreibt...

Im "Laborversuch" am Schreibtisch klappte das schon recht gut. Gestern hab ich dann den Realversuch mit einer am Wattmeter angeschlossenen Waschmaschine (hatte nichts besseres im Sinn was lange läuft und auch noch unterschiedlichen Stromverbrauch haben muss ) im Anschluß blieb der Arduino über Nacht drann um auch den Standby bei nicht ausgeschalteter Maschine zu beobachten....

Leider scheint das nicht so geklappt zu haben wie ich mir das vorgestellt habe... er hat insgesamt nur rund 230 Impulse also nur 0,23 kwh gezählt, auch nicht bei jedem Impuls den entsprechenden Eintrag gemacht (ich vermute er kam nicht hinterher), d.h. er hat z.B. bei folgendem Aufbau jeder Zeile folgende Einträge gemacht... Datum; Uhrzeit;Anzahl der Impulse; Zeit zwischen diesem um dem letzten Eintrag; Min/Max Werte 13.03.2014; 14:00:00; 1; 0; blablabla...... 13.03.2014; 14:00:02; 2; 2; blablabla...... 13.03.2014; 14:00:15; 10; 13; blablabla...... 13.03.2014; 14:00:30; 15; 5; blablabla...... Das wär jetzt noch nicht so schlimm, aus der vergangenen Zeit kann ich dann ja auch die "grobe Zeit" zwischen den Impulsen berechnen, aber nur 0,23kwh für eine Ladung Wäsche mit einer Waschmaschine die um die 1,3 kwh pro Ladung benötigen soll? Das glaub ich nicht.... Als ich die Verbindung zum Wattmeter weggeschraubt hab hat er dabei massiv hochgezählt und auch diese hohen Werte wurden dann analog dem Beispiel oben mitgeloggt... Kann es sein, dass ich wirklich noch auf die Polung der Anschlüße ans Wattmeter achten muss? Habe hier keine Kennzeichnung/Hinweis am Wattmeter gefunden, könnte es aber mal andersrum versuchen. Auch komisch erschien mir, dass heute morgen (da lief ja keine Maschiene, mal drei Impulse innerhalb einer Sekunde angefallen sein sollen, was selbst für ein Standyby fast ein wenig kurz hintereinander erscheint...

Bin für Euere Ideen und Anregungen wieder sehr dankbar ;-)