СТОРОЖЕВОЙ ТАЙМЕР ARDUINO
Watchdog (англ. сторожевой пёс) – отдельный таймер на микроконтроллере, который имеет собственный источник тактирования и ни от кого не зависит. По данному таймеру можно ловить прерывания и использовать их в своих целях, а также он может перезагрузить микроконтроллер в случае зависания. Внимание! WDT для перезагрузки МК поддерживают не все загрузчики! Смотрите пример с проверкой работоспособности. Обычные прерывания по вочдогу работают на всех загрузчиках.
БИБЛИОТЕКА GYVERWDT
Библиотека для расширенной и удобной работы с watchdog
- Перезагрузка по прерыванию
- Вызов обычных прерываний
- Настройка периода работы
- Разработчик: Egor ‘Nich1con’ Zaharov
Поддерживаемые платформы: все Arduino
ДОКУМЕНТАЦИЯ
void reset(void); // сброс void disable(void); // отключить WDT void enable(uint8_t mode, uint8_t prescaler); // включить WDT с настройками // mode: // RESET_MODE - сброс при зависании (при тайм-ауте WDT) // INTERRUPT_MODE - прерывание при зависании (при тайм-ауте WDT) // INTERRUPT_RESET_MODE - первый таймаут - прерывание, второй - сброс // prescaler: // WDT_PRESCALER_2, WDT_PRESCALER_4... WDT_PRESCALER_1024
ПРИМЕРЫ
#include "GyverWDT.h" /* Пример тестирующий поддержку всех функций watchdog на вышем устройстве > После 10 секунд отсчета программа стартует заного -> поддерживаются все функции > После таймаута устройство зависает, светодиод на D13 начинает мигать -> подерживается только INTERRUPT_MODE В случае bootloop у вас будет 10 секунд на перепрошивку устройства после подачи питания Для добавления поддержки всего функционала watchdog загрузите optiboot или откажитесь от загрузчика */ void setup() { Serial.begin(9600); Serial.println("Program started , wait 10 seconds"); delay(10000); // 10 секунд на перепрошивку в случае bootloop Watchdog.enable(RESET_MODE, WDT_PRESCALER_1024); // Режим сторжевого сброса , таймаут ~8с Serial.println("watchdog enabled"); while (1) { // Бесконечный цикл , эмуляция "зависания" if (!(millis() % 1000)) { // Каждую секунду Serial.println((uint16_t)((millis() / 1000) - 10)); // Вывести время после включения watchdog в секундах delay(10); } } } void loop() {}
#include "GyverWDT.h" /* Пример использования watchdog в качестве генератора прерываний Зависимость таймаутов от делителей см. в GyverWDT.h */ void setup() { Serial.begin(9600); pinMode(13, OUTPUT); Watchdog.enable(INTERRUPT_MODE, WDT_PRESCALER_128); // Режим генерации прерываний , таймаут ~1с } void loop() { /* Загруженный цикл */ digitalWrite(13, HIGH); delay(5000); digitalWrite(13, LOW); delay(5000); } /* Прерывание watchdog */ ISR(WATCHDOG) { Serial.println("Hello from interrupt"); }
#include "GyverWDT.h" /* Пример классического применения watchdog - сброс устройства при зависании Если не вызвать Watchdog.reset() вовремя - произойдет сброс Зависимость таймаутов от делителей см. в GyverWDT.h */ void setup() { pinMode(13, OUTPUT); Watchdog.enable(RESET_MODE, WDT_PRESCALER_512); // Режим сторжевого сброса , таймаут ~4с } void loop() { /* Ваш полезный код */ digitalWrite(13, HIGH); delay(1000); digitalWrite(13, LOW); delay(1000); Watchdog.reset(); // Переодический сброс watchdog, означающий, что устройство не зависло }
#include "GyverWDT.h" #include <avr/sleep.h> /* Пример использования watchdog в "будильника" Зависимость таймаутов от делителей см. в GyverWDT.h */ void setup() { pinMode(13, OUTPUT); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Выбираем нужный режим сна } void loop() { /* Мигаем светодиодом , а в паузах спим */ digitalWrite(13, HIGH); Watchdog.enable(INTERRUPT_MODE, WDT_PRESCALER_128); // Режим прерываний , таймаут ~1c sleep_enable(); // Разрешаем сон sleep_cpu(); // Уходим в сон digitalWrite(13, LOW); Watchdog.enable(INTERRUPT_MODE, WDT_PRESCALER_128); // Режим прерываний , таймаут ~1c sleep_enable(); // Разрешаем сон sleep_cpu(); // Уходим в сон } /* Прерывание watchdog , в нем мы просыпаемся */ ISR(WATCHDOG) { sleep_disable(); // Запрещаем сон Watchdog.disable(); // Выключаем watchdog }
#include "GyverWDT.h" /* Пример работы watchdog для контроля сразу за двумя устройствами В данном случае - arduino + esp8266 модуль Зависимость таймаутов от делителей см. в GyverWDT.h */ void setup() { Serial.begin(9600); // На этом последовательном порту у нас wifi-модуль pinMode(8, INPUT); // Этот пин сбрасывает wifi-модуль при переходе в режим OUTPUT Watchdog.enable(INTERRUPT_RESET_MODE, WDT_PRESCALER_1024); // Комбинированный сторжевой режим , таймаут ~8с } void loop() { /* Ваш полезный код */ } /* Если wifi-модуль нам что то отправил , а мы его поняли - никто из нас не завис */ void serialEvent() { Watchdog.reset(); // Сбросить watchdog } /* Если wifi-модуль не отправлял нам что то более 8с - он завис */ ISR(WATCHDOG) { pinMode(8, OUTPUT); // Тянем за reset модуля Watchdog.enable(INTERRUPT_RESET_MODE, WDT_PRESCALER_1024); // Если мы не смогли перенастроить watchdog - значит мы зависли Watchdog.reset(); // Если не зависли - сбросить watchdog и продолжить pinMode(8, INPUT); // Отпускаем reset модуля }
#include "GyverWDT.h" /* Пример использования watchdog в комбинированном режиме Может использоваться для оповещения в случае зависания Первый тайм-аут вызывает прерывание, второе - сброс Перенастройте watchdog чтобы избежать сброса Зависимость таймаутов от делителей см. в GyverWDT.h */ void setup() { Serial.begin(9600); Serial.println("Program started"); Watchdog.enable(INTERRUPT_RESET_MODE, WDT_PRESCALER_128); // Комбинированный режим , таймаут ~1c Serial.println("watchdog enabled"); while (1); // Причина зависания Serial.println("loop started"); // Этого мы не увидим из-за зависания } void loop() { /* этого кода программа не достигнет - зависание в setup */ Serial.println("hello"); delay(500); } /* Первый тайм-аут вызывает прерывание */ ISR(WATCHDOG) { // Если причина зависания программная - тут можно попытаться исправить ее */ Serial.println("warning!"); // Если исправить причину не вышло - следующий таймаут вызывает сброс // Watchdog.enable(INTERRUPT_RESET_MODE, WDT_PRESCALER_128); // Если перенастроить watchdog здесь - сброса не будет }
УСТАНОВКА БИБЛИОТЕКИ
Если вы не знаете, как установить библиотеку – читайте отдельный урок по работе с библиотеками!
БАГИ И ОШИБКИ
Если вы нашли баг или ошибку в исходнике или примерах, или у вас есть идеи по доработке библиотеки – пишите пожалуйста на почту alex@alexgyver.ru. В комментарии на страницах я заглядываю очень редко, на форум – ещё реже.
ОСТАЛЬНЫЕ БИБЛИОТЕКИ

У меня есть ещё очень много всего интересного! Смотрите полный список библиотек вот здесь.