S0-Zähler mit Arduino Nano auslesen, wie Fehlimpulse verhindern?

Hallo,

ich habe jetzt mal den seriellen Output meines letzten Sketches eine Weile im realen Zählerbetrieb getestet, und mir ist ein komisches Verhalten aufgefallen, nämlich dass der Zähler an einigen Stellen rückwärts läuft, was ich mir angesichts der Programmlogik nicht erklären kann... Hier die Werte die ausgegeben werden, und die geplottete Grafik. Ich suche gerade im Code rauf und runter aber kann mir keine Stelle ausmalen die erklärt, warum das an den "Plateaus" passiert, habt ihr spontan eine Idee?

4037350
4037402
4037452
4037480
4037544
4037576
4037632
4037670
4037702
4037743
4037774
4037808
4037843
4037870
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037836
4037837
4037874
4037898
4037930
4037952
4037974
4037999
4038030
4038054
4038077
4038108
4038132
4038061
4038061
4038061
4038061
4038061
4038061
4038088
4038122
4038146
4038186
4038214
4038235
4038259
4038285
4038309
4038346
4038368
4038403
4038427
4038453
4038481
4038503
4038542
4038564
4038592
4038513

Ist das exakt der aus Post #14?

Ja genau, ich habe zwar schon weiterprogrammiert, aber diese Änderungen noch nicht "produktiv". Derzeit ist es genau der Stand

Und wieso sieht man dann diese Ausgaben nicht?

Er macht genau einen Rücksprung.

Wahrscheinlich dadurch:

Sorry, hätte ich dazuschreiben sollen dass ich das der Übersichtlichkeit halber auf Zeilen mit Zählerwerten gekürzt habe...

Hmm, das klingt plausibel, ich überarbeite den Code nochmal komplett und berichte dann, danke dir! :slight_smile:

Hallo,
ich bin mir nicht ganz sicher was das soll. Aber hier überschreibst Du den aktuellen counter Stand mit einem alten gespeicherten. Abhängig von ..... ??

Den Zählerstand aus dem Eprom auslesen musst du doch nur einmal machen wenn der Nano neu startet, also vom Setup aus.

Du kannst meines Erachtens auch die ganze Zeitüberwachung de

r Impulse rausnehmen. Wenn Du eine negative Flanke erkennst muss gezählt werden. Das hast Du letztlich mit dem Interupt ganz am Anfang auch so gemacht. Allerdings hast Du Dir dabei irgendwelche Störimpulse eingefangen weil die ISR zu schnell aufgerufen werden konnte. Wenn das jetzt immer noch passieren sollte dann würde ich entweder einen Kondensator einbauen, oder z.B die Lib bounce2 verwenden. Damit kannst Du gleich Flanken erkennen und debuncen. Dann zählst Du jede Flanke einen Impuls hoch. Bei jeweils 1000 mehr speicherst du auf Eprom. Beim Einschalten liest Du den Eprom aus.

Nachtrag

Du kannst counter auch unsigned long machen der kann nicht negativ werden

Wofür du überhaupt den Zählerstand brauchst,
außer um festzustellen, dass du dir durch unnötig komplizierte Programmierung Fehler einbaust,
habe ich noch nicht verstanden.

Sollte der Arduino mal nicht laufen, gehen in jedem Fall Pulse verloren, auch wenn du einen alten Zählerstand im EEPROM gespeichert hast?

Hallo,

so, ich weiß jetzt wo meine "Verluste" herkommen, nachdem ich dank eurer Anregung mein Programm mal wieder auf ein Minimalmaß heruntergebrochen habe (neuer Stand siehe unten), und zwar passiert folgendes:

es handelt sich ja um einen Wärmepumpenzähler, der im Schaltschrank (Sicherungskasten) hängt, von dort führe ich ein serielles Kabel nach draußen zum Arduino. Tja, und nun ratet: jedesmal wenn die Wärmepumpe angeht, resettet der Arduino :frowning:

