Hallo,
ich habe nun nach vielen Jahren meine Aquariumsteurung auf etwas modernere Hardware portiert.
Also vom Mega auf einen ESP32. Hauptsächlich weil ich mit dem ESP ohne Klimmzüge ins WLAN komme.
War insgesamt einfacher als gedacht. Vieles konnte ich ohne große Änderungen übernehmen obwohl ich damit nicht das komfortablere API (gerade im Bereich WebServer) des ESPs ausnutze.
Aber umschreiben wäre aufwändiger gewesen. Und warum ohne Not wenn Code seit Jahren problemlos läuft.
Etwas blieb aber übrig. Wenn der Watchdog auslöst logge ich das mit so das ich nach dem Reboot noch in der Statistik habe.
Bei Mega war das kein Thema.
Bei ESP gibt es dem esp_task_wdt_isr_user_handler. Nur wird der leider nicht aufgerufen wenn der
Watchdog zuschlägt. Hat jemand einen Tipp wie man das korrekt macht ?
Code zeige ich hier nicht weil laut Doku muss die Funktion ja einfach nur da sein um aufgerufen zu werden.
//---------------------------------------------------------------------------
// Watchdog routines (name of the dog is Bora :-)
//---------------------------------------------------------------------------
void esp_task_wdt_isr_user_handler(void)
{
Config.BoraBoot = 1;
Config.anzBoraBoots++;
WriteEEPROM();
digitalWrite(WATCHDOG,LED_ON);
}
//---------------------------------------------------------------------------
// Setup the Watchdog for three seconds
//---------------------------------------------------------------------------
void Wdt_Setup()
{
esp_task_wdt_init(3,false); //Init Watchdog with 3 seconds timeout and panicmode
esp_task_wdt_add(NULL);
}
Wdt_Setup() wird aus setup() aufgerufen. Und der Watchdog funktioniert auch.
Laut Doku sollte nun beim Auslösen des Watchdogs die Funktion esp_task_wdt_isr_user_handler
aufgerufen werden. Wird sie aber nicht.
Erst mal danke für die Antwort.
Mit dem extern "C" erhalte ich folgende Fehlermeldungen :
Utilities:448:17: error: conflicting declaration of 'void esp_task_wdt_isr_user_handler()' with 'C' linkage
extern "C" void esp_task_wdt_isr_user_handler(void)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/kandy/sketchbook/AquaMain/AquaMain_V4_ESP32/Utilities.ino:448:6: note: previous declaration with 'C++' linkage
extern "C" void esp_task_wdt_isr_user_handler(void)
Der Sketch verwendet 227149 Bytes (17%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes.
Globale Variablen verwenden 21760 Bytes (6%) des dynamischen Speichers, 305920 Bytes für lokale Variablen verbleiben. Das Maximum sind 327680 Bytes.
Ob es funktioniert kann ich nicht sagen....
So tut man das, wenn man ein Problem hat!
Man zeigt die Problemstelle.
Man zeigt testbaren Code.
Aber wenn du meinst, dass dein Code perfekt ist, ist hier wohl das Gegenteil bewiesen.
Dann landet man eben in diesem Sumpf: Ich weiß, dass es funktioniert, und du weißt nicht warum es bei dir versagt.
Etwas erweitertes Programm beispielsweise aus dieser Quelle:
#include <esp_task_wdt.h>
#define WDT_TIMEOUT 3 // 3 seconds WDT
#define WATCHDOGLED 13
int i = 0;
int last = millis();
extern "C" void esp_task_wdt_isr_user_handler(void)
{
digitalWrite(WATCHDOGLED,!digitalRead(WATCHDOGLED));
i = 0;
}
void setup() {
Serial.begin(115200);
delay(500);
Serial.println("Configuring WDT...");
pinMode(WATCHDOGLED, OUTPUT);
esp_task_wdt_init(WDT_TIMEOUT, false); //enable panic so ESP32 restarts
esp_task_wdt_add(NULL); //add current thread to WDT watch
}
void loop() {
// resetting WDT every 2s, 5 times only
if (millis() - last >= 2000 && i < 5) {
Serial.println("Resetting WDT...");
esp_task_wdt_reset();
last = millis();
i++;
if (i == 5) {
Serial.println("Stopping WDT reset. CPU should reboot in 3s");
}
}
}
Serieller Monitor:
13:54:38.235 -> Configuring WDT...
13:54:39.683 -> Resetting WDT...
13:54:41.673 -> Resetting WDT...
13:54:43.680 -> Resetting WDT...
13:54:45.686 -> Resetting WDT...
13:54:47.692 -> Resetting WDT...
13:54:47.692 -> Stopping WDT reset. CPU should reboot in 3s
13:54:50.677 -> E (26063) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
13:54:50.677 -> E (26063) task_wdt: - loopTask (CPU 1)
13:54:50.677 -> E (26063) task_wdt: Tasks currently running:
13:54:50.677 -> E (26063) task_wdt: CPU 0: IDLE
13:54:50.677 -> E (26063) task_wdt: CPU 1: loopTask
13:54:50.717 -> E (26063) task_wdt: Print CPU 0 (current core) backtrace
13:54:50.717 ->
13:54:50.717 ->
13:54:50.717 -> Backtrace: 0x400D89A3:0x3FFBEA8C |<-CORRUPTED
13:54:50.717 ->
13:54:50.717 -> E (26063) task_wdt: Print CPU 1 backtrace
13:54:50.717 ->
13:54:50.717 ->
13:54:50.717 -> Backtrace: 0x400832FD:0x3FFBF2BC |<-CORRUPTED
13:54:50.717 ->
13:54:50.717 -> Resetting WDT...
13:54:52.720 -> Resetting WDT...
13:54:54.726 -> Resetting WDT...
13:54:56.732 -> Resetting WDT...
13:54:58.738 -> Resetting WDT...
13:54:58.738 -> Stopping WDT reset. CPU should reboot in 3s
13:55:01.709 -> E (37102) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
13:55:01.709 -> E (37102) task_wdt: - loopTask (CPU 1)
13:55:01.709 -> E (37102) task_wdt: Tasks currently running:
13:55:01.756 -> E (37102) task_wdt: CPU 0: IDLE
13:55:01.756 -> E (37102) task_wdt: CPU 1: loopTask
13:55:01.756 -> E (37102) task_wdt: Print CPU 0 (current core) backtrace
13:55:01.756 ->
13:55:01.756 ->
13:55:01.756 -> Backtrace: 0x400D89A3:0x3FFBEA8C |<-CORRUPTED
13:55:01.756 ->
13:55:01.756 -> E (37102) task_wdt: Print CPU 1 backtrace
13:55:01.756 ->
13:55:01.756 ->
13:55:01.756 -> Backtrace: 0x400832FD:0x3FFBF2BC |<-CORRUPTED
13:55:01.756 ->
Für mich sieht das gut aus. (IDE 1.8.19, ESP32 Core 2.0.6)
Etwas irritiert bin ich, weil ich im weltweiten Netz auf die Schnelle nichts Vergleichbares finde und das Beispiel ESP32/examples/Timer/WatchdogTimer/WatchdogTimer.ino mit einem "normalen" Timer arbeitet
So. Vielen Dank.
Wenn ich die Externdefinition des Handlers in das "Hauptmodul" des Sketches packe ist
die Fehlermeldung weg und auch der Handler wird aufgerufen.
Aber ist leider untauglich. Ich kann gerade eine LED togglen und nichts in den Zustand
nach dem Boot herüberretten (ohne schmutzige Tricks).
Schreiben ins LittleFS gelingt nicht mehr und sogar ein delay wird nicht mehr ausgeführt.
Der Reboot knallt noch mitten in den Handler.
Werde mir was eigenes mit einem Timer schreiben.
Den Watchdog hatte ich auf dem Mega damals eingeführt weil ich mal ein Netzwerkshield benutzt
hatte dessen Librarie Bugs hatte. Das Dingen hing sich bei Zugriffen von Außen auf die Website
schon mal weg. Das Problem war mit einem anderen Shield dann weg den WD habe ich gelassen.
Man weiß ja nie ;-).
Das klappt aber scheinbar nur mit "DeepSleep".
Aus dem Watchdog oder auch aus meinem selbstgebauten WD mit Timer ist das Teil
nach dem Reset wieder auf 0 !
Ich werde schon eine Lösung finden. Auch die "Preferences" kann ich im Interrupt oder dem
WD-Callback leider nicht schreiben.
#define WATCHDOG_TIMEOUT 3
RTC_DATA_ATTR int BoraBoot = 0;
//---------------------------------------------------------------------------
// Watchdog routines (name of the dog is Bora :-)
//---------------------------------------------------------------------------
extern "C" void esp_task_wdt_isr_user_handler()
{
BoraBoot = 1;
ESP.restart();
}
//---------------------------------------------------------------------------
// Setup the Watchdog for three seconds
//---------------------------------------------------------------------------
void BoraSetup()
{
esp_task_wdt_init(WATCHDOG_TIMEOUT,false); //Init Watchdog with 3 seconds timeout and panicmode
esp_task_wdt_add(NULL);
}
Auch ein RTC_NOINIT_ATTR vor der Variablen bringt es nicht.
Mit diesem Attribut steht immer etwas != 0 in der Variablen.
Oder muss man die RCA_DATA_ATTR Variable an einer bestimmte Stelle deklarieren ?
"A quick note at the end: the ESP32 handles RTC memory differently (clear on boot), so this method does not work there. The author likes to hear of ESP32 veterans on how to reproduce the functionality on an ESP32."