Interrupt und Debaounce für Stromzähler

Hallo ! Habe folgenes vor: Ich baue mir gerade ein Messinstroment für meinen Stromzähler zusammen.Dieser gibt ein Impuls pro Watt raus oder besser gesagt 1000 Imp = 1Kw. Da ich zwei stück davon besitze wollte ich einen Interrupt auslösen um den Schaltvorgang nicht zu übersehen das kombinieren mit Debounce finde ich noch wichtig aber ich glaube werde dann den 2 Kanal damit behindern wenn er wartet.

Wer kann Helfen ?

Wenn du mit Interrupts arbeitest, kannst du debounce nicht via delay realisieren.

Prellt dein "Stromzähler" überhaupt ? Wie ist das Puls-Pause Verhältnis ? ( 1:1 oder feste Puls-Länge und variable Pause ) Was ist die Maximal-Frequenz / Leistung, die der Zähler erfassen kann, bzw. bei dir vorkommt ?

Du kannst ja mal einen Test-Sketch schreiben, der dir die minimalen Puls- bzw. Pause-Dauern erfasst. Das sollte zeigen, dass debounce kein Thema ist.

Übrigens am Rande : Du meinst sicher 1000 Imp = 1kWh (1 Imp = 3.6 Ws) oder 1 Imp = 1Ws

Danke für die Antwort! Kann ich leider nicht sagen ob der schalter Prellt deswegen mach ich das erst mal algemein

Zur Frequenz muss mal nachschauen aber das wäre eine Idee.

Wie sieht es denn aus wenn ich in der warte Schleife des einen bin und der andere gibt auch einen Impuls ab ? Laufen beide prozesse gleichzeitig ab?

Wie sieht es denn aus wenn ich in der warte Schleife des einen bin und der andere gibt auch einen Impuls ab ?

Wenn Du das über Interrupts realisieren willst, hast Du keine Warteschleife. Du verarbeitest den Impuls (wie auch immer) und kehrst schnellstmöglich zurück. Während der Abarbeitung eines Interrupts sind die anderen Interrupts gesperrt, weshalb man immer so wenig Zeit wie möglich in einem Interrupt-Handler verbringen sollte.

Ahh Ok!
Hab jetzt mal das Zusammengestellt funktioniert aber noch nicht richtig zählt nicht mit :zipper_mouth_face:

#include <SPI.h>                                //includieren der Ethernet Bibiothek
#include <Ethernet.h>                           //includieren der Ethernet Bibiothek
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };         //Mac-Adresse vergeben
IPAddress ip(192,168,1, 177);                   // IP Adresse vergeben
IPAddress gateway(192,168,1, 1);                // Gateway Adresse vergeben
IPAddress subnet(255, 255, 0, 0);               // Subnetmask  
EthernetServer server(23);                      // Telenetport 23 für Monitoring
boolean alreadyConnected = false;               // Status ob verbindung besteht



const int SoeinsPin     =0;       // Initalisierung S0 für Zähler 1
const int SozweiPin     =1;       // Initalisierung S0 für Zähler 2
const int SodreiPin     =2;       // Initalisierung S0 für Zähler 2
const int ledeinsPin    =3;       // Initalisierung LED für S0<1>
const int ledzweiPin    =4;       // Initalisierung LED für S0<2>
const int leddreiPin    =5;       // Initalisierung LED für S0<3>
const int ledpowerPin   =6;       // initalisierung Power LED

// Variablen werden Vorgabewerte zugewiesen
int ledSchalt0 = LOW;             //LED Schaltzustand Power LED
int ledSchalt1 = LOW;              //LED Schaltzustand S0<1>       
int ledSchalt2 = LOW;              //LED Schaltzustand S0<2>
int ledSchalt3 = LOW;              //LED Schaltzustand S0<3>
int SchaltzustandS1 = LOW;               // Schalter für Impulsgeber S0<1>
int SchaltzustandS2 = LOW;               // Schalter für Impulsgeber S0<2>
int SchaltzustandS3 = LOW;               // Schalter für Impulsgeber S0<3>
int impuls[]={0,0,0};              // Impulsarray zum Zählen der Impulse {S0<1>,S0<2>,S0<3>)    


