DS3231 Sleep and wakeup on Mega2560

Hi everybody,
in order to reduce the power as much as possible, I'm trying to wake up my Elegoo Mega every 15 minutes.
I'm using a DS3231 and I started from this sketch to try to understand how I can configure everything for my requirements.
Using this sketch I'm able to send the Arduino to sleep but it's not awakened.
Are there any differences about this aspect between Arduino Uno e and Mega?
I tried also using wakeup pin 2 and 18 (as I reed searching on the web)

#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 = 18;  // Porta per il segnale di risveglio - pin used for alarm clock (interrupt 0)
byte temp_buffer = 0b11110111; // configurazione 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]; // zona di memorizzazione data ed ora fornita da ds3231 - repository actual time from ds3231
//
//
//  ****** routine di modifica del byte di controllo DS3231 - Set DS3121 SQW control bytes
//
void modificabyte (byte control, bool which)   // 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" - sleep routine
//
void dormiora()
{
  Serial.print("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);
  Serial.println(print_date);  // visualizza sul monitor seriale il momento dell'addormentamento - display sleeping time on serial monitor
  sleep_enable();        // abilita l'addormentamento del sistema
  delay(100);
  digitalWrite (LED_BUILTIN, 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.print("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
}
//
//
void setup()
{
  Serial.begin(9600);
  clock.begin();
  modificabyte(temp_buffer, 0);
  clock.armAlarm1(false);
  clock.armAlarm2(false);
  clock.clearAlarm1();
  clock.clearAlarm2();
  pinMode (LED_BUILTIN, OUTPUT); // alla porta 4 e' collegato il led che segnala lo dtato di "sveglio" 
  pinMode(wakePin, INPUT);  // la porta 2 riceve l'allarme da DS3232 - pin 2 for alarm signal from ds3232
  attachInterrupt(0, svegliatiora, FALLING);   // attiva la gestione dell'interrupts - enable intrrupts
  //clock.setDateTime(2022, 3, 27, 15, 15, 45);  // 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.
}
//
//
void loop()
{
    // setAlarm2(Date or Day, Hour, Minute, Mode, Armed = true)
  clock.setAlarm2(0, 0, 1,     DS3231_MATCH_M);
  //clock.setAlarm1(0, 0, 0, 10, DS3231_MATCH_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
  //
  // **** punto in cui il sistema rientra nella sezione di loop dopo il risveglio - arduino start working here after woke
  //
  digitalWrite (LED_BUILTIN, HIGH); // segnala lo stato di "sveglio" - woke status signal

  delay (5000);  // rimane sveglio per 5 secondi - arduino remain active for 5 seconds
  Serial.println("Sveglio!");
}

Please note that I'm not the author of this sketch!

so the second comment states pin #2 is to be used, (which would make sense since your attachInterrupt() uses interrupt #0 which corresponds to pin 2) but your definition says it's pin 18....

As I wrote, I tried using pin 2 and pin18 also with the same result..

You need to use pin 2 with your code

Make a small code with setting the RTC’s alarm in the setup and activate the ISR on pin 2

Yes, of course I also changed the code variable wakePin when I changed the pin connection...

Can you use your voltmeter to determine where the problem is? Is the INT/SQW pin of the DS3231 high normally, and then does it go low at wakeup time? If it does all that, then the problem is that your interrupt isn't set up right to wake up. If it doesn't do that, then the alarm isn't being enabled properly in the DS3231 in the first place.

Hi @ShermanP , thanks for your reply. I'm not an electronic expert so, please, try to guide me with this test. Let Me to expone what I tried:

  • I switched on my voltmeter and I rotated the configurator mechanism on 20v.
  • I linked the black cable to the Arduino GND and the red cable to the DS3231 SQW pin.
    the values that I see oscillates between 0.09 to 0.11
    I tried this different times and I waited with this configuration for some minutes for each test session.

Well first try measuring the voltage on the Mega's 5V pin and 3.3V pin, and confirm that you're measuring correctly. Your meter should show roughly those voltages.

The SQW pin needs a pullup resistor, either a physical resistor on a module, or the internal pullup resistor on the Mega's D2. Are you using a discrete DS3231 chip, or are you using a module like the ZS-042? The module has a pullup resistor that works fine if there is power at the module's Vcc pin. If you're using a discrete chip, then you need to add a pullup resistor, or change the pinMode instruction from INPUT to INPUT_PULLUP.

So how this works is the SQW pin is normally high (5V) during normal Mega operation. And it stays high while the Mega sets the alarm time and enables the alarm interrupt, then goes to sleep. Then at the alarm time the SQW pin is drawn low, which triggers the FALLING interrupt, the Mega wakes up, and then clears the alarm in the DS3231, which allows SQW to go back high. You may not be able to see the low pulse on your meter because it happens so fast. But if you are measuring low on SQW all the time, then either there is no pullup resistor, or the alarm isn't being cleared.

A FALLING interrupt triggers only when the voltage drops from 5V to ground. If SQW is always low, no interrupt will be triggered.

I haven't studied your code, but it looks like you are setting Alarm2, but clearing Alarm1. You might try commenting out the line which sets Alarm2, and uncommenting the line below it (set Alarm1).

I think you should be using pin 2, not pin 18, with your sketch. Edit: I shouldn't say that. I've never used a Mega2560. But the pin you use should be the same pin implied in your attachInterrupt line, whatever interrupt zero is on a Mega.

@ShermanP thanks for your suggestion. I’ll try to apply the suggested changes code side..in the mean time the DS3231 module that I’m using is this: AZDelivery Real Time Clock RTC... https://www.amazon.it/dp/B01M2B7HQB?ref=ppx_pop_mob_ap_share

Yes, that's the typical DS3231 module. It's also known as the ZS-042 module. It includes a pullup resistor on SQW.

So either you're using the wrong pin on the Mega, or the right alarm isn't being cleared. You probably should clear both alarms just to be safe.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.