3.27. Temporizador watchdog¶
Um temporizador watchdog é um componente de hardware que reinicia o microcontrolador se o script em execução parar de o verificar periodicamente. O script «alimenta» o watchdog a partir de algum ponto onde sabe que está a executar código saudável; se um bug, um bloqueio ou uma exceção inesperada impedirem a câmara de alimentar o watchdog dentro de um timeout configurado, o chip reinicia-se e o script começa do início.
Num dispositivo em produção sem ninguém por perto para fazer um ciclo de energia, esta é a diferença entre um bug transitório que se recupera em segundos e um tijolo que precisa de uma chamada de serviço.
O contador watchdog diminui a partir do seu timeout. Cada feed() recarrega-o; se chegar a zero, o chip reinicia.¶
3.27.1. A classe machine.WDT¶
machine.WDT ativa o watchdog e expõe um único método, feed(). Uma vez iniciado, o watchdog não pode ser parado – as únicas saídas são alimentá-lo no prazo ou deixá-lo reiniciar o chip:
from machine import WDT
wdt = WDT(timeout=2000) # reset if not fed within 2 seconds
while True:
do_work()
wdt.feed()
O timeout está em milissegundos. O valor correto depende de quanto tempo demora a iteração legítima mais longa do ciclo principal, com margem confortável – um ciclo de 100 ms com um timeout de 2 s tem margem suficiente para uma iteração lenta sem resets desnecessários.
3.27.2. Onde chamar feed()¶
O local onde feed() reside é a decisão de conceção crítica; o watchdog apenas apanha bugs nas partes do código que não são executadas entre as alimentações.
Chamar a partir do ciclo principal, no início ou no fim. O padrão mais comum. O watchdog apanha tudo o que bloqueie o ciclo principal – um deadlock, um
whileinfinito, um periférico que nunca responde – e reinicia o chip de volta ao ciclo.Não chamar a partir de um handler de interrupção. O objetivo do watchdog é apanhar bloqueios no percurso de código normal. Uma ISR que dispara independentemente de o ciclo principal estar bloqueado continuaria a alimentar um watchdog que deveria estar a disparar.
Não chamar a partir de uma operação de bloqueio longa. Um pedido de rede ou uma leitura de sensor que demora dez segundos é exatamente o tipo de bloqueio que o watchdog deve apanhar. Colocar
feed()dentro dele anula a proteção.
Uma diretriz que funciona para a maioria dos programas: alimentar uma vez por iteração do ciclo principal, com o timeout definido para várias vezes a duração esperada do ciclo. Se uma única iteração legitimamente precisar de mais tempo do que o timeout – uma fase de calibração deliberada, por exemplo – estruture essa fase como uma série de partes menores com feed() entre elas, ou altere o timeout com timeout_ms() (onde suportado) antes de entrar nela.
3.27.3. Disponibilidade¶
O watchdog está disponível na maioria das câmaras OpenMV, mas não em todas – o hardware está presente em todos os componentes, mas a API Python ainda não está ligada em toda a parte. Consulte o Placas OpenMV ou tente construir uma WDT e apanhe o AttributeError se não for suportado.
Mesmo nas câmaras onde WDT não está disponível, um dispositivo em produção pode usar um equivalente por software – uma tarefa separada ou um passo do ciclo principal que monitoriza o progresso e aciona machine.reset() se algo parecer bloqueado. É menos robusto do que um watchdog de hardware (um handler de interrupção bloqueado também pode derrubar o monitor por software), mas cobre os mesmos casos ao nível da aplicação.