DS3231 Alarm Interrupt Triggering on Startup

Hi everyone

I am an Arduino novice (noob I believe the technical definition is), I have successfully completed the blink tutorial a year ago and that’s about it. I have recently started again, but I am the type of person that garners more from troubleshooting and project based learning than from single tutorials.

I have been dabbling with neopixel rings, as I am wanting to create a sunrise alarm clock (and later add more functionality).
So far I have succeeded in creating this using the Timealarms library, but this is not my end goal as if power goes out then I have no alarm.
I also think that having my Arduino Nano on all the time when it only needs to be awake for 30-60minutes a day is a bit daft, and I do plan on making a battery powered alarm clock for when I go away camping etc. So I am wanting to use RTC Alarm Interrupts for this.

I have set my alarm to trigger once per day, but as soon as the code is uploaded and I go to the serial monitor I receive an “Alarm1 Triggered” message and the neopixels turn on even though it is not the correct time (the proper Alarm Trigger then goes off at my set time). This also occurs when I reset the arduino.

Is this because the attachInterrupt in setup is calling the wakeUpNow function? How could I remedy this?

I am using this library https://github.com/jarzebski/Arduino-DS3231
And I got the majority of my code from this youtube video

I also modified my ZS-042 DS3231 RTC as per this page after I noticed bulging of the battery cell.

Here is my RTC Alarm Int code:

#include <Adafruit_NeoPixel.h>
#include<Wire.h>
#include<DS3231.h>
#include<avr/sleep.h>

#define PIN 7
#define NUMPIXELS 12
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int wakePin=2; //pin used for waking up
int led=13;

DS3231 clock;
RTCDateTime dt;

void setup() {
  Serial.begin(9600);

  //Initialize DS3231
  Serial.println("Initialize DS3231");
  delay(100);
  clock.begin();
  pinMode(wakePin,INPUT_PULLUP);
  pinMode(led,OUTPUT);
  clock.enableOutput(false); //this enables use of the interrupts by disabling the squarewave output
  strip.begin();
  strip.show();

  // Manual (Year, Month, Day, Hour, Minute, Second)
  //clock.setDateTime(2017, 11, 27, 20, 0, 0);

  // Disarm alarms and clear alarms for this example, because alarms is battery backed.
  // Under normal conditions, the settings should be reset after power and restart microcontroller.
  clock.armAlarm1(false);
  clock.clearAlarm1();

  // Set Alarm - Every 01h:10m:30s in each day
  // setAlarm1(Date or Day, Hour, Minute, Second, Mode, Armed = true)
  clock.setAlarm1(0, 22, 22, 00, DS3231_MATCH_H_M_S);
  attachInterrupt(0,wakeUpNow,LOW);

  //Check alarm settings
  checkAlarms();
}

void checkAlarms()
{
  RTCAlarmTime a1;
  RTCAlarmTime a2;

  if(clock.isArmed1())
  {
    a1=clock.getAlarm1();

    Serial.print("Alarm1 is triggered");
    switch(clock.getAlarmType1())
    {

      case DS3231_MATCH_H_M_S:
      Serial.print("when hours, minutes and seconds match:");
      Serial.println(clock.dateFormat("__ __:__:__", a1));
      delay(100);
      break;
      default:
      Serial.println("UNKNOWN RULE");
      break;
    }
  }
}

void wakeUpNow()
{
  //execute code here after wake-up before returning to the loop function
  //timers and code using timers (serial.print and more...) will not work here
  //we dont really need to execute any special functions here, since we
  //just want it to wake up
  //Serial.println("Woke up");
  //delay(100);  
  
  colorWipe(strip.Color(255, 0, 0), 50); // Red
  colorWipe(strip.Color(0, 0, 0), 0);
}

void colorWipe(uint32_t color, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, color);
      strip.show();
      delay(wait);
  }
}

void sleepNow()
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //sleep mode is set here
  sleep_enable(); //enables the sleep bit in the mcucr register
  attachInterrupt(0,wakeUpNow,FALLING); //use interrupt 0 (pin2) and run function
  sleep_mode(); //here the device is actually put to sleep
  //Program continues from here after waking up

  sleep_disable(); //first thing after waking from sleep:disable sleep...
  detachInterrupt(0); //disables interrupt 0 on pin 2 so the wakeUpNow code will not be executed during normal running time
}




void loop() 
{
  dt=clock.getDateTime();

  Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt));
  delay(100);
  //Call isAlarm1(false) if you want to clear alarm1 flag manually by clearAlarm1();
  if(clock.isAlarm1());
  {
    Serial.println("ALARM 1 TRIGGERED!");
    Serial.println("Entering Sleep Mode");
    delay(100); //sleep function called here
    sleepNow();
  }
  delay(900);
}

I may as well post the code I am ultimately trying to merge with the above RTC AlarmInt code in case there is a kind soul who will take pity on my self inflicted plight:

#include <DS3232RTC.h>
#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <Adafruit_NeoPixel.h>
#define LED_DELAY 7500
#define LED_HOLD 1800000
#define NUM_LEDS 40
#define DATA_PIN 2

#define ALARM_HOUR 7
#define ALARM_MIN 0
#define ALARM_SEC 0

#define ALARM_OFF_HOUR 1
#define ALARM_OFF_MIN 1
#define ALARM_OFF_SEC 0

