Watchdog lässt sich nicht deaktivieren

Hey!

Ich hab ein Arduino Ethnernet und ein Problem mit dem Watchdog:
Wenn ich mein Watchdog eingerichtet habe und das Programm dann irgendwann auch in ein Timeout geht und mein Arduino resettet, wird die Setup Routine wieder aufgerufen. In der Setup Routine muss ich einiges erledigen, vorallem die SD Karte öffnen (was ewig dauert) aber auch die TCP Verbindung starten etc.etc… deswegen will ich (logischer weise) in der SetUp routine kein Watchdog.

Wenn ich aber nun den Watchdog deaktiviere mit “wdt_disable” bleibt dies wirklungslos. Ich habe im weltweitennetz gelesen, dass dooferweise beim Reset durch den Watchdog auch das Watchdog register zurückgesetzt wird und das Timeout auf B0000000 gesetzt wird (was 16ms sekunden entspricht). Wenn ich am Anfang also statt “wdt_disable” einfach “wdt_enable(WTD0_8S)” eingebe, wird der befehl noch mit ausgeführt, und nach 8 Sekunden in der Setup phase resettet der Watchdog wieder mein Arduino.

Hier also nun meine Frage: Warum kann ich den Watchdog mit wdt_disable nicht deaktiveren?

Hier mal ein Beispiel

#include <Arduino.h>
#include <avr/wdt.h>

const int onboardLED            = 9;

void setup() {

  int k;

  wdt_disable();

  
  
  //nimms raus und es funktioniert! lass es drin, und der Arduino wird nach 16ms resettet
  //trotz wdt_disable!
  delay(2L * 1000L);



  wdt_enable(WDTO_4S);

  pinMode(onboardLED, OUTPUT);


  for (k = 1; k <= 3; k = k + 1) {
    digitalWrite(onboardLED, HIGH);
    delay(250L);
    digitalWrite(onboardLED, LOW);
    delay(250L);
  }
  // delay a bit more so it is clear we are done with setup
  delay(750L);
}

void loop() {

  int k;

  // this loop simply turns the LED on and then waits k*250ms. As k increases, the amount of time
  // increases. Until finally the watch dog timer doesn't get reset quickly enough.
  for (k = 1; k <= 10000; k = k + 1) {
    // at the top of this infinite loop, reset the watchdog timer
    wdt_reset();
    digitalWrite(onboardLED, HIGH);
    delay(k * 250L);
    digitalWrite(onboardLED, LOW);
    delay(250L);
  }
}

Lieben Gruß,
Spider

Watchdog und delay() führen gerne zu Problemen. Also meine Empfehlung: Nur eins von beiden verwenden.


Warum kann ich den Watchdog mit wdt_disable nicht deaktiveren?

Siehe:

Ein Deaktivieren des WDTs ist nicht möglich, wenn die WDTON - Fuse gesetzt ist!

Aus: https://www.mikrocontroller.net/articles/AVR-Tutorial:_Watchdog

Also mein Tipp: Als letzte Aktion in der setup() Den Watchdog aktivieren.

Hey Combie,

Danke schon mal für deine Antwort.

Das Delay sollte hier nur meine Setup Instanz simulieren. Mal dauert das Setup eine Sekunde, kann aber auch mal 10 Sekunden oder mehr dauern.

Das Problem ist, wie oben beschrieben, wenn der Watchdog das System resettet lauf ich sofort wieder in ein Reset, wenn ich den Watchdog erst am ende des Setups starte.

Wie setzte ich denn die WFTON-Fuse mit C zurück? Ich dachte das würde schön wdt_disable() machen?

lg, Spider

gtaspider:
Das Delay sollte hier nur meine Setup Instanz simulieren. Mal dauert das Setup eine Sekunde, kann aber auch mal 10 Sekunden oder mehr dauern.

Kannst Du Dir nicht einen Timer-Interrupt starten, der in so “langen Aktionen” den Watchdog-Reset innerhalb eines Timer-Interrupts durchführt?

Beispielsweise ein Timer-Interrupt, der 10x pro Sekunde feuert.
Vor dem Start der “langen Aktion” (bei Dir also am Anfang von setup()) setzt Du einen Zähler auf einen bestimmten Wert, z.B. 250 würde dann 25 Sekunden entsprechen.

Innerhalb der Timer-Interruptroutine prüfst Du dann, ob der Zähler noch größer als 0 ist, und wenn ja, zählst Du den Zähler eins runter und resettest den Watchdog.

Und wenn der Zähler bei 0 angelangt ist, macht die Interruptroutine nichts mehr und nach dem vollständigen Runterzählen, z.B. erst nach 25 Sekunden plus Watchdog-Timeout, würde der Watchdog-Reset dann zuschlagen.

Hey Jurs,

Danke für deine Antwort!

Ja, das könnte ich auch machen. Problem ist nur, dass ich den Code möglichst abgespeckt haben möchte, und um ein Timer zu machen müsste ich wieder eine neue Bibliothek laden.

Ich verstehe auch einfach nicht, warum es so kompliziert ist einfach den Watchdog für eine gewisse Zeit zu deaktivieren?

Gruß,
Spider

Wie setzte ich denn die WFTON-Fuse mit C zurück? Ich dachte das würde schön wdt_disable() machen?

Genau das geht NICHT! Wenn die Fuse gesetzt ist, dann ist sie gesetzt. Und kein Code der Welt kann den WDT abschalten. Erst eine externer Programmer... Wäre ja auch voll widersinnig. Startest du ihn aus der Software, dann kannst du ihn auch wieder in der Software abschalten.

Kannst Du Dir nicht einen Timer-Interrupt starten, der in so "langen Aktionen" den Watchdog-Reset innerhalb eines Timer-Interrupts durchführt?

Dann kann man ihn auch gleich abgeschaltet lassen... Denn das widerspricht auch dem WDT Gedanken. Und wenn in/während der Initialisierung die Interrupts abgeschaltet werden, dann hilft das auch sowieso nix.

combie: Startest du ihn aus der Software, dann kannst du ihn auch wieder in der Software abschalten.

Aber genau das mache ich doch? Ich starte ihn aus der Software mit wdt_enable(). Vorher war er nicht aktiviert. Jetzt will ich ihn einfach wieder deaktivieren.

Naja, ich hab es jetzt einfach so gelöst, dass ich während des initalisierens acht sekunden timeout habe und zwischen durch den WDT resette.. Sauber ist das zwar nicht, aber wenn man ihn wirklich nicht abschalten kann, dann komm ich wohl nicht drum rum..

Danke trotzdem Gruß, Spider