3.27. Temporizator de supraveghere (watchdog)¶
Un temporizator de supraveghere (watchdog) este o piesă hardware care resetează microcontrolerul dacă scriptul în execuție încetează vreodată să îl mai impulsioneze periodic. Scriptul „hrănește” watchdog-ul dintr-un loc despre care știe că rulează cod sănătos; dacă un bug, o blocare sau o excepție neașteptată împiedică vreodată camera să hrănească watchdog-ul în limita unui timeout configurat, cipul se resetează singur și scriptul pornește din nou.
Pe un dispozitiv implementat fără niciun om în apropiere care să îl realimenteze, aceasta este diferența dintre un bug tranzitoriu care își revine în câteva secunde și o blocare totală care necesită o intervenție de service.
Contorul watchdog-ului scade de la valoarea timeout-ului său. Fiecare feed() îl reîncarcă; dacă ajunge la zero, cipul se resetează.¶
3.27.1. Clasa machine.WDT¶
machine.WDT activează watchdog-ul și expune o singură metodă, feed(). Odată pornit, watchdog-ul nu poate fi oprit – singurele căi de ieșire sunt hrănirea lui conform programului sau lăsarea lui să reseteze cipul:
from machine import WDT
wdt = WDT(timeout=2000) # reset if not fed within 2 seconds
while True:
do_work()
wdt.feed()
Valoarea timeout este în milisecunde. Valoarea potrivită depinde de cât durează cea mai lungă iterație legitimă a buclei principale, cu o marjă confortabilă – o buclă de 100 ms cu un timeout de 2 s are o marjă amplă pentru o iterație lentă, fără reseturi nedorite.
3.27.2. Unde să apelezi feed()¶
Locul unde se află feed() este decizia critică de proiectare; watchdog-ul prinde doar bug-urile din părțile codului care nu rulează între hrăniri.
Apelează din bucla principală, la început sau la sfârșit. Cel mai comun model. Watchdog-ul prinde orice blochează bucla principală – un deadlock, un
whileinfinit, un periferic care nu returnează niciodată – și resetează cipul înapoi în buclă.Nu apela dintr-un handler de întrerupere. Scopul watchdog-ului este de a prinde blocările pe calea de cod normală. Un ISR care se declanșează indiferent dacă bucla principală este blocată ar continua să hrănească un watchdog care ar trebui să se declanșeze.
Nu apela din interiorul unei operații lungi care blochează. O cerere de rețea sau o citire de senzor care durează zece secunde este exact genul de blocare pe care watchdog-ul ar trebui să o prindă. Plasarea lui
feed()în interiorul ei anulează protecția.
O recomandare care funcționează pentru majoritatea programelor: hrănește o dată per iterație a buclei principale, cu timeout-ul setat la de câteva ori durata așteptată a buclei. Dacă o singură iterație are nevoie în mod legitim de mai mult timp decât timeout-ul – de exemplu o fază de calibrare deliberată – structurează acea fază ca o serie de bucăți mai mici cu feed() între ele, sau schimbă timeout-ul cu timeout_ms() (acolo unde este suportat) înainte de a intra în ea.
3.27.3. Disponibilitate¶
Watchdog-ul este expus pe majoritatea camerelor OpenMV, dar nu pe toate – hardware-ul este prezent pe fiecare componentă, dar API-ul Python nu este încă conectat peste tot. Verifică Plăci OpenMV sau încearcă să construiești un WDT și prinde AttributeError dacă nu este suportat.
Chiar și pe camerele unde WDT nu este expus, un dispozitiv implementat pe teren poate folosi un echivalent software – o sarcină separată sau un pas al buclei principale care monitorizează progresul și declanșează machine.reset() dacă ceva pare blocat. Este mai puțin robust decât un watchdog hardware (un handler de întrerupere blocat poate doborî și monitorul software), dar acoperă aceleași cazuri la nivelul aplicației.