СТОРОЖЕВОЙ ТАЙМЕР ARDUINO

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

БИБЛИОТЕКА GYVERWDT

Библиотека для расширенной и удобной работы с watchdog

  • Перезагрузка по прерыванию
  • Вызов обычных прерываний
  • Настройка периода работы
  • Разработчик: Egor ‘Nich1con’ Zaharov

Поддерживаемые платформы: все Arduino

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


/*
О прескалерах и режимах работы watchdog таймера:
1) Осцилятор сторжевого таймера не предполагает высокой точности и имеет отклонение при производстве около 10%
2) Приблизительное соотношение делителей и таймаутов:
[/2 ~ 16ms   /4 ~ 32ms  /8 ~ 64ms  /16 ~ 0.125s  /32 ~ 0.25s  /64 ~ 0.5s  /128 ~ 1s  /256 ~ 2s  /512 ~ 4s  /1024 ~ 8s ]
3) Описание режимов работы сторжевого таймера:
- INTERRUPT_MODE  => Таймаут инициирует вызов прерывания , работает на любом bootloader'e 
- RESET_MODE  => Таймаут инициирует сброс микроконтроллера , работает НЕ со всеми загрузчиками , для проверки воспользуйтесь примером "watchdog_support_test"
- INTERRUPT_RESET_MODE  => Первый таймаут инициирует прерывание,и автоматически переводит watchdog в режим "RESET_MODE",
соотв. последующий таймаут иницирует сброс. Если в вызванном прерывании удалось побороть причину зависания,
вы можете перенастроить сторжевой таймер конструкцией [watchdog_disable() + watchdog_enable()],чтобы следующий таймаут не инициировал сброс.
*/

void watchdog_reset(void);   // сбросить watchdog 
void watchdog_disable(void); // полностью выключить watchdog 
void watchdog_enable(uint8_t mode , uint8_t  prescaler, void (*isr)()); // Включить и настроить ватчдог (с прерыванием)
void watchdog_enable(uint8_t prescaler); // Включить и настроить ватчдог (только reset)

/* варианты предделителей для watchdog'a */
WDT_PRESCALER_2		
WDT_PRESCALER_4		
WDT_PRESCALER_8		
WDT_PRESCALER_16	
WDT_PRESCALER_32	
WDT_PRESCALER_64	
WDT_PRESCALER_128	
WDT_PRESCALER_256	
WDT_PRESCALER_512	
WDT_PRESCALER_1024	

/* Режимы работы watchdog'a */
INTERRUPT_MODE			// вызывает прерывание при таймауте
INTERRUPT_RESET_MODE	// вызывает прерывание при таймауте, следующий таймаут инициирует сброс

ПРИМЕРЫ


#include "GyverWDT.h"
/* Скетч , тестирующий поддержку автоматического watchdog reset на вашем bootloader'е */

/* !!! Если после запуска скетча программа перезапускается каждые ~8с - ваш bootloader поддерживает  watchdog reset !!!
   !!! Если после таймаута программа не перезагружается , а светодиод на плате начинает быстро мигать - watchdog reset не поддерживается !!!
   Если ваш bootloader не поддерживаем watchdog reset , вы можете использовать watchdog для генерации прерываний, см. GyverWDT.h
*/

void setup() {
  Serial.begin(9600);
  Serial.println("wait 10 sec");
  delay(10000); // задержка , чтобы иметь возможность перепрошить контроллер в случае bootloop
  watchdog_enable(WDT_PRESCALER_1024); // таймаут ~ 8с
  Serial.println("watchdog enabled");
  while (1) { // бесконечный цикл, в котором нет watchdog_reset();
    if (!(millis() % 1000)) { // каждую секунду
      delay(10);
      Serial.println((int)((millis() / 1000) - 10)); // выводим прошедшее время в секундах
    }
  }
}

void loop() {

}
#include "GyverWDT.h"
/* пример работы ватчдога как источника переодических прерываний */

volatile long oldTime;
void setup() {
  Serial.begin(9600);
  Serial.println("hello!");
  watchdog_enable(INTERRUPT_MODE, WDT_PRESCALER_128, func); // подробнее о делителях и режимах в GyverWDT.h
  oldTime = millis();
  delay(10000);  // работаем 10 секунд
  watchdog_disable(); // выключаем ватчдог
  //while(1) watchdog_reset(); // или можем сбрасывать его и не допускать таймаута и соотв. прерываний
}

void func() {
  Serial.println(millis() - oldTime);
  oldTime = millis();
}

void loop() {}
#include "GyverWDT.h"
/* пример работы ватчдога как автоматического reset при зависании */

void setup() {
  Serial.begin(9600);
  Serial.println("hello!"); // сигнализирует о старте программы
  /* в режиме reset фунция имеет только один аргумент */
  watchdog_enable(WDT_PRESCALER_512); // подробнее о режимах и прескалерах в файле GyverWDT.h
  Serial.println("watchdog enabled"); // сигнализирует о включении watchdog
  while (1); // источник зависания
  /* для подтверждения правильной работы программы, вызывайте watchdog_reset() не реже заданного таймаута */
  Serial.println("data:"); // это сообщение мы никогда не увидим , из-за зависания выше
  /* по достижению таймаута мы увидим , что программа перезапустилась */
}

void loop() {
}
#include "GyverWDT.h"
/* пример работы ватчдога в комбинированном режиме */

void setup() {
  Serial.begin(9600);
  Serial.println("hello!"); // сигнализирует о старте программы
  watchdog_enable(INTERRUPT_RESET_MODE, WDT_PRESCALER_512, alert); // подробнее о режимах и прескалерах в файле GyverWDT.h
  Serial.println("watchdog enabled"); // сигнализирует о включении watchdog
  while (1); // источник зависания
  Serial.println("data:"); // это сообщение мы никогда не увидим , из-за зависания выше
  /* первый таймаут сигнализирует предупреждением , последующий - инициирует сброс */
}

void alert() {
  Serial.println("attention!");
  // в этом прерывании вы можете попытаться исправить причину зависания
  // если нет - следующий таймаут инициирует сброс
}

void loop() {
}

ОСТАЛЬНЫЕ БИБЛИОТЕКИ

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