First Commit
This commit is contained in:
167
libraries/DS3231/examples/AdvanceAlarm/AdvanceAlarm.ino
Normal file
167
libraries/DS3231/examples/AdvanceAlarm/AdvanceAlarm.ino
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
AdvanceAlarm.ino
|
||||
David Sparks Sept 2022
|
||||
|
||||
Example of advancing an alarm by an arbitrary interval of time.
|
||||
|
||||
Hardware setup:
|
||||
Connect DS3231 SQW pin to Arduino interrupt pin 2
|
||||
|
||||
Builds upon ArduinoInterrupt.ino example by
|
||||
Jacob Nuernberg August 2022
|
||||
|
||||
Example on using recurring interrupts
|
||||
of arbitrary frequency with DS3231 alarms.
|
||||
|
||||
Hardware setup:
|
||||
Connect DS3231 SQW pin to Arduino interrupt pin 2
|
||||
|
||||
Tested on:
|
||||
- Arduino Nano (ATmega328P)
|
||||
|
||||
*/
|
||||
|
||||
#include <DS3231.h>
|
||||
#include <Wire.h>
|
||||
|
||||
// Interrupt frequency, in seconds
|
||||
#define INT_FREQ 3UL // 3 seconds, characterized as unsigned long
|
||||
|
||||
// myRTC interrupt pin
|
||||
#define CLINT 2
|
||||
|
||||
// Setup clock
|
||||
DS3231 myRTC;
|
||||
|
||||
// Variables for use in method parameter lists
|
||||
byte alarmDay;
|
||||
byte alarmHour;
|
||||
byte alarmMinute;
|
||||
byte alarmSecond;
|
||||
byte alarmBits;
|
||||
bool alarmDayIsDay;
|
||||
bool alarmH12;
|
||||
bool alarmPM;
|
||||
|
||||
// Interrupt signaling byte
|
||||
volatile byte tick = 1;
|
||||
|
||||
|
||||
void setup() {
|
||||
// Begin I2C communication
|
||||
Wire.begin();
|
||||
|
||||
// Begin Serial communication
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
// Set the DS3231 clock mode to 24-hour
|
||||
myRTC.setClockMode(false); // false = not using the alternate, 12-hour mode
|
||||
|
||||
// Set the clock to an arbitrarily chosen time of
|
||||
// 00:00:00 midnight the morning of January 1, 2020
|
||||
// using a suitable Unix-style timestamp
|
||||
myRTC.setEpoch(1640995200);
|
||||
|
||||
// Assign parameter values for Alarm 1
|
||||
alarmDay = myRTC.getDate();
|
||||
alarmHour = myRTC.getHour(alarmH12, alarmPM);
|
||||
alarmMinute = myRTC.getMinute();
|
||||
alarmSecond = INT_FREQ; // initialize to the interval length
|
||||
alarmBits = 0b00001110; // Alarm 1 when seconds match
|
||||
alarmDayIsDay = false; // using date of month
|
||||
|
||||
// Upload initial parameters of Alarm 1
|
||||
myRTC.turnOffAlarm(1);
|
||||
myRTC.setA1Time(
|
||||
alarmDay, alarmHour, alarmMinute, alarmSecond,
|
||||
alarmBits, alarmDayIsDay, alarmH12, alarmPM);
|
||||
// clear Alarm 1 flag after setting the alarm time
|
||||
myRTC.checkIfAlarm(1);
|
||||
// now it is safe to enable interrupt output
|
||||
myRTC.turnOnAlarm(1);
|
||||
|
||||
// When using interrupt with only one of the DS3231 alarms, as in this example,
|
||||
// it may be possible to prevent the other alarm entirely,
|
||||
// so it will not covertly block the outgoing interrupt signal.
|
||||
|
||||
// Try to prevent Alarm 2 altogether by assigning a
|
||||
// nonsensical alarm minute value that cannot match the clock time,
|
||||
// and an alarmBits value to activate "when minutes match".
|
||||
alarmMinute = 0xFF; // a value that will never match the time
|
||||
alarmBits = 0b01100000; // Alarm 2 when minutes match, i.e., never
|
||||
|
||||
// Upload the parameters to prevent Alarm 2 entirely
|
||||
myRTC.setA2Time(
|
||||
alarmDay, alarmHour, alarmMinute,
|
||||
alarmBits, alarmDayIsDay, alarmH12, alarmPM);
|
||||
// disable Alarm 2 interrupt
|
||||
myRTC.turnOffAlarm(2);
|
||||
// clear Alarm 2 flag
|
||||
myRTC.checkIfAlarm(2);
|
||||
|
||||
// NOTE: both of the 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);
|
||||
|
||||
// Configure the LED for blinking
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// static variable to keep track of LED on/off state
|
||||
static byte state = false;
|
||||
|
||||
// Do when alarm interrupt received:
|
||||
if (tick) {
|
||||
// right away, capture the current time in a DateTime variable
|
||||
// for later processing
|
||||
DateTime alarmDT = RTClib::now();
|
||||
|
||||
// disable Alarm 1 interrupt
|
||||
myRTC.turnOffAlarm(1);
|
||||
|
||||
// Clear Alarm 1 flag
|
||||
myRTC.checkIfAlarm(1);
|
||||
|
||||
tick = 0; // reset the local interrupt-received flag
|
||||
state = ~state; // reverse the state of the LED
|
||||
digitalWrite(LED_BUILTIN, state);
|
||||
|
||||
// optional serial output
|
||||
Serial.print("Turning LED ");
|
||||
Serial.print((state ? "ON" : "OFF"));
|
||||
Serial.print(" at ");
|
||||
Serial.print(alarmDT.hour());
|
||||
Serial.print(":");
|
||||
Serial.print(alarmDT.minute());
|
||||
Serial.print(":");
|
||||
Serial.println(alarmDT.second());
|
||||
|
||||
// extract the DateTime values as a timestamp
|
||||
uint32_t nextAlarm = alarmDT.unixtime();
|
||||
// add the INT_FREQ number of seconds
|
||||
nextAlarm += INT_FREQ;
|
||||
// update the DateTime with the new timestamp
|
||||
alarmDT = DateTime(nextAlarm);
|
||||
|
||||
// upload the new time to Alarm 1
|
||||
myRTC.setA1Time(
|
||||
alarmDT.day(), alarmDT.hour(), alarmDT.minute(), alarmDT.second(),
|
||||
alarmBits, alarmDayIsDay, alarmH12, alarmPM);
|
||||
|
||||
// enable Alarm 1 interrupts
|
||||
myRTC.turnOnAlarm(1);
|
||||
// clear Alarm 1 flag again after enabling interrupts
|
||||
myRTC.checkIfAlarm(1);
|
||||
}
|
||||
}
|
||||
|
||||
void isr_TickTock() {
|
||||
// interrupt signals to loop
|
||||
tick = 1;
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user