Ich vermute also, dass entweder irgendwelche Impulse im Zählerkasten oder irgendwas das vom Zähler auf den S0 durchschlägt den Arduino neustarten lässt, nur wie finde ich das raus, und viel wichtiger: wie behebe ich das? Ein besseres (geschirmtes?) Kabel nehmen, und wenn ja, welches? Die "kleinen" Einbrüche kamen daher, dass der Nano beim vorherigen Sketch halt immer den zuletzt im Speicher hinterlegten Zustand genommen hat, und jetzt hab ich das Speichern ganz rausgenommen, und da fängt er dann halt wieder beim Initialwert an.

Aktueller Sketch der Vollständigkeit halber, aber wirklich interessieren würde mich wie ich die Neustartproblematik umgehen kann. Danke für alle Tipps!

#include <EEPROM.h>

#define ADR 8
#define MEASUREPIN 2
long interval = 10000;

long counter;
unsigned long time_now = 0;
byte prevLEDStatus = LOW;
bool counting = false; 
char serialinput;
String valueString;
bool serialBlock = false;

void setup() 
{
  Serial.begin(9600);
  pinMode(MEASUREPIN, INPUT_PULLUP);
  counter = read_counter(ADR);
  pinMode(LED_BUILTIN, OUTPUT);  
}

void loop() 
{
  /*if(Serial.available())
  {
    Serial.setTimeout(4000);
    serialinput = Serial.read();
    if (serialinput == 's')
    {
      Serial.println("Please enter a new counter value to start with: ");
      serialBlock = true;
      valueString = Serial.readStringUntil('s');       
      long received = atol(valueString.c_str());
      if (received > 0)
      {
        counter = received;
        save_counter(ADR, counter);
        Serial.println("received and saved: " + (String)counter);
      } 
      else
      {
        Serial.println("received 0, not saving ");
      }     
      serialBlock = false;
    }
  }*/
  if (serialBlock == false)
  {
    if ( digitalRead(MEASUREPIN) == LOW && counting==false)
    {          
      counting=true;
      //digitalWrite(LED_BUILTIN, HIGH);
    }
    if (digitalRead(MEASUREPIN) == HIGH  && counting==true) 
    {    
      counting = false;
      counter++;      
      //digitalWrite(LED_BUILTIN, LOW); 
    }
    if(millis() > time_now + interval)
    {
      //prevLEDStatus = LOW;
      //digitalWrite(LED_BUILTIN, LOW); 
      time_now = millis();          
      Serial.println(counter);      
    }
  }
}


void save_counter(int adr, long lo) 
{
  EEPROM.put(adr, lo);
} 


long read_counter(int adr) 
{
  long lo=0;

    EEPROM.get(adr, lo);
    return lo;
} 

Hallo,
es gibt da mehrere Möglichkeiten
Stromversorgung , wo & wie versorgst du den Arduino. Steckernetzteil ausserhalb des Schaltschrankes wäre gut.
Induktiv über E/A Lass mal das Kabel zum Zähler weg , startet er dann auch neu. eventuell ein abgechirmtes Kabel verwenden.
Induktiv HF Arduino in eine Pappschachtel setzen die Du mit Alufolie umwickelt hast. Arduino möglichst weit von den Lastkabeln zur Wärmepume entfernen.

Der Arduino ist außerhalb des Zählerkastens, gespeist wird er per USB Kabel von einem Raspberry PI 3, der die Signale weiterverarbeitet. Der Raspi hängt auch an der Wärmepumpe, kann ich irgendwie die Spannungsversorgung vom seriellen trennen um diesen auszuschließen? Derzeit gehen Daten und Stromversorgung beide über den USB zum Raspi.

Den Rest mit geschirmter Box werde ich probieren.

Habt ihr einen Tipp für ein brauchbares geschirmtes Kabel vom s0 zum Arduino? Gerne auch mit Link zu Reichelt pollin oder ähnlichem Shop :grinning:

Hast Du nicht ein Stück altes Netzwerkkabel was Du nicht mehr brauchst.

wichtig wäre esrt mal herauszubekommen ob es über den USB Stecker oder das S0 Kabel oder die "Luft" rein kommt

Dazu kommt wie viel KW hat die Pumpe?
Schetze um die 10KW, das macht bei einschalten Schönen EMV Impuls. Wurde den Ardu auserhalb montieren die Datenleitung irgend wie " Endstören" Ferritkern Optokopler oder was auch immer.

