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).
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 ms | WDTO_15MS |
32 ms | WDTO_30MS |
64 ms | WDTO_60MS |
0,125 s | WDTO_120MS |
0,25 s | WDTO_250MS |
0,5 s | WDTO_500MS |
1.0s | WDTO_1S |
2.0s | WDTO_2S |
4.0s | WDTO_4S |
8.0s | WDTO_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();
}