3.27. Watchdog időzítő

A watchdog időzítő egy olyan hardver, amely újraindítja a mikrokontrollert, ha a futó szkript valaha is abbahagyja annak rendszeres megpiszkálását. A szkript onnan „eteti” a watchdogot, ahol tudja, hogy egészséges kód fut; ha egy hiba, egy lefagyás vagy egy váratlan kivétel valaha is megakadályozza a kamerát abban, hogy a watchdogot a beállított időkorláton belül megetesse, a chip újraindítja magát, és a szkript elölről kezdődik.

Egy olyan telepített eszközön, ahol nincs a közelben ember, aki ki-be kapcsolná, ez jelenti a különbséget egy átmeneti hiba között, amely másodperceken belül helyreáll, és egy téglává vált eszköz között, amely szervizhívást igényel.

Egy watchdog-számláló grafikonja az idő függvényében. A számláló az időkorlát értékéről indul, lineárisan csökken nulla felé, és minden alkalommal újratöltődik az időkorlátra, amikor a szkript meghívja a feed() metódust. Három sikeres feed() hívás után egy negyedik intervallumban nincs feed(), és a számláló eléri a nullát, MCU-újraindítást váltva ki.

A watchdog-számláló az időkorlátjáról számol visszafelé. Minden feed() újratölti; ha eléri a nullát, a chip újraindul.

3.27.1. A machine.WDT osztály

A machine.WDT engedélyezi a watchdogot, és egyetlen metódust tesz elérhetővé, a feed() metódust. Egyszer elindítva a watchdog nem állítható le – az egyetlen kiút az ütemezett etetése vagy az, hogy hagyod, hogy újraindítsa a chipet:

from machine import WDT

wdt = WDT(timeout=2000)    # reset if not fed within 2 seconds

while True:
    do_work()
    wdt.feed()

A timeout ezredmásodpercben van megadva. A megfelelő érték attól függ, mennyi ideig tart a fő ciklus leghosszabb jogos iterációja, kényelmes ráhagyással – egy 100 ms-os ciklusnak 2 s-os időkorláttal bőven van mozgástere egy lassú iterációhoz, anélkül hogy fölösleges újraindítások történnének.

3.27.2. Hol hívd meg a feed()-et

Az, hogy a feed() hol helyezkedik el, a kritikus tervezési döntés; a watchdog csak a kód azon részeinek hibáit fogja meg, amelyek nem futnak le az etetések között.

  • Hívd meg a fő ciklusból, a tetején vagy az alján. A leggyakoribb minta. A watchdog elkap mindent, ami lefagyasztja a fő ciklust – egy holtpontot, egy végtelen while-t, egy soha vissza nem térő perifériát – és visszaindítja a chipet a ciklusba.

  • Ne hívd meg megszakításkezelőből. A watchdog lényege, hogy a normál kódútvonal lefagyásait fogja el. Egy ISR, amely attól függetlenül lefut, hogy a fő ciklus elakadt-e, folyamatosan etetne egy watchdogot, amelynek ki kellene váltania az újraindítást.

  • Ne hívd meg egy hosszú blokkoló művelet belsejéből. Egy hálózati kérés vagy érzékelő-leolvasás, amely tíz másodpercig tart, pontosan az a fajta lefagyás, amelyet a watchdognak el kellene kapnia. Ha a feed() hívást belerakod, az kijátssza a védelmet.

Egy iránymutatás, amely a legtöbb programnál működik: etesd egyszer fő ciklus iterációnként, az időkorlátot a várt ciklusidő többszörösére állítva. Ha egyetlen iteráció jogosan tovább tart, mint az időkorlát – mondjuk egy szándékos kalibrációs fázis –, strukturáld azt a fázist kisebb darabok sorozataként, közöttük feed() hívásokkal, vagy a belépés előtt változtasd meg az időkorlátot a timeout_ms() segítségével (ahol támogatott).

3.27.3. Elérhetőség

A watchdog a legtöbb OpenMV kamerán elérhető, de nem mindegyiken – a hardver minden alkatrészen jelen van, de a Python API még nincs mindenhol bekötve. Nézd meg a OpenMV kártyák oldalt, vagy próbálj meg létrehozni egy WDT példányt, és kapd el az AttributeError hibát, ha nem támogatott.

Még azokon a kamerákon is, ahol a WDT nem érhető el, egy terepre telepített eszköz használhat egy szoftveres megfelelőt – egy különálló feladatot vagy fő ciklus lépést, amely figyeli az előrehaladást, és kiváltja a machine.reset() függvényt, ha bármi elakadtnak tűnik. Ez kevésbé robusztus, mint egy hardveres watchdog (egy elakadt megszakításkezelő a szoftveres figyelőt is leránthatja), de ugyanazokat az eseteket fedi le alkalmazásszinten.