Arduino-Watchdog

Arduino verfügt über eine Funktion, die hilft, mit unerwarteten Fehlern im Arduino-Programm umzugehen, wenn das Programm nicht reagiert, in eine Endlosschleife gerät oder einfriert. Dies ist der Watchdog-Timer (WDT).

AZDelivery-ATmega328 Mikrocontroller Board mit USB-Kabel
AZDelivery-ATmega328 Mikrocontroller Board mit USB-Kabel
Werbung

Der Arduino Watchdog-Timer verwendet ebenfalls einen Interrupt. Wenn das Arduino-Programm nicht reagiert, bis der eingestellte Timer des Watchdogs überläuft, startet der Watchdog den Mikrocontroller neu.

Um Watchdog nutzen zu können, benötigen wir die AVR Watchdog-Bibliothek, rufen wir sie am Anfang des Arduino-Sketches auf.

#include <avr/wdt.h>

Um Watchdog nutzen zu können, benötigen wir drei Funktionen. Verwenden wir die Funktion wdt_enable(time), um die Verwendung von Watchdog zu aktivieren.

wdt_enable(time)

Im Parameter geben wir die Zeit an, nach der der Watchdog den Prozessor neu startet. Diese Zeit muss so definiert werden, dass sie ausreicht, um das Programm in der Schleife „loop()“ auszuführen.

Der Watchdog-Timer kann mit verschiedenen Zeiteinstellungen aktiviert werden. Die Watchdog-Bibliothek enthält die konstanten Werte, die verwendet werden können. Der Wert dieser Konstanten liegt gemäß der folgenden Tabelle zwischen 16 ms und 8 s.

ZeitKonstanter Name
16 msWDTO_15MS
32 msWDTO_30MS
64 msWDTO_60MS
0,125 sWDTO_120MS
0,25 sWDTO_250MS
0,5 sWDTO_500MS
1,0sWDTO_1S
2,0sWDTO_2S
4,0sWDTO_4S
8,0sWDTO_8S

Mit Hilfe der Funktion wdt_disable() können wir die Überwachung des Watchdogs stoppen.

wdt_disable();

Die Funktion wdt_reset() sollte normalerweise am Anfang von loop() aufgerufen werden. Normalerweise wird jede loop()-Schleife ausgeführt und der Watchdog-Timer-Zähler zurückgesetzt. Wenn unser Arduino-Programm aus irgendeinem Grund abstürzt, kann die Funktion wdt_reset() den Watchdog-Timer nicht zurücksetzen, der Arduino wird neu gestartet.

#include <avr/wdt.h>

void setup()
{
  wdt_enable(WDTO_8S); // 8 Sekunden Watchdog-Timer aktivieren
}

void loop()
{
  wdt_reset(); // Watchdog reset

  // Das Arduino-Hauptprogramm...
}

Bei einem längeren, zeitintensiveren Programm muss die Funktion wdt_reset() erneut im kritischen Programmabschnitt platziert werden.

Der folgende Beispielcode zeigt die Steuerung eines Bewässerungssystems mit einem Feuchtesensor. Dieser Code ist nicht unbedingt praktisch, veranschaulicht aber die Verwendung von Watchdog.

#include <avr/wdt.h>

const char motorValve = 13;
const char sensorPin = A0;

int sensorValue = 0;


void setup()
{
  // Watchdog Aktivieren mit 4-Sekunden-Timeout
  wdt_enable(WDTO_4S);
  
  Serial.begin(9600);
  
  pinMode(motorValve, OUTPUT);
  digitalWrite(motorValve, LOW);
}

void loop()
{
  // Zurücksetzen des Watchdog
  wdt_reset();   
  
  // Lesen wir den Wert des Sensors ab
  sensorValue = analogRead(sensorPin);
  
  // Wenn der Sensorwert abfällt
  if(sensorValue < 50)
  {
    // Wir beginnen der Bewässerung, mit das motorisierte Ventil öffnen
    digitalWrite(motorValve, HIGH);
  
    // Wir warten, bis der Boden ausreichend feucht ist.
    // Der Zyklus läuft so lange, bis der Sensorwert mindestens 100 beträgt.
    while(sensorValue >= 100)
    {
      // Wir starten den Watchdog-Timer neu, da wir nicht wissen, 
      // wann der Sensorwert 100 erreichen wird
      wdt_reset();
	
      delay(1000);
	
      // Lesen wir den Sensorwert wieder ab
      sensorValue = analogRead(sensorPin);
    }
    // Erreicht der Wert des Sensors 100, wird der Zyklus verlassen
    // und das Wasser abstellen
    digitalWrite(motorValve, LOW);
  }
  
  // Wir schreiben den Wert des Sensors auf die serielle Schnittstelle.
  Serial.println(sensorValue);
  
  delay(1000);
}

Der Watchdog-Timer wird nicht nur zur Behandlung von Einfrierungen verwendet, die durch unerwartete Fehler im Arduino-Programm verursacht werden. Der Watchdog-Timer läuft kontinuierlich, auch wenn der Arduino schläft, und eignet sich daher, um den Arduino gelegentlich aufzuwecken.

Bei batteriebetriebenen Projekten müssen wir bestrebt sein, Energie zu sparen. Watchdog hilft auch dabei.

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

const char ledPin = 13;

void setup()
{
// Wir haben den Watchdog-Timer auf 8 Sekunden eingestellt
  wdt_enable(WDTO_8S);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}


void loop()
{
  // Wir setzen den Watchdog-Timer zurück
  wdt_reset();
  
  // Wir schalten die Onboard-LED für zwei Sekunden ein
  digitalWrite(ledPin, HIGH);
  delay(2000);
  digitalWrite(ledPin, LOW);


  // Wir können damit beispielsweise Sensordaten verarbeiten
  // Dann versetzen wir es in den Schlafmodus, um Energie zu sparen.
  
  // Wir wählen den Power-Down-Modus 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // Dann schicken wir den Prozessor in den Schlafmodus
  sleep_mode();
}