RTC wakeup from sleep

Hi everyone

I decided to dig out an Arduino Pro Mini for a little plant misting project.

I found a great little programmable garden water timer that lets me adjust sprays down to the second, I need 15-second sprays, so far so good, but it's programmed for 1 hour, and that's it, so it sprays all night and soaks everything every hour, so it's no good, however, its battery powered and uses a 3volt water solenoid switch, so I`m going to be using that.

I haven't built it yet but wanted some advice on the code, I need the unit to be battery powered so I will use a 18650 2000mAH LiPo battery to provide the power, I have modified the Pro Mini by removing the LED and replaced the voltage regulator with a low leakage one to get the lowest hardware power consumption, also will be using the lowpower library to put the Pro Mini to sleep, I have DS3231 RTC to keep the time accurate, and a BME280 sensor for humidity.

So the idea is that the unit goes to sleep and wakes up every 8 seconds to check the time and humidity reading, if the humidity is low enough and one of the alarm times is correct then the sprayer will run for 15 seconds and then turn off and the system go back to sleep.

That's all I need it to do, however as I finished the code I realized a big error, as the system wakes up every 8 seconds it could miss its alarm time, therefore it won't do the spraying!

If I was not using the sleep function I see no problem with the code, but with the sleep running, I cant see how to get this going, maybe I need a different method?.

Any ideas are greatly appreciated.

Many thanks in advance Alan

#include <LowPower.h>
#include <TimeAlarms.h>                                                                  // System Libraries 
#include <TimeLib.h>
#include <Wire.h>
#include "RTClib.h"
#include "Seeed_BME280.h"

#define Solenoid 2                                                                       // Device Setups
BME280 bme280;
RTC_DS3231 rtc;

time_t syncProvider()                                                                    // RTC to system time
{
  return rtc.now().unixtime();
}

void setup() {
  Serial.begin(9600); Wire.begin(); rtc.begin();                                         // Devices Start
  //rtc.adjust(DateTime(2019, 12, 18, 12, 26, 00));

  setSyncProvider(syncProvider); delay(1000); Serial.println();                          // Confirm system time is synced with RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");

  bme280.init();                                                                         // Start Sensor

  delay(100);
  pinMode(Solenoid, OUTPUT); digitalWrite(Solenoid, LOW);                                // Setup Solenoid

  // alarms, to trigger at specific times ------------------//                           // Setup Solenoid start and stop times

  
  Alarm.alarmRepeat(9, 00, 00, StartAlarm); Alarm.alarmRepeat(9, 00, 15, StopAlarm);
  Alarm.alarmRepeat(9, 30, 00, StartAlarm); Alarm.alarmRepeat(9, 30, 15, StopAlarm);
  Alarm.alarmRepeat(10, 00, 00, StartAlarm); Alarm.alarmRepeat(10, 00, 15, StopAlarm);
  Alarm.alarmRepeat(10, 30, 00, StartAlarm); Alarm.alarmRepeat(10, 30, 15, StopAlarm);
  Alarm.alarmRepeat(11, 00, 00, StartAlarm); Alarm.alarmRepeat(11, 00, 15, StopAlarm);
  Alarm.alarmRepeat(11, 30, 00, StartAlarm); Alarm.alarmRepeat(11, 30, 15, StopAlarm);
  Alarm.alarmRepeat(12, 00, 00, StartAlarm); Alarm.alarmRepeat(12, 00, 15, StopAlarm);
  Alarm.alarmRepeat(12, 30, 00, StartAlarm); Alarm.alarmRepeat(12, 30, 15, StopAlarm);
  Alarm.alarmRepeat(13, 00, 00, StartAlarm); Alarm.alarmRepeat(13, 00, 15, StopAlarm);
  Alarm.alarmRepeat(13, 30, 00, StartAlarm); Alarm.alarmRepeat(13, 30, 15, StopAlarm);
  Alarm.alarmRepeat(14, 00, 00, StartAlarm); Alarm.alarmRepeat(14, 00, 15, StopAlarm);
  Alarm.alarmRepeat(14, 30, 00, StartAlarm); Alarm.alarmRepeat(14, 30, 15, StopAlarm);
  Alarm.alarmRepeat(15, 00, 00, StartAlarm); Alarm.alarmRepeat(15, 00, 15, StopAlarm);
  Alarm.alarmRepeat(15, 30, 00, StartAlarm); Alarm.alarmRepeat(15, 30, 15, StopAlarm);
  Alarm.alarmRepeat(16, 00, 00, StartAlarm); Alarm.alarmRepeat(16, 00, 15, StopAlarm);
  Alarm.alarmRepeat(16, 30, 00, StartAlarm); Alarm.alarmRepeat(16, 30, 15, StopAlarm);
  Alarm.alarmRepeat(17, 00, 00, StartAlarm); Alarm.alarmRepeat(17, 00, 15, StopAlarm);
  Alarm.alarmRepeat(17, 30, 00, StartAlarm); Alarm.alarmRepeat(17, 30, 15, StopAlarm);
}

