Функция millis() и прерывания?

Спаял схему для авто полива моих растений на Digispark

Нашёл прошивку из инета:
#define PERIOD 86400   // период работы в секундах (пример: 60*60*24 = 86400 - день!)
#define WORK 30         // время работы в секундах
#define MOS 1           // пин мосфета

uint32_t mainTimer, myTimer;
boolean state = false;

#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off)
#define adc_enable()  (ADCSRA |=  (1<<ADEN)) // re-enable ADC

void setup() {
  // все пины как входы, экономия энергии
  for (byte i = 0; i < 6; i++) {
    pinMode(i, INPUT);
  }
  adc_disable();          // отключить АЦП (экономия энергии)

  wdt_reset();            // инициализация ватчдога
  wdt_enable(WDTO_1S);    // разрешаем ватчдог
  // 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8S

  WDTCR |= _BV(WDIE);     // разрешаем прерывания по ватчдогу. Иначе будет резет.
  sei();                  // разрешаем прерывания
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // максимальный сон
}

void loop() {
  mainTimer++;

  if (!state) {                           // если помпа не включена
    if ((long)mainTimer - myTimer > PERIOD) {   // таймер периода
      myTimer = mainTimer;                // сброс таймера
      state = true;                       // флаг на запуск
      pinMode(MOS, OUTPUT);               // пин как выход
      digitalWrite(MOS, HIGH);            // врубить
    }
  } else {                                // если помпа включена
    if ((long)mainTimer - myTimer > WORK) {     // таймер времени работы
      myTimer = mainTimer;                // сброс
      state = false;                      // флаг на выкл
      digitalWrite(MOS, LOW);             // вырубить
      pinMode(MOS, INPUT);                // пин как вход (экономия энергии)
    }
  }

  sleep_enable();   // разрешаем сон
  sleep_cpu();      // спать!
}

ISR (WDT_vect) {
  WDTCR |= _BV(WDIE); // разрешаем прерывания по ватчдогу. Иначе будет реcет.
}

Данная прошивка работает не корректно, так как на 60 прерываний тратится 68 с копейками секунд, а не 60 как задумывал её автор, то есть за день таймер отстаёт на 3 часа с лишним от реального времени.

Хотел использовать millis() но не работает при прерывании, как сделать, что бы Digispark срабатывала по указанному времени и при этом сохранялся режим экономного энергопотребления?
  • Вопрос задан
  • 907 просмотров
Пригласить эксперта
Ответы на вопрос 3
@AlexSku
не буду отвечать из-за модератора
RTC
Привяжитесь к календарю (время внутри дня), а не к простому таймеру.
Ответ написан
@vanyamba-electronics
PERIOD задайте 76235, а WORK - 27.
Ответ написан
@kalapanga
1) Непонятна цель всех этих манипуляций со спящим режимом. При работающих от сети помпах, что пытается экономить ардуинка?
2) Прислушайтесь к Александр Скуснов. Т.к. Вам не просто период нужен, а полив в конкретное время, использование часов более логично. Но часы тоже разного качества есть, что попало не берите.
3) Если уж вдруг и у RTC точность не устроит, то надо на какую-нибудь ESP переходить и время по интернету корректировать.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы