Помощь с прерыванием режима ожидания Arduino и ватчдог таймера

Я хочу использовать функции сна и пробуждения Arduino, но столкнулся с препятствием и, похоже, не могу его преодолеть. Поскольку я только создаю прототип для окончательной системы, я не могу использовать маломощную библиотеку для реализации функциональности, поэтому я делаю это просто. Я могу перевести Arduino в спящий режим просто отлично, основная проблема связана со сторожевым таймером. У меня есть или, как мне кажется, я настроил его на 8-секундное прерывание, чтобы вывести Arduino из спящего режима, но Arduino выходит из спящего режима так же, как и входит в него без каких-либо задержек. Код таков

#include <Arduino.h>
#include <avr/sleep.h>

void goToSleep();
void setupWDT();
void stopWDT();

ISR(WDT_vect) {
  sleep_disable(); // разбудить Arduino
}

void setup() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  stopWDT();

  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(9600);
  Serial.println("Uno is in setup funtion.");

  bool ledState = 0;
  while(millis()<3000){
    digitalWrite(LED_BUILTIN, ledState);
    ledState = !ledState;
    delay(500);
  }
}

void loop() {
  Serial.println("Uno is awake.");
  digitalWrite(LED_BUILTIN, HIGH);
  delay(2000);
  Serial.println("Going to sleep...");
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);

  setupWDT();
  goToSleep();
  stopWDT();
  delay(100);
  digitalWrite(LED_BUILTIN, HIGH);
}

void goToSleep() {
  ADCSRA &= ~(1<<ADEN); // отключить АЦП
  sleep_mode(); // переводит Arduino в спящий режим
}

void setupWDT() {
  cli();
  WDTCSR |= (1 << WDCE);
  WDTCSR &= ~(1 << WDE);
  WDTCSR |= (1 << WDCE) | (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // настроен на 8 секунд задержки прерывания
  sei();
}

void stopWDT() {
  cli();
  MCUSR &= ~(1 << WDRF); // снять флаг сброса
  WDTCSR |= (1 << WDCE);
  WDTCSR &= ~(1<<WDE);
  WDTCSR = 0x00; // остановить WDT
  sei();
}

, 👍1


1 ответ


1

Попробуйте изменить это:

void setupWDT() {
  cli();
  WDTCSR |= (1 << WDCE);
  WDTCSR &= ~(1 << WDE);
  WDTCSR |= (1 << WDCE) | (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // настроен на 8 секунд задержки прерывания
  sei();
}

Для:

void setupWDT() {
  cli();
  WDTCSR = (1 << WDCE) | (1 << WDE) ;
  WDTCSR = (1 << WDCE) | (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // настроен на 8 секунд задержки прерывания
  sei();
}

Похоже, что ваша конструкция нарушает окно с тактовым циклом 4, в котором бит разрешения изменения сторожевого таймера WDCE позволяет обновлять бит WDE.

,