Adafruit_NeoPixel strip = Adafruit_NeoPixel(40, DATA_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  tmElements_t tm;
  tm.Hour = ALARM_HOUR;
  tm.Minute = ALARM_MIN;
  tm.Second = ALARM_SEC;

  setSyncProvider(RTC.get);
  pinMode(DATA_PIN, OUTPUT);

  // Create an alarm for everyday
  Alarm.alarmRepeat(tm.Hour, tm.Minute, tm.Second, Sunrise);

  // Create an alarm to turn the lights off again
  Alarm.alarmRepeat(tm.Hour + ALARM_OFF_HOUR, tm.Minute + ALARM_OFF_MIN, tm.Second + ALARM_OFF_SEC, LightsOff);

}

void loop() {
Alarm.delay(500);
}

void Sunrise() {
  colorWipe(0xff, 0x00, 0x00, LED_DELAY); //Red
  colorWipe(0xff, 0xa5, 0x00, LED_DELAY); //Orange
      //colorWipe(0xff, 0x93, 0x29, LED_DELAY); //Neon Carrot
      //colorWipe(0xff, 0xd7, 0x00, LED_DELAY); //Gold
      //colorWipe(0xff, 0xa5, 0x00, LED_DELAY); //Yellow
  colorWipe(0xff, 0xff, 0x33, LED_DELAY); //Gorse(Yellow)
      //colorWipe(0xff, 0xec, 0x8b, LED_DELAY); //LightGoldenrod
      //colorWipe(0xff, 0xff, 0x7f, LED_DELAY); //Witch Haze(Yellow)
  colorWipe(0xff, 0xff, 0xff, LED_DELAY); //White
      //colorWipe(0x00, 0xff, 0xff, LED_DELAY); //Blueish
  colorWipe(0xb5, 0xcd, 0xff, LED_DELAY); //Light Blue
  colorWipe(0x00, 0x00, 0xff, LED_DELAY); //Blue
  setGroup(0, strip.Color(0x00, 0x00, 0xff));
}

void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
  for (uint16_t i = 0; i < NUM_LEDS; i++) {
    strip.setPixelColor(i, red, green, blue);
    strip.show();
    delay(SpeedDelay);
  }
}

void setGroup(uint8_t g, uint32_t c) {
  int firstPixel = g * 40;
  for(uint8_t i=0; i<40; i++){
    strip.setPixelColor(firstPixel + i, c);
    strip.show();
    delay(LED_HOLD);
  }
}

// turn off the leds
void LightsOff()
{
  //FastLED.clear(); // clear strip data
  strip.clear(); 

}

I appreciate any of your time as I realise you get a large amount of queries from people in over their heads.

When I uncomment the serial.println in the wakeUpNow function it shows this:

Initialize DS3231 Alarm1 is triggeredwhen hours, minutes and seconds match:__ ::__ 27-11-2017 22:38:49 - Monday ALARM 1 TRIGGERED! Entering Sleep Mode Woke up Woke up 27-11-2017 22:40:01 - Monday ALARM 1 TRIGGERED! Entering Sleep Mode

22:38 being the time of the upload and 22:40 being the alarm time.

My understanding is that it should enter wakeUpNow, complete the neopixel function then return to sleep, but it seems that this might not be occurring with the multiple wake ups.

const int or const long or const byte are fare better than typeless #define statements.

You have a clock. You can tell the time. Why do you need the Alarm class?

Does your code work properly if you ingest a bit of caffeine and stay awake?

Hi Paul

Thanks for your reply. Have just done some reading after your post and I think I understand your point.

So I should use const int/long like so: const int PIN=7 const int NUMPIXELS=12

const int LED_DELAY = 7500 const long LED_HOLD = 1800000 const int NUM_LEDS = 40 const int DATA_PIN = 2 Is this correct or could I just use const byte in place of const int so I save memory/ram?

Should I also change these to const int? I read something about naked ints being potentially problematic. int wakePin=2; //pin used for waking up int led=13;

I'm not so sure how I should change the #define ALARM_HOUR, would these be const int or const byte? I am leaning towards using bytes for the alarm class as they are 0-255 values.

The Alarm class was from a sketch I created before I had managed to get an interrupt firing from the DS3231. It is just so I can have a semi functioning alarm light in the interim. The inclusion of the second code was just so anyone could see the eventual light function I am trying to merge with the first code.

Ask me later and we shall see if/how the caffeine has helped ;D

I'm not sure I was that clear but my purpose of posting is due to the interrupt firing on upload/reset as well as then firing when it should do at the programmed alarm time. I was just wanting to figure out why this was before I tried to merge my light sequence in the second code as I need that to run over the course of an hour and if the interrupt triggered that everytime I uploaded or reset then it would make it hard to test.

Again thanks for your help

So I should use const int/long like so:

Like that, but not exactly like that. Semicolons...

could I just use const byte in place of const int so I save memory/ram?

What type is needed to hold the value? If the value is 2 or 40, use byte. If the value is 1234, use int. If the value is 123456, use long.

I'm not sure I was that clear but my purpose of posting is due to the interrupt firing on upload/reset as well as then firing when it should do at the programmed alarm time.

The Alarm class does not use interrupts, so there is no "interrupt firing" going on.

Strip out, or comment out, everything having to do with putting the device to sleep. Does the Alarm callback still happen on reset? Which one?