Wake from external interrupt not working with MEGA (OK with uno)

Hello,

My problem today is about a code which is working on arduino Uno board but not on arduino Mega.
I don’t know why… Any help will be appreciated…

My program should turn on a led during 20 second and go to sleep, at each 30 minutes it should wake my arduino, turn on led for 20s and go to sleep… So it work well with a uno and not with mega…
It’s a DS3231 which should trigger the external interrupt

I’ve slighty adapted a code from this tutorial :sleep e risveglio (wake) tramite interrupts da RTC DS3231 - Arduino - e45bis - YouTube

I’ve tried others attachinterrupt function without success like:

attachInterrupt(digitalPinToInterrupt(2), svegliatiora, FALLING);

complete code :

/* Attenzione: facendo il copia/incolla dal PDF all’IDE si perde la formattazione del testo.
  Per rendere piu’ facilmente leggibile il programma e’ opportuno formattarlo subito dopo il
  trasferimento nell’IDE, premendo CTRL+T.
  Questo programma e' derivato da un analogo programma reperito in rete
  Arduino entra in stato di sleep e viene risvegliato, al decimo secondo di ogni
  minuto, da un impulso lanciato da un orologio digitale (DS3231).
  Una vola sveglio accende e mantiene acceso un led per 5 secondi dopo di che entra
  di nuovo in stato di sleep, in attesa del successivo impulso proveniente dall'orologio

  per ottenere questo risultato e' stato necessario modificare il funzionamento del pin
  SQW del modulo DS3231 intervenendo su di un byte di controllo interno al modulo.
  Senza questa modifica il sistema non riesce ad addormentarsi


  --------------------------------------------------------------------------------------------
  Warning: cut and paste from PDF to IDE loses formatting. To restore it press CTRL + T

  Tis program is based on program found on line

  Arduino wakes (from a sleep state) on interrupts launched from an external digital clock
  (DS3231 RTC). To rise this goal must be change a control byte on DS3231.
  Without that change Arduino doesn't go to sleep mode even the first time
  --------------------------------------------------------------------------------------------
  //Arduino: sleep e wake su interrupts da RTC DS3231
  //arduino, ds3231, Wake, interrupts, wakeup, sleep,
*/
#include <Wire.h> //libreria wire, presente di default nell'IDE
#include <DS3231.h> // Libreria ds3231, https://github.com/jarzebski/Arduino-DS3231
#include <avr/sleep.h> // libreria avr/sleep, presente di default nell'IDE
DS3231 clock;
RTCDateTime dt;
const byte wakePin = 2; //Porta per il segnale di risveglio - pin used for alarm clock (interrupt 0)
byte temp_buffer = 0b11110111; // struttura del byte che disabilita il pin SQW sul modulo DS3231.
// Sembra inutile, ma senza di questo arduino non si addormenta. - Byte to disable SQW pin
// of DS3231, not logical yes, but without that the Arduino doesn't go to sleep mode even the first time
char print_date[16]; // memorizzazione della data ed ora fornita da ds3231 – Actual time repository
uint8_t trent = 0;
//
//
// ************* routine di modifica del byte di controllo DS3231 ***********************
// ********************** Set DS3121 SQW control bytes **********************************
//
void modificabyte (byte control, bool which) // aggiorna il byte di controllo su ds3231 - Set
// DS3121 RTC control bytes
{
  Wire.beginTransmission(0x68);
  if (which) // which=false -> 0x0e, true->0x0f.
    Wire.write(0x0f);
  else
    Wire.write(0x0e);
  Wire.write(control);
  Wire.endTransmission();
}
//
//
// ******** routine di sveglia, attivata dall'interrupt (su allarme DS3231) *****************
// *************wake routine, activated on interrupt from ds3231 ****************************
//
void svegliatiora()
{
  sleep_disable(); // disabilita la modalita' sleep (sveglia il sistema)
}
//
//
// ************************* routine di "addormentamento" *********************************
// ****************************** asleep routine ******************************************
//
void dormiora()
{
  Serial.println("dormo - sleep.... ");
  dt = clock.getDateTime(); // chiede l'ora dall'orologio digitale DS3231 - get time form DS3231
  sprintf(print_date, "%02d/%02d/%d %02d:%02d:%02d", dt.day, dt.month, dt.year, dt.hour, dt.minute, dt.second);
  //display sleeping time on serial monitor
  sleep_enable(); // abilita l'addormentamento del sistema
  delay(100);
  digitalWrite (13, LOW); // spegne il led 4, per segnalare che il sistema e' dormiente
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Seleziona la modalita' "power down", che massimizza
  // il risparmio di energia - Select "power down mode" to maximize energy saving
  cli(); // disabilita l'interrupt - disable interrupts
  //sleep_bod_disable(); // disabilita il controllo interno di alimentazione (brown out detection)
  sei(); // riabilita l'interrupt - enable interrupts
  sleep_cpu(); // "addormenta" la cpu - sleep mode on cpu
  //
  // **questo e' il punto in cui Arduino riprende a lavorare, subito dopo la routine svegliatiora
  // ****************************arduino wake up here *****************************************
  //
  clock.clearAlarm1(); // elimina l'allarme (per evitare ulteriori indesiderati interrupt)
  Serial.println("sveglio - working.. ");
  dt = clock.getDateTime(); // chiede l'ora dall'orologio digitale DS3231 - get time form DS3231
  sprintf(print_date, "%02d/%02d/%d %02d:%02d:%02d", dt.day, dt.month, dt.year, dt.hour, dt.minute, dt.second);
  Serial.println(print_date); // visualizza sul monitor seriale il momento della sveglia
  //display wake time on serial monitor

  trent = dt.minute + 30;
  if ( trent > 59 ) {
    trent = trent - 60;
  }
}
//
//
void setup()
{
  Serial.begin(9600);
  clock.begin();
  //Arduino: sleep e wake su interrupts da RTC DS3231
  //arduino, ds3231, Wake, interrupts, wakeup, sleep,
  modificabyte(temp_buffer, 0); //lancia la routine di modifica del byte su ds3231 - call DS3231 byte modify routine
  clock.armAlarm1(false);
  clock.armAlarm2(false);
  clock.clearAlarm1();
  clock.clearAlarm2();
  pinMode (13, OUTPUT); // alla porta 4 e' collegato il led che segnala lo stato di "sveglio"
  pinMode(wakePin, INPUT); //la porta 2 riceve l'allarme da DS3232 - pin 2 for alarm from ds3232
  attachInterrupt(0, svegliatiora, FALLING); // attiva l’interrupts - enable intrrupts
  clock.setDateTime(2017, 02, 10, 11, 00, 00); // inizializza l'orologio con data ed ora prefissata,
  // utile al solo fine del test. In caso di uso effettivo l'orologio deve essere inzializzato
  // una sola volta, con data ed ora effettiva
  // initializes ds3231 with a dummy date and hour.
  trent = 30;
  upLED();
}
//
//
void upLED() {
  digitalWrite (13, HIGH); // segnala lo stato di "sveglio" - woke status signal
  delay (20000); // rimane sveglio per 5 secondi - arduino work for 20 seconds
}

