I am quite noobish with using the interrupts on Arduino and I am facing a strange problem. I am using an Arduino Pro Mini, a light sensor and an RTC module(DS3231) which has set 2 alarms, one at sunrise and one at the sunset. Each time the DST triggers the alarm, the interrupt routine (here onAlarm()) blocks the state of Arduino and nothing happens form there. Is there anything wrong with the code I write?
The code bellow is a little bit simplified, I just let the method calls, not the whole declarations of them.
#include <avr/sleep.h>//this AVR library contains the methods that controls the sleep modes
#include <avr/power.h>
#include <DS3232RTC.h> //RTC Library https://github.com/JChristensen/DS3232RTC
#define ldrInterruptPin 2
#define DS2331interruptPin 3
void setup() {
Serial.begin(9600);//Start Serial Comunication
Wire.begin();
//_____________________setup DS3231 interrupts_________
pinMode(DS2331interruptPin, INPUT_PULLUP);
digitalWrite(DS2331interruptPin, HIGH);
attachInterrupt(digitalPinToInterrupt(DS2331interruptPin), onAlarm, FALLING);
//_____________________setup LD235R interrupts_________
pinMode(ldrInterruptPin, INPUT);
digitalWrite(ldrInterruptPin, HIGH);
attachInterrupt(digitalPinToInterrupt(ldrInterruptPin), irq1, RISING);
resetDS3231Alarms();
time_t t = RTC.get();
setUpAlarms();
}
void loop() {
//read the light sensor vlaues
}
Adn this is the onAlarm function:
void onAlarm() {
Serial.println("ALARM");
formatTime(timestamp, RTC.get());
if (RTC.alarm(ALARM_1))
{
Serial << F("SLEEP alarm at ") << timestamp << endl;
goToSleep();
}
else if (RTC.alarm(ALARM_2))
{
Serial << F("WakeUP Alarm at ") << timestamp << endl;
Serial.println("Time to Wake up......!");
sleep_disable();
Serial.println("I woke up!!!");
attachInterrupt(digitalPinToInterrupt(ldrInterruptPin), irq1, RISING);
}
//update the sleep and wakeup times based on curreent day
setUpAlarms();
};
resetAlarms()
void resetDS3231Alarms() {
// initialize the alarms to known values, clear the alarm flags, clear the alarm interrupt flags
RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);
RTC.alarm(ALARM_1);
RTC.alarm(ALARM_2);
RTC.alarmInterrupt(ALARM_1, false);
RTC.alarmInterrupt(ALARM_2, false);
RTC.squareWave(SQWAVE_NONE);
}
Every time an alarm occurs, the code blocks and outputs exactly what is in the serial monitor capture bellow: It just prints "AL" form the Serial.println("ALARM"); and nothing happens from there
Does anyone know what causes this issue and how can it be solved?
1 Answer 1
When the AVR processor goes to sleep, the only way it can wake up is by an interrupt. If it goes to sleep with interrupts disabled, then it will never wake up.
Interrupt routines are by default non-interruptible: the first thing the
processor does when servicing an interrupt is to disable further
interrupts. Your onAlarm()
function is thus running with interrupts
disabled. If it goes to sleep, it will lock the processor.
A quick and dirty fix would be to call interrupts()
right before going
to sleep. I would not recommend that though, as you will end up piling
interrupt contexts one over another. The proper fix would be to trim
down your interrupt service routines to the bare minimum that must be
done immediately, and handle everything else in regular code, within
loop()
. In this particular case, setting a volatile bool
might well
be the only thing you really need to do. Your loop()
would test that
bool
and take care of everything else.
-
Thaks, it works with both of the options you gave, but I chose the one with the boolEmanuel Giurgiu– Emanuel Giurgiu2020年11月29日 12:38:45 +00:00Commented Nov 29, 2020 at 12:38
Explore related questions
See similar questions with these tags.
Serial
in an interrupt. It itself relies on an interrupt, which can't happen because your interrupt is the one running.delay()
. That will also break. Interrupts should be the absolute minimum you can get away with - ideally just set a flag then examine that flag inloop()
to do your actual work. The interrupt captures the event, but doesn't do the work.