Hallo, ich habe mit dem Arduino erfolgreich ein Beispiel nachgebaut, womit ich die S0-Schnittstelle eines Stromzählers auslesen und so die Zählimpulse mit dem Arduino zählen und auswerten kann.
Nun meine wichtige Frage dazu: Ist es möglich mit der Funktion attachInterrupt mehrere unterschiedliche Pins und somit mehrere Zähler entsprechend getrennt auszuwerten?
Bisher klappt das leider nicht und ich erhalte in meinem Beispiel überall die gleichen Werte, obwohl an Pin 3 und 4 kein Zähler angeschlossen ist. Somit ist die Frage, ob der Fehler eine technische Ursache hat oder im Code ein Fehler steckt?
int interval = 5; //Counter refresh and save interval
int wh_start1;
int wh_start2;
int wh_start3;
int crontimer;
void setup() {
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), Ext_INT1_ISR1, RISING);
attachInterrupt(digitalPinToInterrupt(3), Ext_INT1_ISR2, RISING);
attachInterrupt(digitalPinToInterrupt(4), Ext_INT1_ISR3, RISING);
}
void loop() {
if(millis()/1000 > crontimer+interval){
crontimer = millis()/1000;
Serial.print("Start Wh: ");
Serial.print(wh_start1);
Serial.print(wh_start2);
Serial.println(wh_start3);
Serial.println("================");
}
}
void Ext_INT1_ISR1()
{
wh_start1++;
}
void Ext_INT1_ISR2()
{
wh_start2++;
}
void Ext_INT1_ISR3()
{
wh_start3++;
}
Eingangspins die nicht beschaltet sind ziehen Störungen herein. Sie können ein HIGH wie auch ein LOW Potential haben, oder auch jederzeit zufällig wechseln.
Reden wir mal von einem Arduino UNO R3.
Der Controller ist an allen Pins Interuptfähig. Die Pins 2 und 3 haben eine bessere Ausarbeitungsmöglichkeit. Alle anderen Pins können einen Interrupt generieren, die genaue Interruptquelle muß aber nach einem Interruptereignis explizit ausgelesen werden.
Hallo,
wie hast Du denn die Eingänge beschaltet ? Wenn die offen in der Luft rumhängen stören die sich eventuell gegenseitig .
Du kannst aber die Eingänge auch ganz normal im Setup mit dem internen Pullup und pinMode auf ein definiertes Potential legen.
Beim Uno kannst Du pin2 und pin3 für eine ISR nutzen. Wenn Du int Variable nutzt dann benötigt der Uno 2 Speicherzugriffe beim auslesen. Genau zwischen beiden könnte ein Interrupt fallen und die bereits halb ausgelesene Variable nochmals ändern. Das kann zu falschen Werten führen. Damit das nicht passiert, kann man vor der Übergabe den Interrupt sperren und direkt anschließend wieder freigeben, oder das ATOMIC Makro verwenden.
Deine Zählvariable außerhalb der ISR verändern willst Du ja vermutlich nicht ansonsten solltest Du die Variable ebenfalls als volatile definieren.
Hallo,
ich hab das mal in Deinen Sketch eingebaut. Die Berechnung millis()/1000 habe ich jetzt mal rausgenommen , ich denke da kann es zu Rundungsfehlern kommen. Ich habe aber nicht weiter drüber nachgedacht
Ja.
Ich habe aber noch eine weitere Möglichkeit, die in Betracht gezogen werden kann.
Du kannst weitere Pins als interruptpins deklarieren und dann mit eigener Routine auslesen.
Schau Dir im DaBla die Pinbelegung an.
Jeder pin, der pcint gefolgt von einer Zahl beschrieben ist, ist fähig.
Über welchen arduino sprichst du?
Für einen Mega habe einen kompletten Port -> 8 Pins direkt verfügbar gemacht und damit alle meine Zähler ausgelesen.
Beim ATmega328 des UNO R3 sind alle Pins Interruptfähig. Der Unterschied zwischen den pins 2 und 3 und den anderen ist die Ausleselogik. Für die Pins 2 und 3 gibt es explizit Register während die anderen in Register zusammengefaßt sind und man die Info daraus extrahieren muß. Ist keine Hexenwerk aber eben nicht von der Controlerinternen Logik so vorgekaut und in mundgerechte Stücke gebracht wie bei Pins 2 und 3.
Hallo @michael_x ,
danke für den Hinweis
darf ich da noch mal für mein Verständnis nachfragen ?
ich war bisher davon ausgegangen das detachInterrupt(digitalPinToInterrupt(2)) den Interrupt auf pin 2 und damit die dazugehörige ISR abschaltet. Nur diese zugehörige ISR könnte ja den Wert der Variablen verändern. Nachteil ein zugehöriger Pegelwechsel an dem Eingang während der Zeit würde unerkannt bleiben, also im Beispiel nicht gezählt.
Aus deinem Post schließe ich nun:
noInterrupts() schaltete alle Interrupts aus, klingt ja erst mal unnötig.
Aber nach dem erneuten Einschalten werden die zugehörigen ISR für die Ereignisse, die während der Zeit aufgetreten sind, nachträglich bearbeitet. Damit ginge kein Interrupt verloren und es würde in dem Beispiel immer gezählt.
noInterrupt() ( = cli() ) sperrt Interrupts, setzt also quasi die Priorität des normalen Sketches hoch.
Wenn in der Zeit ein Interrupt auftritt, wird er eben danach bearbeitet.
Innerhalb einer ISR sind übrigens die Interrupts genauso gesperrt.
detachInterrupt hängt die ISR ab, richtig. Alle Impulse die in dieser Phase kommen, gehen also verloren. Das willst du nicht.
Eine lange Interruptroutine und schnelle Interupts können zu verarbeitungsverlusten führen. Egal ob in der ISR der Interrupt geperrt ist oder interrupts erlaubt sind.
Du mußt nur denken Du sitzt vor dem Fernsehr, siehst ein interessantes Fusßballspiel und Deine Frau will was von Dir. Wenn es nur ein Einmachglas ist das Du aufmachne mußt geht das ja noch, wenn aber der Müll rausgetragen werden muß, der Winterbezug der Gartensitzbank aus dem Speicher geholt werden und Du noch eine weitere Aufgabe bekommst bevor Du mit der letzten fertig bist wird das weder was Gutes mit dem Spiel noch mit der Abarbeitung der Unterbrechiungen.
Hallo,
wenn du die Zählerstände der 14 Zähler ebenfalls im EPROM speichern willst, wie in dem Link, dann kannst du dazu eine Struktur anlegen. Die lässt sich dann mit get und put mit einer Zeile auslesen und speichern. Zudem macht die Verwendung von Arrays Sinn.
ich denke auch es sollte ohne Interrupts gehen, allerdings wenn Du z.B noch ein Display mit dran hast sieht das eventuell anders aus. Es hängt davon ab was Du mit den Daten vorhast. Eventuell nimmst Du auch einen ESP und nutzt z.B einen Webserver über Wlahn als Anzeige.Möglichkeiten gibt es da reichlich.