I am trying to make a simple sensor node for a project of mine and I’ve stumbled upon this issue with the deep sleep or STANDBY mode.
For my hardware, I am using:
Board: Arduino MKR1310 WAN
RTC: DS3231 module
The SQW pin is connected to the INT7(pin 7) of the board.
Here is the sketch. It’s a modified version of the example given here.
#include <Arduino.h>
#include <Wire.h>
#include <RTC.h>
#include <SPI.h>
void ISR();
void setAlarm();
void deepSleep();
void onAlarm();
// the pin that is connected to SQW
#define CLOCK_INTERRUPT_PIN 7
bool alarmSet = false;
void setup() {
Serial.begin(9600);
// initializing the rtc
if(!rtc.begin()) {
Serial.println("Couldn't find RTC!");
Serial.flush();
while (1) delay(10);
}
if(rtc.lostPower()) {
// this will adjust to the date and time at compilation
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
//we don't need the 32K Pin, so disable it
rtc.disable32K();
// Making it so, that the alarm will trigger an interrupt
pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), ISR, FALLING);
// set alarm 1, 2 flag to false (so alarm 1, 2 didn't happen so far)
// if not done, this easily leads to problems, as both register aren't reset on reboot/recompile
rtc.clearAlarm(1);
rtc.clearAlarm(2);
// stop oscillating signals at SQW Pin
// otherwise setAlarm1 will fail
rtc.writeSqwPinMode(DS3231_OFF);
// turn off alarm 2 (in case it isn't off already)
// again, this isn't done at reboot, so a previously set alarm could easily go overlooked
rtc.disableAlarm(2);
}
void loop() {
// Initial safety delay
delay(10000);
char date[10] = "hh:mm:ss";
rtc.now().toString(date);
Serial.print(date);
// the stored alarm value + mode
if(!alarmSet){
setAlarm();
}
DateTime alarm1 = rtc.getAlarm1();
Ds3231Alarm1Mode alarm1mode = rtc.getAlarm1Mode();
char alarm1Date[12] = "DD hh:mm:ss";
alarm1.toString(alarm1Date);
Serial.print(" [Alarm1: ");
Serial.print(alarm1Date);
Serial.print(", Mode: ");
switch (alarm1mode) {
case DS3231_A1_PerSecond: Serial.print("PerSecond"); break;
case DS3231_A1_Second: Serial.print("Second"); break;
case DS3231_A1_Minute: Serial.print("Minute"); break;
case DS3231_A1_Hour: Serial.print("Hour"); break;
case DS3231_A1_Date: Serial.print("Date"); break;
case DS3231_A1_Day: Serial.print("Day"); break;
}
Serial.println("]");
deepSleep();
}
void setAlarm() {
if(!rtc.setAlarm1(
rtc.now() + TimeSpan(10),
DS3231_A1_Second // this mode triggers the alarm when the seconds match. See Doxygen for other options
)) {
Serial.println("Error, alarm wasn't set!");
}else {
Serial.println("Alarm will happen in 10 seconds!");
alarmSet = true;
}
}
void deepSleep() {
// Set the sleep mode to standby
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
// SAMD sleep and wait for interrupt;
__WFI();
}
void ISR() {
Serial.println("I WOKE UP!");
rtc.clearAlarm(ALARM_1);
alarmSet = false;
}
RTC.h
#include <RTClib.h>
#define ALARM_1 ((uint8_t)1)
#define ALARM_2 ((uint8_t)2)
#define EXT_INT ((uint8_t)4)
RTC_DS3231 rtc;
The thing is that if I remove the deepSleep
function call, the alarm goes off and ISR
function is called once every 10 seconds. But just using this sketch as it is, the controller goes to sleep and never wakes up.
What exactly am I doing wrong? I have no idea. Please help!
NOTE:
The big delay
at the start of the loop
is to be able to program the board without resetting it.