S
S
Svyatoslav Nemato2019-09-22 23:54:33
Arduino
Svyatoslav Nemato, 2019-09-22 23:54:33

millis() function and interrupts?

I soldered a scheme for auto watering my plants on Digispark.
I found a firmware from the Internet:

#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ет.
}

This firmware does not work correctly, since 68 seconds are spent on 60 interruptions, and not 60 as its author intended, that is, the timer lags behind real time by more than 3 hours per day.
I wanted to use millis() but it does not work when interrupted, how can I make Digispark work at the specified time and at the same time save power consumption mode?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
A
Alexander Skusnov, 2019-09-23
@AlexSku

RTC
Link to a calendar (intraday time) rather than a simple timer.

V
vanyamba-electronics, 2019-09-23
@vanyamba-electronics

Set PERIOD to 76235 and WORK to 27.

K
kalapanga, 2019-09-23
@kalapanga

1) The purpose of all these manipulations with sleep mode is not clear. With mains powered pumps, what is the arduino trying to save?
2) Listen to Alexander Skusnov . Because You do not just need a period, but watering at a specific time, using a clock is more logical. But there are also watches of different quality, don’t take anything horrible.
3) If suddenly RTC is not satisfied with the accuracy, then you need to switch to some ESP and adjust the time via the Internet.

S
Sencis, 2019-10-18
@Userpc0101

You can remove power consumption if everything is powered by the network, and regarding time, any clock is behind in time. If you want accurate work, buy a GPS module, it is synchronized with the most accurate atomic clocks on satellites up to nanoseconds.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question