Работа с WatchDog Arduino. Библиотека GyverWDT

ТЕОРИЯ


Watchdog (англ. сторожевой пёс) – отдельный таймер на микроконтроллере, который имеет собственный источник тактирования и ни от кого не зависит. По данному таймеру можно ловить прерывания и использовать их в своих целях, а также он может перезагрузить микроконтроллер в случае зависания. Внимание! WDT для перезагрузки МК поддерживают не все загрузчики! Смотрите пример с проверкой работоспособности. Обычные прерывания по вочдогу работают на всех загрузчиках.

БИБЛИОТЕКА


Библиотека для управления WDT на AVR ATmega328p/32U4/2560 & ATtiny85/84/167

  • Настройка режима работы WDT
  • Настройка прерываний

Совместимость

AVR ATmega328p/32U4/2560 & ATtiny85/84/167

УСТАНОВКА


  • Библиотеку можно найти и установить через менеджер библиотек по названию GyverWDT в:
    • Arduino IDE (Инструменты/Управлять библиотеками)
    • Arduino IDE v2 (вкладка “Library Manager”)
    • PlatformIO (PIO Home, вкладка “Libraries”)
  • Про ручную установку читай здесь

ДОКУМЕНТАЦИЯ


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

ПРИМЕРЫ


Остальные примеры смотри в папке examples библиотеки, также примеры можно открыть из Arduino IDE/Файл/Примеры

#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"
/*
   Пример использования 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 здесь - сброса не будет
}

ПОДДЕРЖАТЬ


Вы можете поддержать меня за создание доступных проектов с открытым исходным кодом, полный список реквизитов есть вот здесь.

guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии