DS3231 alarm-interrupt
/*H*******************************************************
AlarmInterrupt.ino
Jacob Nuernberg 08/22
Example on using interrupts with DS3231 alarms.
Hardware setup:
Connect DS3231 SQW pin to Arduino interrupt pin 2
Tested on: - Arduino UNO - Arduino nano
Added to this example:
1. Descriptively named variables to pass parameter values.
2. Modify AlarmBits for Alarm 1 to 0b00001111,
for clarity, because Alarm 1 uses only bits 3:0.
3. Add code to prevent Alarm 2 from interfering with the interrupt,
by setting A2Minute to a value that can never match the time
and setting AlarmBits to 0b01100000: alarm "when minutes match".
Also clear the A2 alarm flag. David Sparks, September 2022
********************************************************/
#include <DS3231.h>
#include <Wire.h>
//************************* DEFINES ************************************
#define CLINT 2 // myRTC interrupt pin
#define BAUD 9600
//************************* PROTOTYPES ************************************
//************************* VARIABLES ************************************
DS3231 myRTC; // Setup clock
byte alarmDay, alarmHour, alarmMinute, alarmSecond, alarmBits;
bool alarmDayIsDay, alarmH12, alarmPM;
volatile byte tick = 1; // Interrupt signaling byte
/*F********************************************************************
*
**********************************************************************/
void
setup()
{
Wire.begin(); // BEGIN I2C COMMUNICATION
Serial.begin( 9600 ); // BEGIN SERIAL COMMUNICATION
while( !Serial );
Serial.println();
Serial.println( "Starting Serial");
alarmDay = 0; // ASSIGN PARAMETER VALUES FOR ALARM 1
alarmHour = 0;
alarmMinute = 0;
alarmSecond = 0;
alarmBits = 0b00001111; // ALARM 1 EVERY SECOND
alarmDayIsDay = false;
alarmH12 = false;
alarmPM = false;
myRTC.turnOffAlarm( 1 ); // SET ALARM 1 TO FIRE AT ONE-SECOND INTERVALS
myRTC.setA1Time( alarmDay, alarmHour, alarmMinute, alarmSecond
, alarmBits, alarmDayIsDay, alarmH12, alarmPM);
myRTC.turnOnAlarm( 1 ); // ENABLE ALARM 1 INTERRUPTS
myRTC.checkIfAlarm( 1 ); // CLEAR ALARM 1 FLAG
// WHEN USING INTERRUPT WITH ONLY ONE OF THE DS3231 ALARMS, AS IN THIS EXAMPLE,
// IT MAY BE ADVISABLE TO PREVENT THE OTHER ALARM ENTIRELY, SO IT WILL
// NOT COVERTLY BLOCK THE OUTGOING INTERRUPT SIGNAL. PREVENT ALARM 2
// ALTOGETHER BY ASSIGNING A NONSENSICAL ALARM MINUTE VALUE THAT CANNOT
// MATCH CLOCK TIME, AND AN alarmBits VALUE TO ACTIVATE
// "when minutes match".
alarmMinute = 0xFF; // A VALUE THAT WILL NEVER MATCH TIME
alarmBits = 0b01100000; // ALARM 2 WHEN MINUTES MATCH, I.E., NEVER
// UPLOAD PARAMETERS TO PREVENT ALARM 2 ENTIRELY
myRTC.setA2Time( alarmDay, alarmHour, alarmMinute, alarmBits
, alarmDayIsDay, alarmH12, alarmPM );
myRTC.turnOffAlarm( 2 ); // DISABLE ALARM 2 INTERRUPT
myRTC.checkIfAlarm( 2 ); // CLEAR ALARM 2 FLAG
// NOTE: BOTH ALARM FLAGS MUST BE CLEAR TO ENABLE OUTPUT OF A FALLING
// INTERRUPT ATTACH CLOCK INTERRUPT
pinMode( CLINT, INPUT_PULLUP );
attachInterrupt( digitalPinToInterrupt( CLINT ), isr_TickTock, FALLING);
pinMode( LED_BUILTIN, OUTPUT ); // USE BUILTIN LED TO BLINK
}
/*F********************************************************************
*
**********************************************************************/
void
loop()
{
static byte state = false; // KEEP TRACK OF LED ON/OFF STATE
if( tick ) // IF ALARM WENT OF, DO ALARM STUFF
{
tick = 0;
state = ~state;
digitalWrite( LED_BUILTIN, state);
Serial.print( "Turning LED "); // OPTIONAL SERIAL OUTPUT
Serial.println( (state ? "ON" : "OFF"));
myRTC.checkIfAlarm( 1 ); // CLEAR ALARM 1 FLAG
}
delay( 10 ); // LOOP DELAY TO EMULATE OTHER RUNNING CODE
}
/*F********************************************************************
*
**********************************************************************/
void
isr_TickTock()
{
tick = 1; // INTERRUPT SIGNALS TO LOOP
return;
}