驴Qu茅 es el WDT de Arduino?
Esta lecci贸n analiza el dispositivo y el trabajo con el temporizador de vigilancia (Watchdog), para lo cual se propone utilizar la biblioteca GyverWDT, que proporciona un control total sobre el WDT y acceso a todas sus configuraciones y modos de funcionamiento. La biblioteca es muy ligera y se adapta a la mayor铆a de microcontroladores AVR, es decir, en particular para todas las placas Arduino basadas en ellos.
El temporizador de vigilancia en Arduino es una unidad as铆ncrona independiente sincronizada desde un generador RC interno separado, cuya frecuencia es de aproximadamente 128 kHz (algo que depende de la temperatura y el voltaje de suministro). Cabe se帽alar que este generador fue dise帽ado originalmente como una fuente de reloj de eficiencia energ茅tica y no implica una alta precisi贸n, la desviaci贸n de frecuencia durante la producci贸n es de aproximadamente el 10%. Si lo desea, este oscilador tambi茅n puede sincronizar el n煤cleo AVR, en caso de que no se proporcione un resonador de cristal externo y el oscilador RC interno de 8 MHz no cumpla con los requisitos de consumo de energ铆a.
El temporizador de vigilancia (Watchdog) es un registro de conteo simple de 10 bits que se incrementa en cada borde de la se帽al de reloj que proviene del divisor. Tan pronto como el valor en este registro de conteo llega a 1023, se produce un tiempo de espera y el temporizador de vigilancia, seg煤n el modo establecido, inicia un restablecimiento del microcontrolador o activa una interrupci贸n. Para evitar un tiempo de espera, puede restablecer el temporizador de vigilancia a 0 utilizando la funci贸n corta Watchdog.reset () de la biblioteca GyverWDT, o la instrucci贸n del ensamblador 芦WDR禄.
驴Por qu茅 necesito un temporizador de vigilancia? Le permite reiniciar autom谩ticamente el microcontrolador en caso de que el programa se cuelgue, lo que puede ser necesario en proyectos independientes. Adem谩s, la biblioteca GyverWDT brinda la capacidad de usar el temporizador de vigilancia para otros fines, por ejemplo, para generar interrupciones de alta prioridad sin usar los temporizadores de hardware principales, lo que puede ser muy 煤til en proyectos complejos, por ejemplo, para sondear regularmente sensores. No olvide que el temporizador de vigilancia permanece activo en todos, incluso en los modos de suspensi贸n m谩s profundos, y puede despertar al microcontrolador con una interrupci贸n. El modo de vigilancia combinado tambi茅n puede ser 煤til, para sondear sensores simult谩neamente, actuar como un temporizador de vigilancia para un dispositivo externo y monitorear el funcionamiento de su propio kernel.
Divisores de frecuencia de vigilancia
Divisor constante GyverWDT | Tiempo de espera estimado | Frecuencia de tiempo de espera aproximada |
WDT_PRESCALER_2 | ~ 16 ms | ~ 62 Hz |
WDT_PRESCALER_4 | ~ 32 ms | ~ 32 Hz |
WDT_PRESCALER_8 | ~ 64 ms | ~ 16 Hz |
WDT_PRESCALER_16 | ~ 0,125 s | ~ 8 Hz |
WDT_PRESCALER_32 | ~ 0,25 s | ~ 4 Hz |
WDT_PRESCALER_64 | ~ 0,5 s | ~ 2 Hz |
WDT_PRESCALER_128 | ~ 1 s | ~ 1 Hz |
WDT_PRESCALER_256 | ~ 2 s | ~ 0,5 Hz |
WDT_PRESCALER_512 | ~ 4 s | ~ 0,25 Hz |
WDT_PRESCALER_1024 | ~ 8 s | ~ 0,125 Hz |
驴Por qu茅 aproximar? Debido a que la frecuencia del temporizador de vigilancia que ya est谩 en producci贸n tiene una distribuci贸n decente, y si en valores peque帽os del divisor esto pr谩cticamente no aparece (16 ms +/- 1,6 ms), entonces en valores grandes puede convertirse en un problema grave (8 s +/- 1 s) …
No olvide que un oscilador RC, a diferencia de un resonador de cuarzo, tiene una peque帽a dependencia de frecuencia de la temperatura y la tensi贸n de alimentaci贸n.
Biblioteca GyverWDT.
Para trabajar con Watchdog, puede usar la biblioteca avr incorporada, pero usaremos una biblioteca con un conjunto m谩s amplio de configuraciones: GyverWDT, enlace de descarga aqu铆.
Funciones de la biblioteca GyverWDT:
- Watchdog.reset(); un comando corto y r谩pido para restablecer el temporizador de vigilancia a 0, llamado dentro del programa para confirmar el funcionamiento normal.
- Watchdog.disable(); comando corto para detener el temporizador de vigilancia. Llamada para deshabilitar el perro guardi谩n por completo.
- Watchdog.enable(mode, prescaler); funci贸n para configurar e iniciar el temporizador (ver ejemplo)
Modo (constante) | Acci贸n de tiempo de espera |
INTERRUPT_MODE | Interrupci贸n con la funci贸n especificada en watchdog_enable () |
INTERRUPT_RESET_MODE | Una interrupci贸n que llama a la funci贸n especificada en watchdog_enable () y establece autom谩ticamente el temporizador de vigilancia en el modo de reinicio. |
(modo combinado) | En consecuencia, el primer tiempo de espera inicia una interrupci贸n, el segundo tiempo de espera inicia un restablecimiento. |
驴Por qu茅 necesita el modo combinado? Permite usar interrupciones y reinicios al mismo tiempo, lo que puede ser muy poderoso. C贸mo funciona:
- Si el motivo de la congelaci贸n radica en un error de software, por ejemplo, en una espera interminable para que lleguen los datos. El primer tiempo de espera desencadenar谩 una interrupci贸n de alta prioridad si pudi茅ramos ingresar y comprender que sucedi贸: saber si el bloqueo es claramente por software, no hardware. En este caso, podemos intentar corregir un error de programa justo dentro de la interrupci贸n o advertir al usuario que el c贸digo escrito tiene 谩reas problem谩ticas. Si logramos resolver r谩pidamente el problema antes de que ocurra el pr贸ximo tiempo de espera, podemos reconfigurar el temporizador de vigilancia con la funci贸n watchdog_enable () para que en el pr贸ximo tiempo de espera nos env铆e a una interrupci贸n de se帽alizaci贸n en lugar de un reset completo. Si no fue posible solucionar r谩pidamente la causa del congelamiento, el pr贸ximo tiempo de espera reiniciar谩 autom谩ticamente el controlador.
- Si es necesario utilizar interrupciones al mismo tiempo (por ejemplo, para sensores de sondeo) y protecci贸n contra congelamiento. En la funci贸n personalizada, las interrupciones, adem谩s de las acciones que necesitemos, sondear sensores, etc. la funci贸n de reconfiguraci贸n simplemente se agrega con watchdog_enable (), si la reconfiguraci贸n no ocurri贸, entonces el controlador no ingres贸 al procedimiento de interrupci贸n, simplemente se colg贸. El pr贸ximo tiempo de espera reiniciar谩 el controlador.
- Si necesita monitorear el rendimiento del hardware tanto del dispositivo externo como del Arduino. Por ejemplo, cuando microcontrolador y el m贸dulo Bluetooth / Wi-Fi / GSM / GPS funcionan juntos. 驴C贸mo implementar esto? Watchdog est谩 configurado para el per铆odo requerido. Un dispositivo externo debe enviar peri贸dicamente una confirmaci贸n de su operabilidad al microcontrolador, puede ser un pulso generado peri贸dicamente usando el GPIO de un dispositivo externo, iniciando una interrupci贸n externa, o un mensaje enviado por un dispositivo externo a trav茅s de uno de los interfaces, y de manera similar iniciando interrupci贸n en el microcontrolador. Dentro de la rutina de interrupci贸n, la funci贸n corta se llama watchdog_reset (); reiniciar el temporizador de vigilancia. Si un dispositivo externo se cuelga y deja de enviar datos / pulsos, no se producen reinicios de vigilancia y se produce una interrupci贸n, dentro de la cual podemos restablecer f谩cilmente el dispositivo externo aplic谩ndole un nivel bajo (se requiere un pull-up externo a VCC). El perro guardi谩n se reconfigura en la misma interrupci贸n. Si el Arduino se cuelga, no reconfigurar谩 el perro guardi谩n a tiempo y el pr贸ximo tiempo de espera iniciar谩 un reinicio del microcontrolador.
Ejemplos de programa para WDT Arduino.
WDT como fuente de interrupci贸n
#include "GyverWDT.h" / * Un ejemplo del uso del perro guardi谩n como generador de interrupciones Consulte GyverWDT.h para ver los tiempos de espera frente a los divisores. * / void setup() { Serial.begin(9600); pinMode(13, OUTPUT); Watchdog.enable(INTERRUPT_MODE, WDT_PRESCALER_128); // Modo de generaci贸n de interrupciones, tiempo de espera ~ 1s } void loop() { / * Bucle cargado * / digitalWrite(13, HIGH); delay(5000); digitalWrite(13, LOW); delay(5000); } /* Interrumcion perro guardi谩n */ ISR(WATCHDOG) { Serial.println("Hello from interrupt"); }
Sue帽o profundo y despierta con WDT
#include "GyverWDT.h" #include <avr/sleep.h> /* Ejemplo de uso de perro guardi谩n en "alarma" Consulte GyverWDT.h para ver los tiempos de espera frente a los divisores. */ void setup() { pinMode(13, OUTPUT); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Seleccione el modo de suspensi贸n deseado } void loop() { /* Hacemos parpadear el LED y dormimos durante las pausas */ digitalWrite(13, HIGH); Watchdog.enable(INTERRUPT_MODE, WDT_PRESCALER_128); // Modo de interrupci贸n, tiempo de espera ~ 1 sleep_enable(); // Permitir dormir sleep_cpu(); // Ve a dormir digitalWrite(13, LOW); Watchdog.enable(INTERRUPT_MODE, WDT_PRESCALER_128); // Modo de interrupci贸n, tiempo de espera ~ 1 sleep_enable(); // Permitir dormir sleep_cpu(); // Ve a dormir } /* Interrumpir perro guardi谩n, en el que nos despertamos */ ISR(WATCHDOG) { sleep_disable(); //Deshabilitar el sue帽o Watchdog.disable(); // Apagar perro guardi谩n }
Modo combinado, interrupci贸n + reinicio
#include "GyverWDT.h" /* Ejemplo de uso de perro guardi谩n en modo combinado Puede usarse para alertar en caso de congelaci贸n El primer tiempo de espera desencadena una interrupci贸n, el segundo un reinicio Reconfigure el perro guardi谩n para evitar el reinicio Consulte GyverWDT.h para ver los tiempos de espera frente a los divisores. */ void setup() { Serial.begin(9600); Serial.println("Program started"); Watchdog.enable(INTERRUPT_RESET_MODE, WDT_PRESCALER_128); // Modo combinado, tiempo de espera ~ 1s Serial.println("watchdog enabled"); while (1); // Raz贸n de la congelaci贸n Serial.println("loop started"); // No veremos esto debido a la congelaci贸n } void loop() { /* el programa no alcanzar谩 este c贸digo - cuelgue en la configuraci贸n */ Serial.println("hello"); delay(500); } /* El primer tiempo de espera provoca una interrupci贸n */ ISR(WATCHDOG) { // Si el motivo del bloqueo es el software, aqu铆 puede intentar solucionarlo */ Serial.println("warning!"); // Si la causa no se puede corregir, el siguiente tiempo de espera provoca un reinicio // Watchdog.enable (INTERRUPT_RESET_MODE, WDT_PRESCALER_128); // Si reconfiguras el perro guardi谩n aqu铆, no habr谩 reinicio }
Watchdog y sue帽o.
- Configure el Arduino en uno de los modos de suspensi贸n.
- Permita dormir a Arduino.
- Establecer el perro guardi谩n en un tiempo de espera espec铆fico en el modo de interrupci贸n.
- Mande a dormir a Arduino.
- Al despertar, estando en la rutina de interrupci贸n del perro guardi谩n, desactive el sue帽o.
- Continuar la ejecuci贸n del programa.
Problemas.
El principal problema es que el modo de reinicio autom谩tico no funciona en algunas placas Arduino.聽Por el contrario, cuando funciona bien, solo conduce a un reinicio o bucle de arranque sin fin.聽驴Por qu茅 est谩 pasando esto?聽El hecho es que los controladores de lotes nuevos, en el caso de un reinicio del perro guardi谩n, reconfiguran autom谩ticamente el temporizador del perro guardi谩n durante el per铆odo m铆nimo, es decir,聽16 ms sin apagarlo.聽Para evitar un bootlap, es necesario desactivar el watchdog al iniciar el programa, pero como sabes, en la mayor铆a de las placas base tenemos un Arduino con un bootloader cableado, cuyo tiempo de ejecuci贸n es superior a 16 mS.聽Esto lleva al hecho de que el controlador ni siquiera tiene tiempo para comenzar a ejecutar el programa principal, ya que va directo al reset, esto ocurre c铆clicamente e infinitamente.聽La 煤nica forma de detener este proceso es apagar la placa.
Comprobaci贸n del estado del perro guardi谩n.
En los ejemplos, la biblioteca contiene un esquema de prueba del soporte del perro guardi谩n en su placa.聽C谩rguelo en la placa y abra el monitor de puerto.聽Despu茅s de 10 segundos de una pausa configurada para simplificar el parpadeo durante el ciclo de arranque, el tiempo de ejecuci贸n del programa en segundos se mostrar谩 en el monitor del puerto serie.聽Si, cuando se alcanza el tiempo de espera, el programa se reinicia y la cuenta regresiva comienza de nuevo, su placa (cargador de arranque) admite el perro guardi谩n al 100%.聽Si despu茅s del reinicio se detiene la salida de tiempo correcta al monitor de puerto y el LED de la placa comienza a parpadear r谩pidamente y sin parar, el cargador de arranque de la placa no admite el reinicio del perro guardi谩n.聽Sube cualquier otro boceto a la pizarra para seguir usando.
Verificaci贸n de WDT
#include <GyverWDT.h> /* Un ejemplo de soporte de prueba para todas las funciones de vigilancia en su dispositivo > Despu茅s de 10 segundos de cuenta atr谩s, el programa comienza de nuevo -> todas las funciones son compatibles > Despu茅s de un tiempo de espera, el dispositivo se congela, el LED en D13 comienza a parpadear -> solo se admite INTERRUPT_MODE En caso de bootloop, tendr谩 10 segundos para flashear el dispositivo despu茅s de encender Para agregar soporte para todas las funciones de vigilancia, descargue optiboot u opte por no usar el gestor de arranque */ void setup() { Serial.begin(9600); Serial.println("Program started , wait 10 seconds"); delay(10000); //10 segundos para parpadear en caso de bootloop Watchdog.enable(RESET_MODE, WDT_PRESCALER_1024); // Modo de reinicio del perro guardi谩n, tiempo de espera ~ 8 s Serial.println("watchdog enabled"); //Imprime el tiempo despu茅s de que se encendi贸 el perro guardi谩n en segundos while (1) { // Bucle sin fin, congelar la emulaci贸n if (!(millis() % 1000)) { // Cada segundo Serial.println((uint16_t)((millis() / 1000) - 10)); // Imprime el tiempo despu茅s de que se encendi贸 el perro guardi谩n en segundos delay(10); } } } void loop() {}
驴Qu茅 pasa si el cargador de arranque de mi placa no es compatible con el perro guardi谩n?
Si realmente necesita la funcionalidad completa del temporizador de vigilancia, necesita actualizar el cargador de arranque, para esto necesita un programador que admita microcontroladores AVR u otra placa Arduino + un boceto de ISP de Arduino.聽Lea m谩s en la lecci贸n sobre c贸mo trabajar con el programador.聽Sin flashear el cargador de arranque, tiene acceso a interrupciones ordinarias que no usan temporizadores y tienen alta prioridad y, en consecuencia, la capacidad de usar el perro guardi谩n en el modo de alarma del microcontrolador.