void setup() {
  pinMode(SoeinsPin, INPUT);        // Definieren was SoeinsPin ist (Ein o. Ausgang?)
  pinMode(SozweiPin, INPUT);        // Definieren was SozweiPin ist  
  pinMode(SodreiPin, INPUT);
  pinMode(ledpowerPin, OUTPUT);
  pinMode(ledeinsPin, OUTPUT);
  pinMode(ledzweiPin, OUTPUT);     
  digitalWrite(ledpowerPin, HIGH);  // Power LED wird eingeschaltet
}

void loop() {
    attachInterrupt(SoeinsPin, zaehleneins, RISING);  //Interrupt wird ausgelößt bei Positiver Flanke und springt in Programm zaehlen1
    attachInterrupt(SozweiPin, zaehlenzwei, RISING);  //Interrupt wird ausgelößt bei Positiver Flanke und springt in Programm zaehlen2
    attachInterrupt(SodreiPin, zaehlendrei, RISING);  //Interrupt wird ausgelößt bei Positiver Flanke und springt in Programm zaehlen2
 } 
  
  
void zaehleneins(){                              //Unterprogramm zum Impulse Zählen
impuls[1]++;
}

void zaehlenzwei()                              //Unterprogramm zum Impulse Zählen
{
impuls[2]++;
}

So wird es nicht funktionieren.

1) Solltest Du die Interrupthandler nicht in der loop() sondern in setup() setzen. 2) Schau mal unter http://arduino.cc/en/Reference/AttachInterrupt nach, da gibt es eine Tabelle welche Pins als Interruptquelle verwendbar sind. Da Du nicht schreibst welchen Arduino Du nutzt, können wir dazu nicht viel sagen. Pin 0 (wie für dein SoeinsPin ist aber bei keinem Arduino ein Interrupt Pin) Und wenn Du keinen Mega hast, gibt es nur 2 Interruptquellen, nicht 3 wie in Deinem Sketch. 3) Woran merkst Du in Deinem Sketch denn, das nicht gezählt wird? Es gibt da keine Ausgaben oder irgendwas, womit Du Feedback über das Zählen bekommen würdest.

Kurze Korrektur, beim Leonardo sind tatsächlich Pin 0 bis 3 als Interruptquellen möglich.

Ja habs jetzt Rausbekommen. Die Ausgabe ist nachher dran in eine SQL Datenbank + zu wartungszweken noch Seriel.

Hier der Code:

/*#include <SPI.h>                                //includieren der Ethernet Bibiothek
#include <Ethernet.h>                           //includieren der Ethernet Bibiothek
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };         //Mac-Adresse vergeben
IPAddress ip(192,168,1, 177);                   // IP Adresse vergeben
IPAddress gateway(192,168,1, 1);                // Gateway Adresse vergeben
IPAddress subnet(255, 255, 0, 0);               // Subnetmask  
EthernetServer server(23);                      // Telenetport 23 für Monitoring
boolean alreadyConnected = false;               // Status ob verbindung besteht
*/

const int ledpowerPin   =0;       // initalisierung Power LED
                                  // Pin 1 ist nicht belegt (Frei)
const int SoeinsPin     =2;       // Initalisierung S0 für Zähler 1
const int SozweiPin     =3;       // Initalisierung S0 für Zähler 2
const int ledeinsPin    =4;       // Initalisierung LED für S0<1>
const int ledzweiPin    =5;       // Initalisierung LED für S0<2>


// Variablen werden Vorgabewerte zugewiesen
int ledSchalt0 = LOW;              //LED Schaltzustand Power LED
int ledSchalt1 = LOW;              //LED Schaltzustand S0<1>       
int ledSchalt2 = LOW;              //LED Schaltzustand S0<2>
int SchaltzustandS1 = LOW;         // Schalter für Impulsgeber S0<1>
int SchaltzustandS2 = LOW;         // Schalter für Impulsgeber S0<2>
int impuls[]={0,0};                // Impulsarray zum Zählen der Impulse {S0<1>,S0<2>,S0<3>)    


