NodeMCU (ESP8266) Watchdog - wie geht das?

Hallo zusammen,

ich habe da auch mal eine Verständnisfrage. Wahrscheinlich reicht mein rudimentäres Englisch (ich gehe im 2. Halbjahr zur Volkshochschule - Rentnerkurs) nicht aus, um es zu verstehen.
Zur Problemstellung: Ich messe aller 15 Minuten (per millis) einige Werte und sende sie zu einer fernen MySQL-DB. Wenn da ein Timeout auftritt (MySQL-Lib erweitert) wird neu gebootet. Das funktioniert. Durch die Zwangstrennung automatisch getestet.

Falls das Ganze irgend wo anders hängt, würde ich gern nach 20 Minuten einen Reboot erzwingen. Dafür wäre nach meiner Meinung der Watchdog sinnvoll. Den habe ich bisher aber nicht verstanden. Könnte mich da jemand auf die Schiene heben, wie ich einen Watchdog auf 20 Minuten nicht Messen erstelle und den ein-/aushänge.

Gruß Tommy

Der ESP WDT ist ein Spezialist....

Er ist nicht abschaltbar, also immer aktiv.
Die maximale Reaktionszeit ist deutlich kürzer, als deine Wunsch 20 Minuten.
8 Sekunden. Maximal, soweit mir bekannt...

Bei jedem Loop() Durchlauf und auch während delay() wird sys_yield() o.ä. aufgerufen.
Dabei wird auch gleich ein WDT Reset ausgeführt.

Der WDT ist also höchst vermutlich die falsche Kanone für deine Zwecke.

Danke für die Info, dann kann ich die Idee mit den 20 Minuten begraben. Ich muss also irgendwas aller < 8 Sekunden tun, um ihn ruhig zu halten.
Wie kann man das anstellen? Millis ok, aber wie muss ich ihn einrichten und ruhig halten?

Gruß Tommy

Ruhig gehalten wird er indem vor Ablauf der eingestellten Zeit (15ms bis 8 Sek.) dieser Befehl durchlaufen wird:

wdt_reset(); // Watchdog zurückstellen. Deaktivieren mit "wdt_disable();"

Eingerichtet wird er damit:

wdt_enable(WDTO_500MS); // Watchdog auf 500MilliSek. einstellen
// möglich sind. 15/30/60/120/250/500MS oder 1/2/4/8S

Und ne Librery braucht er auch:

#include <avr/wdt.h> // Librarie für den Watchdog

Hallo Tommy56,

guck dir mal die TimeAlarms Lib an.

Alarm.timerRepeat(seconds, function);
Damit kannst du alle 1200 Sekunden die Funktion deiner Wahl "setup();" aufrufen.

gruß

Ich danke Euch für Eure Hinweise.

Gestern habe ich einen 12V/10A Kleinkompressor an einem umgebauten PC-Netzteil in der Nähe des NodeMCU getestet und damit wahrscheinlich soviele Störungen erzeugt, dass er hängen geblieben ist.
Da hätte ja der Watchdog eigentlich schon zuschlagen müssen, wenn er nicht abgeschaltet werden kann oder habe ich da was falsch verstanden?

Gruß Tommy

#include <avr/wdt.h> // Librarie für den Watchdog

Wird auf dem ESP nicht funktionieren.

Deaktivieren mit "wdt_disable();"

Wird auf dem ESP nicht funktionieren.

Da hätte ja der Watchdog eigentlich schon zuschlagen müssen, wenn er nicht abgeschaltet werden kann oder habe ich da was falsch verstanden?

Wenn der WDT zuschlägt siehst du das bei den BootMeldungen.
Da wird dir der ResetGrund mitgeteilt.

combie:
Wenn der WDT zuschlägt siehst du das bei den BootMeldungen.
Da wird dir der ResetGrund mitgeteilt.

Er hat aber nicht resetet, sondern ist 1,5 h in der Messroutine hängen geblieben (LED an und keine Sätze an DB geschickt) bis ich ihm kurz den Strom geklaut habe.
Hier der Sketch:

// zyperngras
/* Überwachung Zyperngras Belegung NodeMCU
 
  GPIO4   (A0) Analog in Wasservorrat
  GPIO15  (D8) Spannung für Wasservorrat
  GPIO14  (D5) Spannung für Feuchte
  GPIO13  (D7) Input Feuchte (Interrupt Frequenzmessung)
  GPIO12  (D6) (LED)
  GPIO4   (D2) I2C SDA
  GPIO5   (D1) I2C SCL
*/
#include <Wire.h>  
#include <SHT21.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <MySQL.h>

#include "settings.h"

//#define debug

#ifdef debug
#define sbeg Serial.begin(115200);
#define sp Serial.print
#define spn Serial.println
#else
#define sp 
#define spn 
#define sbeg  
#endif

const byte LED = D6;
const uint32_t MESSINTERVALL = 15 * 60 * 1000;  // 15 Minuten
byte isBoot = 1;

SHT21 SHT21;
Connector my_conn;
float luftfeuchte, temperatur, vorrat, feuchte;
int pumpe, valCnt;