Die Pumpe zieht ca. 2kW im Betrieb, aber ich vermute der Anlaufstrom ist hoch, auch mechanisch spürt man das Ablaufen deutlich... Ich werde wie vorgeschlagen Mal sehen ob's über eines der beiden Kabel kommt oder von extern....

Warum noch einen Arduino dazwischen schalten? Das kann der PI doch nebenher mit erledigen.

So, ich habe jetzt aufgrund der Tipps hier mal mein unisoliertes serielles Kabel gegen ein Cat 5E Kabel getauscht, und der Arduino hat bisher alle Anläufe der Wärmepumpe überlebt, von daher bin ich guter Hoffnung dass das damit erledigt ist, danke nochmal :slight_smile:

Ein Problem habe ich aber noch: die Adtern des Netzwerkkabels sind sehr dünn. und der Wärmepumpenzähler hat einen Klemmanschluß. Ich habe nun die Befürchtung, dass das nicht zuverlässig halten wird und die Adern irgendwann abgehen. Was wäre denn ein sauberer Weg, etwas dickere Verbindungsstifte an das Netzwerkkabel zu bekommen und außerdem eine Zugenlastung, habt ihr mir hierfür Tipps? Wie würdet ihr das produktiv am Arduino selbst machen, derzeit steckt das noch auf dem Breadboard, einfach anlöten, oder gibt's da auch "Best Practices" für?

Zur Frage warum ich das nicht direkt mit dem Raspi mache: da gibt es viele Gründe, aber hauptsächlich weil ich mal Lust hatte was mit nem Arduino zu machen, ist mein erstes Projekt auf dieser Art Hardware, mit Raspis habe ich dagegen schon viel gemacht. Und ich hätte es gerne unabhängig vom Raspi falls ich mal ein anderes System dranhängen will zum Auswerten...

Hallo
Na ja, Aderendhülsen wären eine Variante.

Ich denke mal ein einfacher Weg das vernünftig aufzubauen ist mit einer Lochraster oder Loch-Streifenplatine.
Letztlich ist das Geschmackssache. Allerdings solltest du Löten können. Das Board selbst steckst du am besten auf zwei Pfostenleisten, damit du ihn falls nötig rausnehmen kannst. Die Anschlüsse nach aussen mache ich in der Regel über Schraubklemmen die auf die Platine gelötet werden. Das Ganze baust du z.B in eine Aufputz Veteilerdose ein.

Hallo zusammen,

mein Code aus Post #28 läuft jetzt seit mehreren Tagen ansich problemlos, ich habe hardwareseitig noch das Kabel vom Zählerschrank zum Arduino durch ein geschirmtes CAT5E Kabel ersetzt, Adernendhülsen an beiden Seiten wie hier vorgeschlagen, alles super - eigentlich.

Denn ich habe zwar keine Fehlzählungen mehr, aber mir fehlen einige, sehr wenige Impulse, die sich aber leider aufsummieren. Und zwar kann ich sagen dass ich relativ konstant auf 10.000 Impulse (also 10kWh) etwa 40 Impulse habe die mir fehlen (30 bis 50, 40 im Schnitt, wenn der Zähler also 10.000 auf dem Display stehen hat sind es beim Arduino nur 9.960 - das ist nicht viel, aber ich wüsste gerne woher die Abweichung kommen könnte und hoffe auf eure Ideen, auch wie man hier systematisch bei der Fehlersuche vorgehen könnte. Alle Tipps sind sehr willkommen, vielen Dank!

  • ohne einen Reset zwischendurch? Mach doch mal ein Serial.print in setup (oder so)

if(millis() > time_now + interval)
ist zwar falsch, aber der Fehler kommt est nach 49 Tagen ohne Reset zum Tragen und betrifft nur die zyklischen Serial.print - Ausgaben.

änder das mal in
Serial.begin(115200);
und passe den Seriellen Monitor darauf an.
Fehlt die gleiche Zahl Pulse?

Welchen Zusammenhang vermutest du?
Wenn überhaupt, wäre 9600 sicherer, weil der Arduino dann seltener in einem Interrupt hängt.