void setup() {
  pinMode(SoeinsPin, INPUT);        // Definieren was SoeinsPin ist (Ein o. Ausgang?)
  pinMode(SozweiPin, INPUT);        // Definieren was SozweiPin ist  
  pinMode(ledpowerPin, OUTPUT);
  pinMode(ledeinsPin, OUTPUT);
  pinMode(ledzweiPin, OUTPUT);     
  digitalWrite(ledpowerPin, HIGH);  // Power LED wird eingeschaltet
  attachInterrupt(0, zaehleneins, RISING);  //Interrupt wird ausgelößt bei Positiver Flanke und springt in Programm zaehlen1 0 = Digital 2
  attachInterrupt(1, zaehlenzwei, RISING);  //Interrupt wird ausgelößt bei Positiver Flanke und springt in Programm zaehlen2 1 = Digital 3
}

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

void zaehlenzwei()                              //Unterprogramm zum Impulse Zählen
{
impuls[1]++;
}

P.S.ist ein Uno

In Deinem Code ist aber kein Serial zu finden. Schön das es jetzt funktioniert, aber Du solltest zumindest genau den Sketch posten, mit dem Du ein Problem hast, nicht eine veränderte oder abgespeckte Variante. Zusätzlich solltest Du noch die Variable "int impuls[]" als volatile deklarieren, sonst hast du bei ungünstigem Timing Fehler beim Auslesen der Variablen außerhalb der Interrupt-Funktionen.

Ich bezweifle daß Du ein Entprellen brauchst, da der Ausgang des Zählers sicher kein mechanischer Kontakt ist. Grüße Uwe.

Hab jetzt mal ein Programm zum Testen geschrieben, Variable läuft auber nur hoch

const int SoeinsPin     =2;       // Initalisierung S0 für Zähler 1
int impuls=0;                     // Impulsarray zum Zählen der Impulse {S0<1>,S0<2>,S0<3>)
int ausgabe = 5000; 
 
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() 
 { 
 ausgabe--;
 if (ausgabe==0)
   {
     ausgabe=5000;
     Serial.print("Impulse = " );                       
     Serial.print(impuls);      
     Serial.print("\t KWh = ");      
     Serial.println(impuls/1000);  
   }   
 }
void zaehleneins()                              //Unterprogramm zum Impulse Zählen
 {
 impuls++;
 }

Was ist denn da falsch gelaufen?

Variable läuft auber nur hoch

Versteh ich nicht. Welche Variable ?

5000 dummy loop Durchlaufe schnell gemacht ( ca. 20-50 msec ), wie viele Interrupts erwartest du in der Zeit ?

[b]volatile[/b] int impuls=0;
vermeidet falsche Optimierungsversuce des Compilers

eigentlich gar keine ^_^ hab nichts angesclossen ?? Trozdem zählt mir der MC schon sekundenweise hoch sehr komisch ? das ich bei 10 sek auf 1 kw komme

hab nichts angesclossen

Das ist zu wenig. GND oder Vcc ( oder zumindest ein Widerstand dorthin ) sollte es schon sein.

com-cat: eigentlich gar keine ^_^ hab nichts angesclossen ?? Trozdem zählt mir der MC schon sekundenweise hoch sehr komisch ? das ich bei 10 sek auf 1 kw komme

Dann arbeitet Dein PIN wie eine Antenne. Zieh das Pin mit einem großen Widerstand auf einen definierten Pegel. Masse oder 5V, das ist egal.

Ein ähnliches Problem hatten wir letztens: http://arduino.cc/forum/index.php/topic,130970.msg985026.html Was passiert, wenn du aus dem pinMode(SoeinsPin, INPUT); ein pinMode(SoeinsPin, INPUT_PULLUP); machst? Wie gesagt, ohne Anschluss irgendwelcher Sensoren...

ja das war es :slight_smile:
hab das mit einem 100Kohm wiederstand gemacht also von Pin2 zu GND daran dann ein kabel vom Zähler und das andere an den +5V

Danke

und hier noch mal der richtige Test code

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() 
 { 
 ausgabe--;
 if (ausgabe==0)
   {
     ausgabe=50000;
     Serial.print("Impulse = " );                       
     Serial.print(impuls);      
     Serial.print("\t KWh = ");      
     Serial.println(impuls/1000);  
   }   
 }
void zaehleneins()                              //Unterprogramm zum Impulse Zählen
 {
 impuls++;
 }