void setup() {
char puffer[40];
int erg;
  digitalWrite(LED,LOW);
  pinMode(LED,OUTPUT);
  sbeg(115200);
  spn("\nStart");
  SHT21.begin();
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    sp(".");
  }
  
  spn("\nConnected to Wifi. Connecting to database . . .");
  if (my_conn.mysql_connect(dbhost, 3306, user, dbpassword)) {
    spn("DB-Connection ok.");
    delay(500);
  }
  else
    spn("DB-Connection failed.");
  strcpy(puffer,"use ");
  strcat(puffer,db);
  erg = my_conn.cmd_query(puffer);
  sp("Ergebnis: "); spn(erg);
  spn(puffer);

}

///////////////////// DB-Hilfefunktionen ////////////////////////////
// fügt Komma vor Value ein
void addSeperator(char *buf) {
  if (valCnt != 0) {
    strcat(buf,",");
  }
  valCnt++;
}

void appendFloatVal(char *buf, const float val, int nachkomma = 2) {
char lbuf[20];  
  addSeperator(buf);
  // Länge 1, damit keine führenden Blank angelegt werden
  dtostrf(val,1,nachkomma,lbuf);
  strcat(buf,lbuf);
}


void appendIntVal(char *buf, const int val) {
char lbuf[20];  
  addSeperator(buf);
  strcat(buf,itoa(val,lbuf,10));
}

///////////////////// Messen ///////////////////////////////////////////
void senden() {
char puffer[80];
int erg;
boolean isTimeOut;
  // SQL-Statement 
  valCnt = 0;
  strcpy(puffer, "insert into pflanze values (now(),");
  appendFloatVal(puffer,feuchte);  
  appendFloatVal(puffer,temperatur);  
  appendFloatVal(puffer,luftfeuchte);  
  appendFloatVal(puffer,vorrat);
  appendIntVal(puffer,pumpe);
  appendIntVal(puffer,isBoot);
  strcat(puffer,")");
  spn(puffer);  
  erg = my_conn.cmd_query(puffer);
  sp("Ergebnis: "); spn(erg);
  // Wenn Verbindung weg, Neustart versuchen
  isTimeOut = my_conn.isTimeout();
  if (isTimeOut) ESP.restart();
}

void messen() {
static uint32_t lastMillis = -MESSINTERVALL;
uint32_t aktMillis;
boolean isTimeOut;
  aktMillis = millis();
  // wenn Zeit nicht rum nix tun
  if (!(aktMillis - lastMillis >= MESSINTERVALL)) return;
  digitalWrite(LED,HIGH);
  lastMillis = aktMillis;
  luftfeuchte = SHT21.getHumidity();
  temperatur = SHT21.getTemperature();
  
  sp("Humidity(%RH): ");
  sp(luftfeuchte);
  sp("     Temperature(C): ");
  spn(temperatur);
  senden();
  isBoot = 0;
  digitalWrite(LED,LOW);
}

void loop() {
  messen();
}

Gruß Tommy

Hallo Tommy56,

nach dem Programmupload bleibt der ESP bei einem WDT Auslöser hängen.
Wenn der ESP mit der Reset-Taste gestartet wird, bootet er bei einem WDT Auslöser neu, und das
Programm beginnt neu. Das ist ein großes Problem, aber leider nicht zu ändern.

Am Besten mit einem kleinen Testprogramm ausprobieren, hier gibt es gute Info dazu:
https://www.sigmdel.ca/michel/program/esp8266/arduino/watchdogs_en.html

Wenn du eine bessere Lösung für eine zuverlässige Überwachung findest, dann lasse es mich
bitte wissen.

Gruß Hans

Hallo,

Tommy56:
Er hat aber nicht resetet, sondern ist 1,5 h in der Messroutine hängen geblieben (LED an und keine Sätze an DB geschickt) bis ich ihm kurz den Strom geklaut habe.

Dann ist er ja eigentlich nicht abgestürzt sondern wohl irgendwo in eine Endlosschleife geraten, z.B. weil er auf was vom Sensor gewartet hat, was nie kam wegen eines Störimpulses o.ä.
Da kannst Du dann wohl eher in die SHT-Routinen eingreifen und ein Timeout einbauen. Auch ein normaler Timerinterrupt, den Du einhängst bevor Du den SHT abfragst oder die Messroutine aufrufst dprfte da gehen, Muß eben zu schlagen, wenn er dort länger braucht als maximal zu erwarten ist. Wie Du da dann einen sinnvollen Zustand wieder bekommst, mußt Du schauen, notfalls eben Software-Reset für den ESP.

Er ist ja in solche einem Zustand immernoch normal in Betrieb und arbeitet das ja dann auch ab.
Ist letztlich auch nur ein Software-Watchdog und der reicht in solchen Betriebszuständen doch aus.

Gruß aus Berlin
Michael

Danke für die Tipps, aber habt ihr mal aufs Datum meines letzten Beitrags geschaut?

Gruß Tommy

Hallo,

Tommy56:
Danke für die Tipps, aber habt ihr mal aufs Datum meines letzten Beitrags geschaut?

nööööö...

Gruß aus Berlin
Michael