void mainprog() {

  //
  // **** punto in cui il sistema rientra nella sezione di loop dopo il risveglio
  // ********** Arduino return in loop section here, after woke
  //
  upLED();

}

void loop()
{
  Serial.print("next wake up at min : ");
  Serial.println(trent);

  Serial.print(print_date); // visualizza sul monitor seriale il momento dell'addormentamento –
  clock.setAlarm1(0, 0, trent, 0, DS3231_MATCH_M_S); // attiva la sveglia al 10 secondo di ogni minuto –
  // set alarm on the tenth second of every minute
  delay (100);
  dormiora(); // richiama la routine di addormentamento - call sleep routine
  mainprog();
}

thanks
Aurelien

How did you wire the DS3231 to the Arduino? Do you have a pull-up to Vcc for the INT pin as the datasheet shows? Otherwise the interrupt signal will never reach the Arduino.

hello

Thanks for your reply

it's wired directly between the INT/SQW pin and arduino pin 2. there is no pull up resistor. I will try with a pull up. Even if it's the solution how can explain it works on UNO and not on MEGA board?

With a pull up resistor (10K) it is also not working...

One other thing strange... The serial monitor is not displaying the sleeping time (void dormiora) on serial monitor (but it should because it is before sleep instruction) this line :

sprintf(print_date, "%02d/%02d/%d %02d:%02d:%02d", dt.day, dt.month, dt.year, dt.hour, dt.minute, dt.second);

I think it's only related to the refresh rate of the serial monitor. but I want to be sure there is no impact on other instruction... I want to be sure is not sleeping too early...

I finally found the solution... For MEGA board, the pin 2 is not able to detect edge interrupts (FALLING in my case) when the sleep mode is SLEEP_MODE_PWR_DOWN.

I have to use pin 18...

thanks GUIX from this post for the solution : http://forum.arduino.cc/index.php?topic=390545.msg2691957#msg2691957

  sprintf(print_date, "%02d/%02d/%d %02d:%02d:%02d", dt.day, dt.month, dt.year, dt.hour, dt.minute, dt.second);

This line doesn't print anything to the serial interface, it just fills the string "print_date" with the numbers in the last paramters using the format in the second parameter.