3.27. Watchdog-timer

Een watchdog-timer is een stuk hardware dat de microcontroller reset als het draaiende script ooit stopt met deze periodiek aan te porren. Het script “voedt” de watchdog vanuit een plek waarvan het weet dat er gezonde code draait; als een bug, een hang of een onverwachte uitzondering ooit verhindert dat de camera de watchdog binnen een geconfigureerde time-out voedt, reset de chip zichzelf en begint het script opnieuw.

Op een ingezet apparaat zonder mens in de buurt om het uit en aan te zetten, is dit het verschil tussen een tijdelijke bug die binnen seconden herstelt en een onbruikbaar apparaat dat een servicebezoek vereist.

Een grafiek van een watchdog-teller in de tijd. De teller begint bij de time-outwaarde, daalt lineair richting nul en wordt telkens herladen tot de time-out wanneer het script feed() aanroept. Na drie geslaagde feed()- aanroepen heeft een vierde interval geen feed() en bereikt de teller nul, wat een MCU-reset activeert.

De watchdog-teller telt af vanaf zijn time-out. Elke feed() herlaadt hem; als hij nul bereikt, reset de chip.

3.27.1. De machine.WDT-klasse

machine.WDT schakelt de watchdog in en biedt één enkele methode, feed(). Eenmaal gestart kan de watchdog niet meer worden gestopt – de enige uitwegen zijn hem volgens schema voeden of hem de chip laten resetten:

from machine import WDT

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

while True:
    do_work()
    wdt.feed()

De timeout is in milliseconden. De juiste waarde hangt af van hoe lang de langste legitieme iteratie van de hoofdlus duurt, met comfortabele marge – een lus van 100 ms met een time-out van 2 s heeft ruime marge voor een trage iteratie zonder hinderlijke resets.

3.27.2. Waar feed() aan te roepen

Waar feed() zich bevindt is de cruciale ontwerpbeslissing; de watchdog vangt alleen bugs op in de delen van de code die niet tussen voedingen door draaien.

  • Roep aan vanuit de hoofdlus, bovenaan of onderaan. Het meest voorkomende patroon. De watchdog vangt alles op dat de hoofdlus laat hangen – een deadlock, een oneindige while, een randapparaat dat nooit terugkeert – en reset de chip terug in de lus.

  • Roep niet aan vanuit een interrupt-handler. Het doel van de watchdog is om hangs in het normale codepad op te vangen. Een ISR die afgaat ongeacht of de hoofdlus vastzit, zou een watchdog blijven voeden die juist zou moeten afgaan.

  • Roep niet aan binnen een lange blokkerende operatie. Een netwerkverzoek of sensoruitlezing die tien seconden duurt, is precies het soort hang dat de watchdog zou moeten opvangen. Het plaatsen van feed() daarbinnen tenietdoet de bescherming.

Een richtlijn die voor de meeste programma’s werkt: voed één keer per iteratie van de hoofdlus, met de time-out ingesteld op enkele malen de verwachte lusduur. Als een enkele iteratie legitiem langer nodig heeft dan de time-out – bijvoorbeeld een bewuste kalibratiefase – structureer die fase dan als een reeks kleinere brokken met feed() ertussen, of wijzig de time-out met timeout_ms() (waar ondersteund) voordat je hem binnengaat.

3.27.3. Beschikbaarheid

De watchdog is op de meeste OpenMV cams beschikbaar, maar niet op alle – de hardware is op elk onderdeel aanwezig, maar de Python-API is nog niet overal aangesloten. Raadpleeg de OpenMV-boards of probeer een WDT aan te maken en de AttributeError op te vangen als hij niet wordt ondersteund.

Zelfs op cams waar WDT niet beschikbaar is, kan een in het veld ingezet apparaat een softwarematig equivalent gebruiken – een aparte taak of stap in de hoofdlus die de voortgang bewaakt en machine.reset() activeert als er iets vastgelopen lijkt. Het is minder robuust dan een hardware-watchdog (een vastgelopen interrupt-handler kan ook de softwarematige monitor platleggen), maar het dekt dezelfde gevallen op applicatieniveau.