[SOLVED] Atmega2560 doesn't awake on RTC interrupt

The code below works with UNO to wake up the controller every 15s. But with the mega2560 board it doesn’t work anymore - I can’t figure out why…

The atmega2560 controller goes to sleep and doesn’t wake up anymore on RTC interrupt. I checked the level of interrupt pin - it goes after 15s from high to low, but the controller doesn’t react to this falling edge.

Has anyone an idea why? - please help

#include <DS3232RTC.h>        // https://github.com/JChristensen/DS3232RTC
#include <LowPower.h>
#include "RTClib.h"

RTC_DS3231 rtc;

const byte rtcAlarmPin = 2; // External interrupt on pin D2

void setup()
{
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  Serial.begin(115200);
  pinMode(rtcAlarmPin, INPUT_PULLUP); // Set interrupt pin
  // 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);


  // set the alarm
  DateTime now = rtc.now();
  Serial.println(F("Current Time: "));
  printDateTime(now);
  DateTime future (now + TimeSpan(0, 0, 0, 15)); //Tage, Stunden, Minuten, Sekunden
  Serial.println(F("Alarm is set to: "));
  printDateTime(future);


  RTC.setAlarm(ALM1_MATCH_DATE, future.second(), future.minute(), future.hour(), future.day());
  // clear the alarm flag
  RTC.alarm(ALARM_1);
  RTC.alarmInterrupt(ALARM_1, true); // Enable alarm 1 interrupt A1IE
  // ---Check Alarm Pin/Debug---//
  /*
    int val = digitalRead(2);
    Serial.println("Pin 2 ist: " + String(val));
  */
  // ---------------------//
}

void loop()
{
  // ---Check Alarm Pin/Debug---//
  /*
    int val=digitalRead(2);
    Serial.println("Pin 2 ist: " + String(val));
    delay(1000);
    if (val==0){
     setRTCagain();
     }
  */
  // ---------------------//
  //delay(100);
  digitalWrite(13, LOW);
  delay(200);
  sleepNow(); // Enter slee digitalPinToInterrupt(2)
  digitalWrite(13, HIGH);
  setRTCagain();
  delay(5000);
}
// Interrupt Service Routine (ISR) function
void wake ()
{
  detachInterrupt (digitalPinToInterrupt(rtcAlarmPin)); // Disable interrupts on D2
}

void sleepNow ()
{
  noInterrupts (); // Disable interrupts before entering sleep
  attachInterrupt (digitalPinToInterrupt(rtcAlarmPin), wake, FALLING);  // Wake on falling edge of D2
  interrupts (); // Enable interrupts to ensure next instruction is executed
  Serial.println("Entering sleep");
  delay(20);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}

void setRTCagain() {
  Serial.println("Awake...");
  if ( RTC.alarm(ALARM_1) )
  {
    Serial.println("Now Alarm!");

    // set the alarm
    DateTime now = rtc.now();
    DateTime future (now + TimeSpan(0, 0, 0, 15)); //Days, Hours, Minutes, Seconds
    Serial.println(F("Alarm is set to: "));
    printDateTime(future);
    RTC.setAlarm(ALM1_MATCH_DATE, future.second(), future.minute(), future.hour(), future.day());
  }
}

void printDateTime(DateTime t)
{
  Serial.print((t.day() < 10) ? "0" : ""); Serial.print(t.day(), DEC); Serial.print('/');
  Serial.print((t.month() < 10) ? "0" : ""); Serial.print(t.month(), DEC); Serial.print('/');
  Serial.print(t.year(), DEC); Serial.print(' ');
  Serial.print((t.hour() < 10) ? "0" : ""); Serial.print(t.hour(), DEC); Serial.print(':');
  Serial.print((t.minute() < 10) ? "0" : ""); Serial.print(t.minute(), DEC); Serial.print(':');
  Serial.print((t.second() < 10) ? "0" : ""); Serial.println(t.second(), DEC);
}

Pin 2 is interrupt 0

//Mega2560
// external interrupt int.0 int.1 int.2 int.3 int.4 int.5
// pin 2 3 21 20 19 18

Make debuggin a lot easier by reducing the code to the bare minimum that exhibits the problem.

Get rid of all the RTC and printing of date and time stuff, replace the RTC interrupt with a switch.

Now you have a small bit of code that just sets up the interrupts and sends the mega2560 to sleep, does it wake up when you close the switch ?

Wood from the Trees.

