External RTC to wake Arduino up on interrupt

Hi.

I have got RTC DS3231 working pretty well. I set my RTC to send interrupt signal on int.0 (pin2) every full minute. Was working great, I had the LED switch ON/OFF every minute. I assumed here that interrupts are working and I can use it as interrupt to wake an Arduino up. Well not so much.

Must mention here that I am using:
This library for low power
and This library for DS3231.

As provided in an example from library and HERE I am told that I can wake up Arduino when pin is low.

What I would like to achieve is obviously to wake Arduino up on interrupt from DS3231 every minute.
Here is my code. Would appreciate any help on that.

// Using JChristensen library

#include <DS3232RTC.h>
#include <Time.h>
#include <Wire.h>
#include "LowPower.h"

tmElements_t tm;

time_t cvt_date(char const *date, char const *time)
{
    char s_month[5];
    int year;
    tmElements_t t;
    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

    sscanf(date, "%s %hhd %d", s_month, &t.Day, &year);
    sscanf(time, "%2hhd %*c %2hhd %*c %2hhd", &t.Hour, &t.Minute, &t.Second);

    t.Month = (strstr(month_names, s_month) - month_names) / 3 + 1;
   
    /*
    if( year > 99)
      t.Year = year - 1970;
    else
      t.Year = year + 30;
    */
    t.Year = year - 1970;

    return makeTime(t);
}

int switchPin = 2;
int ledPin = 13;
boolean lastButton = LOW;
boolean ledOn = false;

void blink() {
  if (digitalRead(switchPin) == HIGH && lastButton == LOW) {
    ledOn = !ledOn;
    lastButton = HIGH;
  } else {
    lastButton = digitalRead(switchPin);
  }
  digitalWrite(ledPin, ledOn);
}

void pin2Interrupt(void)
{

}

void setup(void) {
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  pinMode(switchPin,INPUT);

  //attachInterrupt(0, pin2Interrupt, CHANGE);
  
  Serial.println(String("__DATE__ = ") + __DATE__);
  Serial.println(String("__TIME__ = ") + __TIME__);
  
  setTime(cvt_date(__DATE__, __TIME__));
  RTC.set(now());
  RTC.squareWave(SQWAVE_NONE); 
  RTC.setAlarm(ALM2_EVERY_MINUTE,0,0,0);
  RTC.alarmInterrupt(ALARM_2, true);
  
  Serial.println(String("System date = ") + day() + "/" + month() + "/" + year() + " " + hour() + ":" + minute() + ":" + second() + "\n");

}

void loop(void) {
  //digitalClockDisplay(); //print time and date
  Serial.println("Entering sleep mode");
  delay(1000);
  attachInterrupt(0, pin2Interrupt, LOW);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  detachInterrupt(0); 
}

void digitalClockDisplay(void)
{
  // digital clock display of the time
  RTC.read(tm);
  Serial.print(tm.Day,DEC);
  Serial.print('/');
  Serial.print(tm.Month, DEC);
  Serial.print('/');
  Serial.print(tm.Year+1970, DEC);
  Serial.print("   ");
  Serial.print(tm.Hour, DEC);
  Serial.print(':');
  Serial.print(tm.Minute, DEC);
  Serial.print(':');
  Serial.println(tm.Second, DEC);
  
  if (RTC.alarm(ALARM_2) ) {
    Serial.println("ALARM");
  }
}

I have 4.7k Ohm resistor between SQW and +5V.

  attachInterrupt(0, pin2Interrupt, LOW);

You are better off using FALLING than LOW.

Well not so much.

What is the problem? It doesn't sleep? It doesn't wake?

MASSIVE EDIT : Wow. Nick you were right. Tried it with FALLING and it works like a charm. Thanks!

After Nick posted I got it working without 3rd party library like this but first code is neater:

#include <avr/sleep.h>
#include <avr/power.h>
#include <DS3232RTC.h>
#include <Time.h>
#include <Wire.h>

tmElements_t tm;

