2

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

enter image description here

Does anyone know what causes this issue and how can it be solved?

3
  • Never use Serial in an interrupt. It itself relies on an interrupt, which can't happen because your interrupt is the one running.
    – Majenko
    Commented Nov 29, 2020 at 11:17
  • I removed all the Serial prints and the issue is still present. Nothing in the onAlarm() method is run and the code freezes Commented Nov 29, 2020 at 11:40
  • You may be calling a function that itself calls 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 in loop() to do your actual work. The interrupt captures the event, but doesn't do the work.
    – Majenko
    Commented Nov 29, 2020 at 11:41

1 Answer 1

2

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.

1
  • Thaks, it works with both of the options you gave, but I chose the one with the bool Commented Nov 29, 2020 at 12:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.