Sorry. on the Mega pin 2 is PE4 which is INT4.
INT CPU Mega
0 PD0 - 43 21
1 PD1 - 44 20
2 PD2 - 45 19
3 PD3 - 46 18
4 PE4 - 6 2
5 PE5 - 7 3
Basically same difference though, the external interrupts (as opposed to the pin change interrupts) are synchronous, which means that if they are to respond to a level change (RISING, FALLING) there must be a clock active. In all but the idle mode of sleep, the clocks are switched off. The only thing that will trigger an interrupt in that case is a sustained LOW for as long as it takes to wake up and service the interrupt. If the signal is not held long enough...

"If the level disappears before the end of the Start-up Time, the MCU will still wake up, but no interrupt will be generated."

Fair enough. I don't use those libraries. The issue remains however, that a RISING or FALLING interrupt will not trigger a hardware interrupt on those pins. One needs to use a pin change interrupt, of which there are 20 exposed on the Mega. If the OP had done a bit of research, this issue has risen numerous times in the recent past. I know because I've ended up giving the same tutorial again and again.

DKWatson:
Fair enough. I don’t use those libraries. The issue remains however, that a RISING or FALLING interrupt will not trigger a hardware interrupt on those pins. One needs to use a pin change interrupt, of which there are 20 exposed on the Mega. If the OP had done a bit of research, this issue has risen numerous times in the recent past. I know because I’ve ended up giving the same tutorial again and again.

I didn’t know that it is not possible to wake up the controller with INT4 (D2). @ DKWatson thanks for your answer regarding PCINT. Now i use Pin D10 (PCINT4) for the rtc interrupt and it works. Here my code:

#include <DS3232RTC.h>        // https://github.com/JChristensen/DS3232RTC
#include <LowPower.h>
#include "RTClib.h"
#include "PinChangeInterrupt.h"  //https://github.com/NicoHood/PinChangeInterrupt

RTC_DS3231 rtc;

#define rtcAlarmPin 10 // External interrupt on pin D3
volatile bool alarmNow = false;
void setup()
{
  pinMode(22, OUTPUT);
  digitalWrite(22, LOW);
  Serial.begin(115200);
  pinMode(rtcAlarmPin, INPUT_PULLUP); // Set interrupt pin
  attachPCINT(digitalPinToPCINT(rtcAlarmPin), wake, FALLING);
  // 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);

  // set the alarm
  DateTime now = rtc.now();
  Serial.println(F("Current Time: "));
  printDateTime(now);
  DateTime future (now + TimeSpan(0, 0, 0, 15)); //Tage, Stunden, Minuten, Sekunden
  Serial.println(F("Alarm is set to: "));
  printDateTime(future);
  
  RTC.setAlarm(ALM1_MATCH_DATE, future.second(), future.minute(), future.hour(), future.day());
  // clear the alarm flag
  RTC.alarm(ALARM_1);
  RTC.alarmInterrupt(ALARM_1, true); // Enable alarm 1 interrupt A1IE
}

void loop()
{
  sleepNow(); // Enter slee digitalPinToInterrupt(2)
  setRTCagain();
}
// Interrupt Service Routine (ISR) function
void wake ()
{
  // detachInterrupt (INT2); // Disable interrupts on D3
}

void sleepNow ()
{
  noInterrupts (); // Disable interrupts before entering sleep
  // attachInterrupt (INT2, wake, FALLING);  // Wake on falling edge of D3
  interrupts (); // Enable interrupts to ensure next instruction is executed
  Serial.println("Entering sleep");
  delay(20);
  Serial.flush();
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}

void setRTCagain() {
  Serial.println("Awake...");

  if ( RTC.alarm(ALARM_1) )
  {
    Serial.println("Now Alarm!");
    // set the alarm
    DateTime now = rtc.now();
    DateTime future (now + TimeSpan(0, 0, 0, 15)); //Days, Hours, Minutes, Seconds
    Serial.println(F("Alarm is set to: "));
    printDateTime(future);
    RTC.setAlarm(ALM1_MATCH_DATE, future.second(), future.minute(), future.hour(), future.day());
  }
}

void printDateTime(DateTime t)
{
  Serial.print((t.day() < 10) ? "0" : ""); Serial.print(t.day(), DEC); Serial.print('/');
  Serial.print((t.month() < 10) ? "0" : ""); Serial.print(t.month(), DEC); Serial.print('/');
  Serial.print(t.year(), DEC); Serial.print(' ');
  Serial.print((t.hour() < 10) ? "0" : ""); Serial.print(t.hour(), DEC); Serial.print(':');
  Serial.print((t.minute() < 10) ? "0" : ""); Serial.print(t.minute(), DEC); Serial.print(':');
  Serial.print((t.second() < 10) ? "0" : ""); Serial.println(t.second(), DEC);
}

Glad to have helped. Can you edit your original post now and include [SOLVED] in the subject line please and thanks.

Good for you. And for posting your code correctly and such, I'll award you your first karma.