void loop() {
  Alarm.delay(1000);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}

void StartAlarm()                                                                        // Start Solenoid
{
  if (bme280.getHumidity() < 60) {
    digitalWrite(Solenoid, HIGH);
    delay(100);
  }
  else {
    digitalWrite(Solenoid, LOW);
    delay(100);
  }
}
void StopAlarm()                                                                         // Stop Solenoid
{
  digitalWrite(Solenoid, LOW);
  delay(100);
}

Do you really need to use TimeAlarms ?

Each time you wake up test whether it is time for a misting. If yes, then do it and save the time ready for the next check, if no then back to sleep

Note also that you need to edit TimeAlarms.h if you want to use more than 6 alarms

From the TimeAlarms readme file

Q: How many alarms can be created?
A: Up to six alarms can be scheduled.
The number of alarms can be changed in the TimeAlarms header file (set by the constant dtNBR_ALARMS,
note that the RAM used equals dtNBR_ALARMS * 11)

Also, having so many alarms active at a time is completely unnecessary as you could set the next one each time one is triggered

Yes. But check whether it is past time for a mist, as you might miss when it is (exactly) time.

Nice project. Be sure, however, to measure the battery current during the sleep period… you have taken the usual measures, but sometimes something will be draining off a small but substantial amount of current without you realizing it.

Does your BME289 have a sleep mode, or are you planning to turn it on and off as needed? Everything in the entire circuit must be examined for power use during the sleep period.

Another approach entirely, just mentioning it, not to sidetrack you, is to use the alarm function in the RTC. Then the processor can sleep until the RTC knows it is time to miss and wakes it up.

Waking up every 8 seconds to do anything takes a bit more power than sleeping soundly for, say, 30 minutes. Obsessive, yes, it is a sickness chasing the last ways to get the most out of the battery.

You may have already, but this is sorta required reading IMO. It may seem like a slog, but he really breaks it all down and presents easily used complete examples of all what he talks about:

http://www.gammon.com.au/power

a7

So don't test for exact values. Instead test for equal or greater than the required period. The largest time discrepancy will be 8 seconds. Will the plants care ? I don't think so

1 Like

The DS3231 has two alarms you can set. The DS3231 alarm output can be connected to an Arduino interrupt input to wake the processor. Set one alarm for "every hour at xx:00:00" and the other for "every hour at xx:30:00" and your processor will be awakened every half hour, on the half hour. No need to have the watchdog timer wake you up "about every 8 seconds" to see if a half hour has passed.

Hi everyone

Thanks for the replies, yes I'm aware of the alarm function from the RTC directly, and it would work perfectly if I wanted every 30 mins for 15 seconds.

But this method will not let me choose the hours of operation and will operate every 30 mins, so all through the night again.

So that's why I looked at this time library to do this, which works fine with multiple alarms but not correctly with the sleep mode in operation

Any other suggestions?

Cheers

Hi Alto

Just re-read your message, that also might work, I'll play withe code tomorrow.

Cheers

The RTC alarm can be configured to handle any scenario.

Your code could also help, like take the alarm and ignore it if. Whatever. If the soil is too damp or it is 3 AM.

All depends on what kinda fun you want to have.

But the watch dog timer is a big (relatively speaking) use of power, and an 8 second cycle is very (too) frequent for this project, and does, however slightly, both make the battery last less longer.

a7

Just because you are awakened by an interrupt every half hour doesn't mean you can't just go back to sleep if the hour is < 9 or > 17. It's a lot less power than waking up every 8 seconds and checking a bunch of alarm times to see if the current time matches any of them.