//CONVERT __DATE__ and __TIME__ to time_t
time_t cvt_date(char const *date, char const *time) {
    char s_month[5];
    int year;
    tmElements_t t;
    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

    sscanf(date, "%s %hhd %d", s_month, &t.Day, &year);
    sscanf(time, "%2hhd %*c %2hhd %*c %2hhd", &t.Hour, &t.Minute, &t.Second);

    t.Month = (strstr(month_names, s_month) - month_names) / 3 + 1;
   
    /*
    if( year > 99)
      t.Year = year - 1970;
    else
      t.Year = year + 30;
    */
    t.Year = year - 1970;

    return makeTime(t);
}

int pin2 = 2;

void pin2Interrupt(void) {

  detachInterrupt(0);
}

void enterSleep(void) {
  
  /* Setup pin2 as an interrupt and attach handler. */
  attachInterrupt(0, pin2Interrupt, LOW);
  delay(100);
  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  
  sleep_enable();
  
  sleep_mode();
  
  /* The program will continue from here. */
  
  /* First thing to do is disable sleep. */
  sleep_disable(); 
}

void setup() {
  Serial.begin(9600);
  
  /* Setup the pin direction. */
  pinMode(pin2, INPUT);
  
  setTime(cvt_date(__DATE__, __TIME__));
  RTC.set(now());
  RTC.squareWave(SQWAVE_NONE); 
  RTC.setAlarm(ALM2_EVERY_MINUTE,0,0,0);
  RTC.alarmInterrupt(ALARM_2, true);
  
  Serial.println(String("System date = ") + day() + "/" + month() + "/" + year() + " " + hour() + ":" + minute() + ":" + second() + "\n");
  
  Serial.println("Initialisation complete.");
}

int seconds = 0;

void loop() {
  delay(1000);
  seconds++;
  
  Serial.print("Awake for ");
  Serial.print(seconds, DEC);
  Serial.println(" second");
  //digitalClockDisplay(); //print time and date
  
  if(seconds == 3) {
    Serial.println("Entering sleep");
    digitalClockDisplay();
    delay(200);
    seconds = 0;
    enterSleep();
  }
  
}

//PRINT TIME FROM RDS3231
void digitalClockDisplay(void) {
  // digital clock display of the time
  RTC.read(tm);
  Serial.print(tm.Day,DEC);
  Serial.print('/');
  Serial.print(tm.Month, DEC);
  Serial.print('/');
  Serial.print(tm.Year+1970, DEC);
  Serial.print("   ");
  Serial.print(tm.Hour, DEC);
  Serial.print(':');
  Serial.print(tm.Minute, DEC);
  Serial.print(':');
  Serial.println(tm.Second, DEC);
  
  if(RTC.alarm(ALARM_2)) {
    Serial.println("ALARM");
  }
}

I read in the Atmega328 datasheet that for INT0 and INT1 only a "level interrupt" will wake the processor. Why, then, is it waking on an edge interrupt?

|500x240

See: http://www.gammon.com.au/interrupts

Confirmed by Atmel that the datasheet is wrong:

Commented by Manoraj Gnanadhas (Atmel) 2015-01-20 06:23:36 GMT [Recipients: Nick Gammon]

Hello Nick,

Our design team has confirmed that “Note-3 mentioned under Table 10-1” is a datasheet bug. So you can use any type of interrupt (Rising edge/ Falling edge / Low level / Any logical change) to wake up from sleep mode. Sorry for the inconvenience caused.

Best Regards, Manoraj Gnanadhas

Nice!

edit: So why doesn’t a level interrupt work for him?

Level interrupts are problematic because they continue firing. Unlike an edge interrupt it keeps calling the ISR while the level is still LOW. This could cause the sketch to run extremely slowly until the interrupt is disabled.

How did you know I edited this thread?

Is there an edge interrupt for forum thread edits that you had enabled?

Under each post it tells you if someone edited it:

Re: External RTC to wake Arduino up on interrupt
Jul 03, 2015, 10:33 am Last Edit: Jul 04, 2015, 01:40 am by jboyton

Or did you not mean that?

No, I meant how did you know to go back and look at this thread when it hadn't been replied to since your last post? Is there a notification mechanism for threads where a post is edited?

Ah, I see. As it happened I was searching for a thread that mentioned Manoraj Gnanadhas from Atmel, because of the issue of whether interrupts were triggered by a falling level or not. Having found this thread (for an unrelated reason to your edit) I noticed the edit and responded to it.