├── DS3231-RTClib-Adafruit-Alarm-Poll-SQW └── DS3231-RTClib-Adafruit-Alarm-Poll-SQW.ino ├── DS3231-RTClib-Adafruit-Alarm-Poll-alarmFired └── DS3231-RTClib-Adafruit-Alarm-Poll-alarmFired.ino ├── DS3231-_RTClib-Adafruit-Alarm-SetTest └── DS3231-_RTClib-Adafruit-Alarm-SetTest.ino ├── DS3231-_RTClib-Adafruit-Alarm-Sleep └── DS3231-_RTClib-Adafruit-Alarm-Sleep.ino └── README.md /DS3231-RTClib-Adafruit-Alarm-Poll-SQW/DS3231-RTClib-Adafruit-Alarm-Poll-SQW.ino: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Using the alarm on a DS3231 with the Adafruit RTClib library and SQW pin 4 | =========================================================================== 5 | 6 | Set an alarm on the DS3231 RTC module and monitor its status using the SQW 7 | to pin. Example sets alarm to trigger in 10 seconds after boot and then 8 | resets to a further 10 seconds after each trigger. 9 | 10 | Tested on a Arduino Nano. 3 July 2020. 11 | 12 | This example: https://github.com/garrysblog https://garrysblog.com/ 13 | Library: https://github.com/adafruit/RTClib 14 | RTClib command info: https://adafruit.github.io/RTClib/html/class_r_t_c___d_s3231.html 15 | 16 | Connections 17 | ----------- 18 | SDA -> Arduino Analog (SDA pin) 19 | SCL -> Arduino Analog (SCL pin) 20 | VCC -> Arduino 5V 21 | GND -> Arduino GND 22 | SQW -> Arduino D4 23 | */ 24 | 25 | #include "RTClib.h" 26 | RTC_DS3231 rtc; 27 | 28 | const int alarmPin = 4; // The number of the pin for monitor alarm status on DS3231 29 | 30 | void setup () { 31 | Serial.begin(9600); // Start serial port for monitoring 32 | 33 | pinMode(alarmPin, INPUT_PULLUP); // Set alarm pin as pullup 34 | 35 | if (! rtc.begin()) { 36 | Serial.println("Couldn't find RTC"); 37 | Serial.flush(); 38 | abort(); 39 | } 40 | 41 | // If required set to to compile time 42 | //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 43 | // Or to an explicit date & time, e.g. July 3, 2020 at 8pm 44 | //rtc.adjust(DateTime(2020, 7, 3, 20, 0, 0)); 45 | 46 | // Disable and clear both alarms 47 | rtc.disableAlarm(1); 48 | rtc.disableAlarm(2); 49 | rtc.clearAlarm(1); 50 | rtc.clearAlarm(2); 51 | 52 | rtc.writeSqwPinMode(DS3231_OFF); // Place SQW pin into alarm interrupt mode 53 | 54 | DateTime now = rtc.now(); // Get current time 55 | 56 | // Print current time and date 57 | char buff[] = "Start time is hh:mm:ss DDD, DD MMM YYYY"; 58 | Serial.println(now.toString(buff)); 59 | 60 | // Set alarm time 61 | rtc.setAlarm1(now + TimeSpan(0, 0, 0, 10), DS3231_A1_Second); // In 10 seconds time 62 | //rtc.setAlarm1(DateTime(2020, 6, 25, 15, 0, 0), DS3231_A1_Hour); // Or can be set explicity 63 | } 64 | 65 | void loop () { 66 | 67 | // Check if SQW pin shows alarm has fired 68 | if (digitalRead(alarmPin) == LOW) { 69 | // The alarm has just fired 70 | 71 | DateTime now = rtc.now(); // Get the current time 72 | char buff[] = "Alarm triggered at hh:mm:ss DDD, DD MMM YYYY"; 73 | Serial.println(now.toString(buff)); 74 | 75 | // Disable and clear alarm 76 | rtc.disableAlarm(1); 77 | rtc.clearAlarm(1); 78 | 79 | // Perhaps reset to new time if required 80 | rtc.setAlarm1(now + TimeSpan(0, 0, 0, 10), DS3231_A1_Second); // Set for another 10 seconds 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /DS3231-RTClib-Adafruit-Alarm-Poll-alarmFired/DS3231-RTClib-Adafruit-Alarm-Poll-alarmFired.ino: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Using the alarm on a DS3231 with the Adafruit RTClib library 4 | =========================================================================== 5 | 6 | Set an alarm on the DS3231 RTC module and monitor its status using the 7 | alarmFired funtion. This does not require monitoring the SQW pin and requies 8 | polling and may not be the best method of using the alarm. 9 | 10 | Example sets alarm to trigger in 10 seconds after boot and then 11 | resets to a further 10 seconds after each trigger. 12 | 13 | Tested on a Arduino Nano. 3 July 2020. 14 | 15 | This example: https://github.com/garrysblog https://garrysblog.com/ 16 | Library: https://github.com/adafruit/RTClib 17 | RTClib command info: https://adafruit.github.io/RTClib/html/class_r_t_c___d_s3231.html 18 | 19 | Connections 20 | ----------- 21 | SDA -> Arduino Analog (SDA pin) 22 | SCL -> Arduino Analog (SCL pin) 23 | VCC -> Arduino 5V 24 | GND -> Arduino GND 25 | */ 26 | 27 | #include "RTClib.h" 28 | RTC_DS3231 rtc; 29 | 30 | void setup () { 31 | Serial.begin(9600); // Start serial port for monitoring 32 | 33 | if (! rtc.begin()) { 34 | Serial.println("Couldn't find RTC"); 35 | Serial.flush(); 36 | abort(); 37 | } 38 | 39 | // If required set time 40 | //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // To compiled time 41 | //rtc.adjust(DateTime(2020, 7, 3, 20, 0, 0)); // Or explicitly, e.g. July 3, 2020 at 8pm 42 | 43 | // Disable and clear both alarms 44 | rtc.disableAlarm(1); 45 | rtc.disableAlarm(2); 46 | rtc.clearAlarm(1); 47 | rtc.clearAlarm(2); 48 | 49 | DateTime now = rtc.now(); // Get current time 50 | 51 | // Print current time and date 52 | char buff[] = "Start time is hh:mm:ss DDD, DD MMM YYYY"; 53 | Serial.println(now.toString(buff)); 54 | 55 | // Set alarm time 56 | rtc.setAlarm1(now + TimeSpan(0, 0, 0, 10), DS3231_A1_Second); // In 10 seconds time 57 | //rtc.setAlarm1(DateTime(2020, 6, 25, 15, 0, 0), DS3231_A1_Hour); // Or can be set explicity 58 | } 59 | 60 | void loop () { 61 | 62 | // Check if alarm by polling by using alarmFired 63 | if (rtc.alarmFired(1) == true){ 64 | 65 | // Print current time and date 66 | DateTime now = rtc.now(); // Get the current time 67 | char buff[] = "Alarm triggered at hh:mm:ss DDD, DD MMM YYYY"; 68 | Serial.println(now.toString(buff)); 69 | 70 | // Disable and clear alarm 71 | //rtc.disableAlarm(1); // Not used as only disables the alarm on the SQW pin 72 | rtc.clearAlarm(1); 73 | 74 | // Perhaps reset to new time if required 75 | rtc.setAlarm1(now + TimeSpan(0, 0, 0, 10), DS3231_A1_Second); // Set for another 10 seconds 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /DS3231-_RTClib-Adafruit-Alarm-SetTest/DS3231-_RTClib-Adafruit-Alarm-SetTest.ino: -------------------------------------------------------------------------------- 1 | /* Example implementation of an alarm using DS3231 2 | * Based on the example DS3231_alarm at 3 | * https://github.com/adafruit/RTClib/tree/master/examples/DS3231_alarm 4 | * 5 | * VCC and GND of RTC should be connected to some power source 6 | * SDA, SCL of RTC should be connected to SDA, SCL of arduino 7 | * SQW should be connected to CLOCK_INTERRUPT_PIN 8 | * CLOCK_INTERRUPT_PIN needs to work with interrupts 9 | */ 10 | 11 | #include 12 | // #include 13 | 14 | RTC_DS3231 rtc; 15 | 16 | // the pin that is connected to SQW 17 | #define CLOCK_INTERRUPT_PIN 2 18 | 19 | static bool firedStatus = false; 20 | 21 | void setup() { 22 | Serial.begin(9600); 23 | 24 | // initializing the rtc 25 | if(!rtc.begin()) { 26 | Serial.println("Couldn't find RTC!"); 27 | Serial.flush(); 28 | while (1) delay(10); 29 | } 30 | 31 | if(rtc.lostPower()) { 32 | // this will adjust to the date and time at compilation 33 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 34 | } 35 | 36 | //we don't need the 32K Pin, so disable it 37 | rtc.disable32K(); 38 | 39 | // Making it so, that the alarm will trigger an interrupt 40 | pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP); 41 | attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING); 42 | 43 | // set alarm 1, 2 flag to false (so alarm 1, 2 didn't happen so far) 44 | // if not done, this easily leads to problems, as both register aren't reset on reboot/recompile 45 | rtc.clearAlarm(1); 46 | rtc.clearAlarm(2); 47 | 48 | // stop oscillating signals at SQW Pin 49 | // otherwise setAlarm1 will fail 50 | rtc.writeSqwPinMode(DS3231_OFF); 51 | 52 | // turn off alarm 2 (in case it isn't off already) 53 | // again, this isn't done at reboot, so a previously set alarm could easily go overlooked 54 | rtc.disableAlarm(2); 55 | 56 | // schedule an alarm 57 | if(!rtc.setAlarm1( 58 | // Time relative to now 59 | //rtc.now() + TimeSpan(10), DS3231_A1_Second // this mode triggers the alarm when the seconds match. See Doxygen for other options 60 | rtc.now() + TimeSpan(0, 0, 1, 0), DS3231_A1_Minute // In 1 minutes time from now 61 | //rtc.now() + TimeSpan(0, 0, 2, 10), DS3231_A1_Minute // In 2 minutes and 10 seconds time from now 62 | //rtc.now() + TimeSpan(0, 1, 1, 0), DS3231_A1_Hour // In 1 hour and 1 minutes time from now 63 | 64 | // At explicit times 65 | //DateTime(0, 0, 0, 0, 0, 0), DS3231_A1_Second // When seconds at zero, that is every minute 66 | //DateTime(0, 0, 0, 0, 0, 0), DS3231_A1_Minute // When the minutes and seconds are at zero, that is, every hour 67 | //DateTime(0, 0, 0, 0, 1, 10), DS3231_A1_Minute // When the minutes are at 1 and seconds are at 10, that is 1 minute and 10 seconds past the hour 68 | //DateTime(0, 0, 0, 10, 0, 0), DS3231_A1_Hour // At 10:00 o'clock every day 69 | //DateTime(0, 0, 0, 10, 18, 0), DS3231_A1_Hour // At 10:18 every day 70 | )) { 71 | Serial.println("Error, alarm wasn't set!"); 72 | }else { 73 | Serial.print("Current time: "); 74 | char date[] = "DDD, DD MMM YYYY hh:mm:ss"; 75 | rtc.now().toString(date); 76 | Serial.println(date); 77 | } 78 | } 79 | 80 | void loop() { 81 | 82 | if (firedStatus == true) { 83 | // Print time alarm occured 84 | Serial.print("Alarm occured! "); 85 | char date[10] = "hh:mm:ss"; 86 | rtc.now().toString(date); 87 | Serial.println(date); 88 | 89 | // Reset alarm status flag 90 | firedStatus = false; 91 | 92 | // Clear alarm 93 | rtc.clearAlarm(1); 94 | Serial.println("Alarm cleared"); 95 | } 96 | } 97 | 98 | void onAlarm() { 99 | // Set status flag 100 | firedStatus = true; 101 | } 102 | -------------------------------------------------------------------------------- /DS3231-_RTClib-Adafruit-Alarm-Sleep/DS3231-_RTClib-Adafruit-Alarm-Sleep.ino: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Wake up from sleep example using DS3231 and Adafruit RTClib library 4 | =========================================================================== 5 | 6 | Use the DS3231 RTC module to wake an µController from sleep using the output 7 | from the SQW pin to trigger an interrupt driven wakeup. 8 | 9 | In this example the µController goes to sleep after 10 seconds, sleeps for 10 10 | seconds (set using alarm), wakes and repeats. 11 | 12 | Tested on a Arduino Nano. 3 July 2020. 13 | 14 | This example: https://github.com/garrysblog https://garrysblog.com/ 15 | Library: https://github.com/adafruit/RTClib 16 | RTClib command info: https://adafruit.github.io/RTClib/html/class_r_t_c___d_s3231.html 17 | 18 | Connections 19 | ----------- 20 | SDA -> Arduino Analog (SDA pin) 21 | SCL -> Arduino Analog (SCL pin) 22 | VCC -> Arduino 5V 23 | GND -> Arduino GND 24 | SQW -> Arduino D2 (Needs to be an interrupt capable pin) 25 | */ 26 | 27 | #include "RTClib.h" // DS3231 library 28 | #include // AVR library for controlling the sleep modes 29 | 30 | const int alarmPin = 2; // The number of the pin for monitoring alarm status on DS3231 31 | 32 | RTC_DS3231 rtc; 33 | 34 | void setup () { 35 | Serial.begin(9600); // Start serial port for monitoring 36 | 37 | pinMode(alarmPin, INPUT_PULLUP); // Set alarm pin as pullup 38 | 39 | if (! rtc.begin()) { 40 | Serial.println("Couldn't find RTC"); 41 | Serial.flush(); 42 | abort(); 43 | } 44 | 45 | // If required set time 46 | //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // To compiled time 47 | //rtc.adjust(DateTime(2020, 7, 3, 20, 0, 0)); // Or explicitly, e.g. July 3, 2020 at 8pm 48 | 49 | // Disable and clear both alarms 50 | rtc.disableAlarm(1); 51 | rtc.disableAlarm(2); 52 | rtc.clearAlarm(1); 53 | rtc.clearAlarm(2); 54 | 55 | rtc.writeSqwPinMode(DS3231_OFF); // Place SQW pin into alarm interrupt mode 56 | 57 | Serial.println("Starting"); 58 | } 59 | 60 | void loop () { 61 | 62 | delay(10000); // Wait 10 seconds before going to sleep 63 | 64 | // Get current time and set alarm to a time to wake 65 | DateTime now = rtc.now(); // Get current time 66 | rtc.setAlarm1(now + TimeSpan(0, 0, 0, 10), DS3231_A1_Second); // In 10 seconds 67 | //rtc.setAlarm1(DateTime(2020, 6, 25, 15, 0, 0), DS3231_A1_Hour); // Or can be set explicity 68 | 69 | enterSleep(); // Go to sleep 70 | } 71 | 72 | void enterSleep(){ 73 | sleep_enable(); // Enabling sleep mode 74 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Setting the sleep mode, in this case full sleep 75 | 76 | noInterrupts(); // Disable interrupts 77 | attachInterrupt(digitalPinToInterrupt(alarmPin), alarm_ISR, LOW); 78 | 79 | Serial.println("Going to sleep!"); // Print message to serial monitor 80 | Serial.flush(); // Ensure all characters are sent to the serial monitor 81 | 82 | interrupts(); // Allow interrupts again 83 | sleep_cpu(); // Enter sleep mode 84 | 85 | /* The program will continue from here when it wakes */ 86 | 87 | // Disable and clear alarm 88 | rtc.disableAlarm(1); 89 | rtc.clearAlarm(1); 90 | 91 | Serial.println("I'm back!"); // Print message to show we're back 92 | } 93 | 94 | 95 | void alarm_ISR() { 96 | // This runs when SQW pin is low. It will wake up the µController 97 | 98 | sleep_disable(); // Disable sleep mode 99 | detachInterrupt(digitalPinToInterrupt(alarmPin)); // Detach the interrupt to stop it firing 100 | } 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Using the DS3231 alarm with the Adafruit RTClib library 2 | 3 | The DS3231 Real Time Clock module includes two alarms. Support for these was added to the Adafruit RTClib. The examples here cover using the alarm. 4 | 5 | - Setting an alarm and polling the SQW pin to monitor its status (DS3231-RTClib-Adafruit-Alarm-Poll-SQW.ino) 6 | - Setting an alarm and polling using alarmFired (DS3231-RTClib-Adafruit-Alarm-Poll-alarmFired.ino) 7 | - Sending the Arduino to sleep and waking it using the alarm and SQW pin (DS3231-_RTClib-Adafruit-Alarm-Sleep.ino) 8 | 9 | More details are available on my blog https://garrysblog.com/2020/07/05/using-the-ds3231-real-time-clock-alarm-with-the-adafruit-rtclib-library/ 10 | 11 | ## Setting the alarm 12 | **setAlarm1(DateTime, alarm_mode)** 13 | 14 | **setAlarm2(DateTime, alarm_mode)** 15 | 16 | ## Alarm modes 17 | ### For alarm 1 18 | - DS3231_A1_PerSecond Once per second 19 | - DS3231_A1_Second When seconds match 20 | - DS3231_A1_Minute When minutes and seconds match 21 | - DS3231_A1_Hour When hours, minutes, and seconds match 22 | - DS3231_A1_Date When date, hours, minutes, and seconds match (day of month) 23 | - DS3231_A1_Day When day, hours, minutes, and seconds match (day of week) 24 | 25 | ### For alarm 2 26 | - DS3231_A2_PerMinute Once per minute (00 seconds of every minute) 27 | - DS3231_A2_Minute When minutes and seconds match 28 | - DS3231_A2_Hour When hours, minutes, and seconds match 29 | - DS3231_A2_Date When date, hours, minutes, and seconds match 30 | - DS3231_A2_Day When day, hours, minutes, and seconds match 31 | 32 | ## Examples 33 | ### Set to an explicit time 34 | In this example the alarm will trigger when seconds, minutes and hours match, resulting in triggering once per day, every day at (15:34:00). The date, month and year are all ignored. 35 | 36 | **setAlarm1(DateTime(2020, 6, 25, 15, 34, 0), DS3231_A1_Hour)** 37 | 38 | ### Using TimeSpan or unixtime to set to an amount from the current time 39 | The current time needs to be called before setting the remaining examples as it is needed to calculate the end time. These examples set the alarm to 10 seconds from the current time. 40 | 41 | **setAlarm1(now + TimeSpan(0, 0, 0, 10), DS3231_A1_Second)** 42 | 43 | **setAlarm1(now.unixtime() + 10, DS3231_A1_Second)** 44 | --------------------------------------------------------------------------------