Arduino Watchdog

Az Arduino rendelkezik egy olyan funkcióval, amely segít az Arduino program olyan váratlan hibáinak kezelésére, amikor a program nem válaszol, végtelen ciklusba kerül, lefagy. Ez a watchdog timer (WDT).

UNO R3 Mikrocontroller USB-Kábellel
UNO R3 Mikrocontroller USB-Kábellel hirdetés

Az Arduino Watchdog időzítője is megszakítást használ. Ha a Arduino program nem válaszol ameddig a Watchdog beállított időzítője túlcsordul, akkor a Watchdog újraindítja a mikrovezérlőt.

A Watchdog használatához szükségünk van az AVR Watchdog könyvtárra, hívjuk meg az Arduino vázlat elején.

#include <avr/wdt.h>

A watchdog használatához három funkcióra van szükségünk. A wdt_enable(time) függvény segítségével engedélyezzük a Watchdog használatát.

wdt_enable(time)

A paraméterben megadjuk azt az időt, ami letelte után a watchdog újraindítja a processzort. Ezt az időt úgy kell meghatározni, hogy bőven elég legyen a loop() ciklusban lévő program lefutásához.

A Watchdog időzítő különböző időbeállításokkal engedélyezhető. A Watchdog könyvtár tartalmazza a használható konstans értékeket. Ezeknek a konstansoknak az értéke 16ms és 8s között van az alábbi táblázat szerint.

IdőKonstans név
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

A wdt_disable() függvény segítségével leállíthatjuk a Watchdog felügyeletét.

wdt_disable();

A wdt_reset() függvényt általában a loop() elején kell meghívni . Normális esetben minden loop() ciklusban lefut és visszaállítja a watchdog időzítő számlálóját. Ha az Arduino programunk bármilyen ok miatt megakad, a wdt_reset() függvény nem tudja visszaállítani a Watchdog időzítőjét, az Arduino újraindul.

#include <avr/wdt.h>

void setup()
{
  wdt_enable(WDTO_8S); // 8 másodperces időzítő bekapcsolása
}

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

  // Az Arduino főprogramja...
}

Hosszabb, időigényesebb program esetén, a kritikus programrészben el kell helyeznünk ismét a wdt_reset() függvényt.

A következő példakód egy talajnedvesség érzékelővel ellátott öntözőrendszer vezérlését mutatja be. Ez a kód nem feltétlenül életszerű, de a watchdog használatát jól szemlélteti.

#include <avr/wdt.h>

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

int sensorValue = 0;


void setup()
{
  // Watchdog engedélyezése 4 másodperces időkorláttal
  wdt_enable(WDTO_4S);
  
  Serial.begin(9600);
  
  pinMode(motorValve, OUTPUT);
  digitalWrite(motorValve, LOW);
}

void loop()
{
  // Watchdog reset
  wdt_reset();   
  
  // Beolvassuk az érzékelő értékét
  sensorValue = analogRead(sensorPin);
  
  // Ha az érzékelő értéke lecsökken
  if(sensorValue < 50)
  {
    // A motoros szelep kinyitásával megkezdjük a locsolást
    digitalWrite(motorValve, HIGH);
  
    // Megvárjuk amíg a talaj elég nedves lesz.
    // A ciklus addig fut, amíg az érzékelő értéke legalább 100 lesz.
    while(sensorValue >= 100)
    {
      // Újraindítjuk a Watchdog időzítőjét, mert nem tudjuk,
      // hogy az érzékelő értéke mikor éri el a 100-as értéket
      wdt_reset();
	
      delay(1000);
	
      // ismét beolvassuk az érzékelő értékét
      sensorValue = analogRead(sensorPin);
    }
    // Ha az érzékelő értéke elérte a 100-as értéket kilép a ciklusból
    // és elzárjuk a vizet
    digitalWrite(motorValve, LOW);
  }
  
  // Kiírjuk a soros portra a szenzor értékét.
  Serial.println(sensorValue);
  
  delay(1000);
}

A Watchdog időzítő nem csak az Arduino program váratlan hibáiból eredő lefagyások kezelésére szolgál. A Watchdog időzítő folyamatosan fut az Arduino alvó állapotában is, ezért alkalmas az Arduino időnkénti felébresztésére.

Akkumulátoros táplálású projektekben törekednünk kell az energiatakarékosságra. A Watchdog segít ebben is.

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

const char ledPin = 13;

void setup()
{
// A watchdog időzítőjét 8 másodpercre állítjuk
  wdt_enable(WDTO_8S);

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


void loop()
{
  // Visszaállítjuk a Watchdog időzítőt
  wdt_reset();
  
  // Két másodpercre bekapcsoljuk a fedélzeti LED-et
  digitalWrite(ledPin, HIGH);
  delay(2000);
  digitalWrite(ledPin, LOW);


  // Használhatjuk például érzékelők adatainak feldolgozására
  // Majd alvó módba küldjük, hogy emergiát takarítsunk meg.
  
  // Kiválasztjuk a power down módot 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // Majd aludni küldjük a processzort
  sleep_mode();
}