Hi -
Thanks for your excellent solution. I am responding to this post because I finally learned how to correctly handle interrupts on the DS3231, and likely other devices. I am writing this to answer the original question and to also serve as a very brief, and hopefully clear to read, tutorial. The code example below is based using Alarm 1 on a DS3231.
1) Create a variable that will indicate the interrupt occurred
volatile boolean clockInterrupt = false; //This will be set TRUE when there is an interrupt
2) Instruct the Arduino what subroutine to invoke if the interrupt is detected.
// Interrupt #1 is Pin 3 on the UNO. you can also use Interrupt #0 and Pin 2
// clockTrigger is the subroutine that will be called when the Interrupt occurs
attachInterrupt(1, clockTrigger, FALLING);
3)Set up the interrupt subroutine. Keep this as short as possible. Ideally it should have nothing more than the statement to set flag that says the interrupt occurred
void clockTrigger() {
clockInterrupt = true; //don't do any other processing in this subroutine
}
4) In the loop routine set if an IF statement to detect if the interrupt flag is set
void loop() {
....
if(clockInterrupt){
.... //Put the code you want to execute when the interrupt occurs
//such as turn on a light or display a message
clearClockTrigger(); //Finally after the code you want to execute because of the
// interrupt completes, call a subroutine to clear the interrupt flag
// so if there is another interrupt, the interrupt code will run again.
}
....
}
5) Clearing the alarm flag. This step is very poorly documented in many examples on the web. Before you can write to and clear the alarm flag you have to read the flag first!
In following example:
- the address of the DS3231 is 0x68
- Bit 0 (the least significant bit) in status register 0F needs to be set to zero to reset the
alarm bit.
void clearClockTrigger()
{
Wire.beginTransmission(0x68); //Tell devices on the bus we are talking to the DS3231
Wire.write(0x0F); //Tell the device which address we want to read or write
Wire.endTransmission();
Wire.requestFrom(0x68,1); // Read one byte
dummyRegister=Wire.read(); // In this example we are not interest in actually using the bye
Wire.beginTransmission(0x68); //Tell devices on the bus we are talking to the DS3231
Wire.write(0x0F); //Tell the device which address we want to read or write
Wire.write(0b00000000); //Write the byte. The last 0 bit resets Alarm 1
Wire.endTransmission();
clockInterrupt=false; //Finally clear the flag we use to indicate the trigger occurred
}
Hope this helps