{"id":165166,"date":"2025-03-31T17:37:45","date_gmt":"2025-03-31T17:37:45","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=165166"},"modified":"2025-04-28T09:54:51","modified_gmt":"2025-04-28T09:54:51","slug":"esp8266-nodemcu-ds3231-real-time-clock-arduino","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-ds3231-real-time-clock-arduino\/","title":{"rendered":"ESP8266 NodeMCU: DS3231 Real Time Clock Module (RTC) \u2014 Getting Time and Setting Alarms"},"content":{"rendered":"\n<p>Learn how to interface the DS3231 Real Time Clock Module with the ESP8266 to get time and set alarms. The DS3231 RTC module is a great module for accurate timekeeping, it allows you to set alarms, output square waves with different frequencies, and also get temperature readings.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Arduino-IDE.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU with DS3231 Real Time Clock Module (RTC) \u2014 Getting Time and Setting Alarms\" class=\"wp-image-165170\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Arduino-IDE.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Arduino-IDE.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Arduino-IDE.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Arduino-IDE.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Arduino-IDE.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgreen\">Using a DS1307 RTC Module? Follow this tutorial instead: <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-ds1307-real-time-clock-rtc-arduino\/\">ESP8266 NodeMCU: Guide for DS1307 Real Time Clock Module (RTC)<\/a>.<\/p>\n\n\n\n<p><strong>Table of Contents<\/strong><\/p>\n\n\n\n<p>In this tutorial, we&#8217;ll cover the following topics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#intro-rtc\" title=\"\">Introducing Real-Time Clock (RTC) Modules<\/a><\/li>\n\n\n\n<li><a href=\"#intro-ds3231\" title=\"\">Introducing the DS3231 RTC Module<\/a><\/li>\n\n\n\n<li><a href=\"#ds3231-esp8266-wiring\" title=\"\">Connecting the DS3231 RTC Module to the ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"#rtclib\" title=\"\">Installing the RTCLib Library<\/a><\/li>\n\n\n\n<li><a href=\"#set-read-time\" title=\"\">ESP8266 with DS3231: Setting and Reading the Time<\/a><\/li>\n\n\n\n<li><a href=\"#setting-alarms\" title=\"\">ESP32 with DS3231: Setting Alarms<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"intro-rtc\">Introducing Real-Time Clock (RTC) Modules<\/h2>\n\n\n\n<p>RTC modules, such as the DS3231 and DS1307, have a tiny clock inside to keep track of time independently without being connected to a microcontroller. They come with a battery holder to connect a battery, so they keep working even if the ESP8266 resets or loses power.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC3231-DS1307-RTC-Modules.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"RTC DS3231 and RTC DS1307 Modules\" class=\"wp-image-164850\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC3231-DS1307-RTC-Modules.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC3231-DS1307-RTC-Modules.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The DS3231 and the DS1307 are some of the most popular choices to use with microcontrollers. Both are compatible with ESP8266 boards and communicate via I2C communication protocol. The DS3231 is more accurate because it gives temperature-compensated results. Additionally, it&#8217;s also possible to set external alarms with the DS3231, which can be extremely useful in automation and datalogging projects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"intro-ds3231\">Introducing the DS3231 RTC Module<\/h2>\n\n\n\n<p>The following picture shows the DS3231 RTC Module. It uses a 32kHz temperature-compensated crystal oscillator (TCXO) to keep track of time in a precise way (it&#8217;s resistant to temperature changes). Because of that, it also allows you to get temperature data.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-Module.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"RTC DS3231 Module\" class=\"wp-image-164851\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-Module.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-Module.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Besides keeping track of the date and time precisely, it also has built-in memory for storing up to two alarms and can output square waves at different frequencies: 1Hz, 4kHz, 8kHz, and 32kHz.<\/p>\n\n\n\n<p>You communicate with the RTC module using I2C communication protocol. Usually, it&#8217;s on address 0x68.  <\/p>\n\n\n\n<p>This module also comes with a 24C32 32-byte EEPROM that you can use to store any non-volatile data that you want. You can communicate with this EEPROM memory via I2C by addressing the right address (0x57).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">DS3231 Battery Holder<\/h3>\n\n\n\n<p>The DS3231 comes with a battery holder to connect a battery to keep accurate timekeeping. In the event of a power outage, it can still keep track of time accurately and keep all the alarms.<\/p>\n\n\n\n<p>You <strong>should use a LIR2032 battery, which is rechargeable<\/strong>. Don&#8217;t use a CR2032&nbsp;(not rechargeable). <\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-Module-back.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"RTC DS3231 Battery Holder\" class=\"wp-image-164852\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-Module-back.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-Module-back.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS3231-Battery-Holder.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"DS3231 RTC Module with Battery Back-up\" class=\"wp-image-164853\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS3231-Battery-Holder.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS3231-Battery-Holder.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<p>If you want to use a CR2032 battery, which is non-rechargeable, you must disconnect the battery charging circuit by unsoldering and removing the resistor (labeled R4 in my module) next to the diode.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-remove-resistor-for-nor-rechargeable-battery.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"RTC DS3231 Remove Resistor for non re-chargeable battery\" class=\"wp-image-164864\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-remove-resistor-for-nor-rechargeable-battery.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/RTC-DS32321-remove-resistor-for-nor-rechargeable-battery.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">DS3231 Alarms<\/h3>\n\n\n\n<p>The DS3231 can store up to two alarms: <strong>alarm 1<\/strong> and <strong>alarm 2<\/strong>. These alarms can be configured to trigger based on a specific time and\/or date. When an alarm is triggered, the SQW pin of the module outputs a LOW signal (it is an active low pin).<\/p>\n\n\n\n<p>You can detect this signal with the ESP8266 to trigger interrupts. Thus, this feature is extremely useful for setting a periodic deep sleep wake-up and other periodic tasks, time-based automation, and also one-time alerts (because you can clear an alarm after it&#8217;s triggered).<\/p>\n\n\n\n<p>Each alarm can be configured to be triggered in different modes. These modes allow you to create alarms that repeat every second, minute, hour, daily, weekly, or even once a month. Alarm1 and alarm2 are different.<\/p>\n\n\n\n<p>Alarm 1:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Every second<\/li>\n\n\n\n<li>When seconds, minutes, hours, day or date match<\/li>\n<\/ul>\n\n\n\n<p>Alarm 2:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Every minute<\/li>\n\n\n\n<li>When minutes, hours, day or date match<\/li>\n<\/ul>\n\n\n\n<p>We&#8217;ll see how to set alarms later in this tutorial.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">DS3231 RTC Module I2C Address<\/h3>\n\n\n\n<p>By default, the address of the DS3231 RTC is <strong>0x68<\/strong> and the EEPROM connected to the module is 0x57. You can run an <a href=\"https:\/\/randomnerdtutorials.com\/esp32-i2c-scanner-arduino\/\" title=\"\">I2C scanner sketch to double-check the addresses<\/a>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"666\" height=\"253\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ds3231-i2c-address.png?resize=666%2C253&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"DS3231 Get I2C Address\" class=\"wp-image-164830\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ds3231-i2c-address.png?w=666&amp;quality=100&amp;strip=all&amp;ssl=1 666w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ds3231-i2c-address.png?resize=300%2C114&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 666px) 100vw, 666px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">DS3231 RTC Module Pinout<\/h3>\n\n\n\n<p>The following table quickly describes the DS3231 RTC Module Pinout.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>32K<\/strong><\/td><td>32kHz oscillator output \u2014 can be used as a clock reference<\/td><\/tr><tr><td><strong>SQW<\/strong><\/td><td>Square wave\/Interrupt output<\/td><\/tr><tr><td><strong>SCL<\/strong><\/td><td>SCL pin for I2C<\/td><\/tr><tr><td><strong>SDA<\/strong><\/td><td>SDA pin for I2C<\/td><\/tr><tr><td><strong>VCC<\/strong><\/td><td>Provides power to the module (3.3V or 5V)<\/td><\/tr><tr><td><strong>GND<\/strong><\/td><td>GND<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"ds3231-esp8266-wiring\">Connecting the DS3231 RTC Module to the ESP8266<\/h1>\n\n\n\n<p>Here\u2019s a list of the parts required for this tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noopener\" title=\"\">ESP8266 Board<\/a> &#8211; read <a href=\"https:\/\/makeradvisor.com\/best-esp8266-wi-fi-development-board\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Best ESP8266 development boards<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/ds3231-rtc-module\/\" target=\"_blank\" rel=\"noopener\" title=\"\">DS3231 Module<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Jumper wires<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Breadboard<\/a><\/li>\n<\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<p>Wire the DS3231 to the ESP8266. You can use the following table as a reference or take a look at the schematic diagram. We&#8217;re using the I2C default pins.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>DS3231 RTC Module<\/strong><\/td><td><strong>ESP8266<\/strong><\/td><\/tr><tr><td>SQW<\/td><td><span class=\"rnthl rntclblue\">GPIO 14<\/span> (or any other digital pin)<\/td><\/tr><tr><td>SCL<\/td><td><span class=\"rnthl rntcyellow\">GPIO 5<\/span> (D1)<\/td><\/tr><tr><td>SDA<\/td><td><span class=\"rnthl rntclgray\">GPIO 4<\/span> (D2)<\/td><\/tr><tr><td>VCC<\/td><td><span class=\"rnthl rntcred\">3V3<\/span><\/td><\/tr><tr><td>GND<\/td><td><span class=\"rnthl rntcblack\">GND<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"993\" height=\"533\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/esp8266-ds3231_wiring.png?resize=993%2C533&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with DS3231 RTC Module Circuit Diagram\" class=\"wp-image-165118\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/esp8266-ds3231_wiring.png?w=993&amp;quality=100&amp;strip=all&amp;ssl=1 993w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/esp8266-ds3231_wiring.png?resize=300%2C161&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/esp8266-ds3231_wiring.png?resize=768%2C412&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 993px) 100vw, 993px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\">You may also like: <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pinout-reference-gpios\/\" title=\"\">ESP8266 Pinout Reference: Which GPIO pins should you use?<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"working-with-rtc\">Working with the RTC<\/h2>\n\n\n\n<p>Using an RTC module in your projects always requires two important steps.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Setting the current time<\/strong>: you can do it manually by inserting the current time (or a different desired time) on the code; the system&#8217;s local time; or get the time from an NTP server.<\/li>\n\n\n\n<li><strong>Retaining the time<\/strong>: to make sure the RTC keeps the correct time, even if it loses power, it needs to be connected to a battery. RTC modules come with a battery holder, usually for a coin cell.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"rtclib\">Installing the RTCLib Library<\/h2>\n\n\n\n<p>We\u2019ll program the ESP8266 NodeMCU using Arduino IDE. Make sure you have the ESP8266 boards installed by following this guide: <a href=\"https:\/\/randomnerdtutorials.com\/installing-esp8266-nodemcu-arduino-ide-2-0\/\">Installing ESP8266 Board in Arduino IDE 2 (Windows, Mac OS X, Linux)<\/a><\/p>\n\n\n\n<p>There are several libraries to interface with the DS3231 RTC module. We&#8217;ll use the <a href=\"https:\/\/github.com\/adafruit\/RTClib\" target=\"_blank\" rel=\"noopener\" title=\"\">RTCLib from Adafruit<\/a> that is compatible with DS1307, DS3231, and PCF8523 RTC modules. Additionally, this library is also compatible with ESP8266 boards.<\/p>\n\n\n\n<p>In the Arduino IDE, go to <strong>Sketch<\/strong> &gt; <strong>Include Library<\/strong> &gt; <strong>Manage Libraries<\/strong>. Search for <strong>RTCLib <\/strong>and install the library by Adafruit. We&#8217;re using version 2.1.4.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"391\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/11\/install-RTCLib.png?resize=750%2C391&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE install RTCLib Library\" class=\"wp-image-163965\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/11\/install-RTCLib.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/11\/install-RTCLib.png?resize=300%2C156&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"set-read-time\">ESP8266 NodeMCU with DS3231: Setting and Reading the Time<\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Module-Get-Time.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 with DS3231: Setting and Reading the Time\" class=\"wp-image-165172\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Module-Get-Time.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Module-Get-Time.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The following example sets the time on the RTC module, and then reads the time in the loop every three seconds. We also read the temperature. This code shows two different ways to set the time: synchronizing the RTC with the system time (the date and time the sketch was compiled) and setting a specific date and time manually by writing it yourself on the code.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete instructions at https:\/\/RandomNerdTutorials.com\/esp8266-nodemcu-ds3231-real-time-clock-arduino\/\n*********\/\n\/\/ Based on the RTCLib Library examples: github.com\/adafruit\/RTClib\n\/\/ Date and time functions using a DS1307 RTC connected via I2C and Wire lib\n#include &quot;RTClib.h&quot;\n\nRTC_DS3231 rtc;\n\nchar daysOfTheWeek[7][12] = {&quot;Sunday&quot;, &quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot;};\n\nvoid setup () {\n  Serial.begin(115200);\n\n  if (! rtc.begin()) {\n    Serial.println(&quot;Couldn't find RTC&quot;);\n    Serial.flush();\n    while (1) delay(10);\n  }\n\n  if (rtc.lostPower()) {\n    Serial.println(&quot;RTC lost power, let's set the time!&quot;);\n    \/\/ When time needs to be set on a new device, or after a power loss, the\n    \/\/ following line sets the RTC to the date &amp; time this sketch was compiled\n    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));\n    \/\/ This line sets the RTC with an explicit date &amp; time, for example to set\n    \/\/ January 21, 2014 at 3am you would call:\n    \/\/rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));\n  }\n\n  \/\/ When time needs to be re-set on a previously configured device, the\n  \/\/ following line sets the RTC to the date &amp; time this sketch was compiled\n  \/\/rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));\n  \/\/ This line sets the RTC with an explicit date &amp; time, for example to set\n  \/\/ January 21, 2014 at 3am you would call:\n  \/\/rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));\n}\n\nvoid loop () {\n  \/\/ Get the current time from the RTC\n  DateTime now = rtc.now();\n  \n  \/\/ Getting each time field in individual variables\n  \/\/ And adding a leading zero when needed;\n  String yearStr = String(now.year(), DEC);\n  String monthStr = (now.month() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.month(), DEC);\n  String dayStr = (now.day() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.day(), DEC);\n  String hourStr = (now.hour() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.hour(), DEC); \n  String minuteStr = (now.minute() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.minute(), DEC);\n  String secondStr = (now.second() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.second(), DEC);\n  String dayOfWeek = daysOfTheWeek[now.dayOfTheWeek()];\n\n  \/\/ Complete time string\n  String formattedTime = dayOfWeek + &quot;, &quot; + yearStr + &quot;-&quot; + monthStr + &quot;-&quot; + dayStr + &quot; &quot; + hourStr + &quot;:&quot; + minuteStr + &quot;:&quot; + secondStr;\n\n  \/\/ Print the complete formatted time\n  Serial.println(formattedTime);\n\n  \/\/ Getting temperature\n  Serial.print(rtc.getTemperature());\n  Serial.println(&quot;\u00baC&quot;);\n\n  Serial.println();\n  delay(3000);\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_DS3231_Set_Get_Time.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work<\/h3>\n\n\n\n<p>Start by importing the <span class=\"rnthl rntliteral\">RTCLib<\/span> library.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include \"RTClib.h\"<\/code><\/pre>\n\n\n\n<p>Then, create an <span class=\"rnthl rntliteral\">RTC_DS3231<\/span> object called <span class=\"rnthl rntliteral\">rtc<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>RTC_DS3231 rtc;<\/code><\/pre>\n\n\n\n<p>Then, you create a char array with the days of the week.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>char daysOfTheWeek&#091;7]&#091;12] = {\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"};<\/code><\/pre>\n\n\n\n<p>You can access each day by its index. For example:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">daysOfTheWeek[0]<\/span> will return &#8220;Sunday&#8221;.<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">daysOfTheWeek[1]<\/span> will return &#8220;Monday&#8221;.<\/li>\n<\/ul>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Initialize the RTC module as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (! rtc.begin()) {\n  Serial.println(\"Couldn't find RTC\");\n  Serial.flush();\n  while (1) delay(10);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Checking the RTC Status<\/h4>\n\n\n\n<p>Then, check if the RTC has lost power with the <span class=\"rnthl rntliteral\">lostPower()<\/span> function. If it is not running, because it is a new device, or because the battery backup failed, we&#8217;ll print a message in the Serial Monitor and set the time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (rtc.lostPower()) {\n  Serial.println(\"RTC lost power, let's set the time!\");<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Setting the Time<\/h4>\n\n\n\n<p>To set the time on the RTC, we can use the <span class=\"rnthl rntliteral\">adjust()<\/span> method on our <span class=\"rnthl rntliteral\">rtc<\/span> object. The following line sets the RTC\u2019s date and time to the current date and time when this sketch was last compiled.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));<\/code><\/pre>\n\n\n\n<p><span class=\"rnthl rntliteral\">__DATE__<\/span> and <span class=\"rnthl rntliteral\">__TIME__<\/span> are macros that provide the current date and time at compilation.<\/p>\n\n\n\n<p>Alternatively, you can set the date and time manually. Pass the time fields in this order: year, month, day, hour, minute, second. This line is commented on the code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ January 21, 2014 at 3am you would call:\nrtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));<\/code><\/pre>\n\n\n\n<p>If you need to re-set the time on a previously configured device, you can call one of the previous two lines to set the time without checking if it has lost power (this is commented on the code).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ When time needs to be re-set on a previously configured device, the\n\/\/ following line sets the RTC to the date &amp; time this sketch was compiled\n\/\/rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));\n\/\/ This line sets the RTC with an explicit date &amp; time, for example to set\n\/\/ January 21, 2014 at 3am you would call:\n\/\/rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Getting Date and Time<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, we get the date and time every three seconds, and we print it in the Serial Monitor.<\/p>\n\n\n\n<p>We call <span class=\"rnthl rntliteral\">rtc.now()<\/span> to get the current date and time from the RTC module.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>DateTime now = rtc.now();<\/code><\/pre>\n\n\n\n<p>It returns a <span class=\"rnthl rntliteral\">DateTime<\/span> object containing the values for the current year, month, day, hour, minute, and second.<\/p>\n\n\n\n<p>To access each field of the date and time, we can use the following methods:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><span class=\"rnthl rntliteral\">now.year()<\/span><\/td><td>Gets the current year (e.g., 2024)<\/td><\/tr><tr><td><span class=\"rnthl rntliteral\">now.month()<\/span><\/td><td>Gets the current month (1\u201312)<\/td><\/tr><tr><td><span class=\"rnthl rntliteral\">now.day()<\/span><\/td><td>Gets the current day of the month (1\u201331)<\/td><\/tr><tr><td><span class=\"rnthl rntliteral\">now.dayOfTheWeek()<\/span><\/td><td>Gets the day of the week (0-6), where 0 is Sunday, and 6 is Saturday<\/td><\/tr><tr><td><span class=\"rnthl rntliteral\">now.hour()<\/span><\/td><td>Gets the current hour (0\u201323)<\/td><\/tr><tr><td><span class=\"rnthl rntliteral\">now.minute()<\/span><\/td><td>Gets the current minute (0\u201359)<\/td><\/tr><tr><td><span class=\"rnthl rntliteral\">now.second()<\/span><\/td><td>Gets the current second (0\u201359)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To convert the result into a string, we can use the <span class=\"rnthl rntliteral\">String()<\/span> method. We also pass <span class=\"rnthl rntliteral\">DEC<\/span> as a second argument to the <span class=\"rnthl rntliteral\">string()<\/span> method to get a decimal number.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String yearStr = String(now.year(), DEC);<\/code><\/pre>\n\n\n\n<p>In the case of the month, day, hour, minute, and second, we add a leading zero when the number is smaller than 10. So, instead of having, for example: 3:5:6 (which is weird for a time format), you&#8217;ll get <span class=\"rnthl rntliteral\">03:05:06<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String monthStr = (now.month() &lt; 10 ? \"0\" : \"\") + String(now.month(), DEC);\nString dayStr = (now.day() &lt; 10 ? \"0\" : \"\") + String(now.day(), DEC);\nString hourStr = (now.hour() &lt; 10 ? \"0\" : \"\") + String(now.hour(), DEC); \nString minuteStr = (now.minute() &lt; 10 ? \"0\" : \"\") + String(now.minute(), DEC);\nString secondStr = (now.second() &lt; 10 ? \"0\" : \"\") + String(now.second(), DEC);<\/code><\/pre>\n\n\n\n<p>To get the name of the day of the week, we use the <span class=\"rnthl rntliteral\">daysOfTheWeek<\/span> array we created at the beginning of the code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String dayOfWeek = daysOfTheWeek&#091;now.dayOfTheWeek()];<\/code><\/pre>\n\n\n\n<p>Finally, we concatenate all the time fields in a variable and display it in the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Complete time string\nString formattedTime = dayOfWeek + \", \" + yearStr + \"-\" + monthStr + \"-\" + dayStr + \" \" + hourStr + \":\" + minuteStr + \":\" + secondStr;\n\n\/\/ Print the complete formatted time\nSerial.println(formattedTime);<\/code><\/pre>\n\n\n\n<p>The DS3231 gives temperature-compensated results. We can get the temperature it measures using the <span class=\"rnthl rntliteral\">getTemperature()<\/span> method on the <span class=\"rnthl rntliteral\">rtc<\/span> object. This returns the temperature in Celsius degrees.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Getting temperature\nSerial.print(rtc.getTemperature());\nSerial.println(\"\u00baC\");<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Testing the Example<\/h3>\n\n\n\n<p>With the RTC connected to the ESP8266 board and upload the code to your board.<\/p>\n\n\n\n<p>Open the Serial Monitor at a baud rate of 115200. The ESP8266 will set the RTC time and display the current time and temperature every three seconds.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"738\" height=\"352\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-Set-Get-Time-Temperature-DS3231.png?resize=738%2C352&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 DS3231 Set and Get Time and Temperature\" class=\"wp-image-165167\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-Set-Get-Time-Temperature-DS3231.png?w=738&amp;quality=100&amp;strip=all&amp;ssl=1 738w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-Set-Get-Time-Temperature-DS3231.png?resize=300%2C143&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 738px) 100vw, 738px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"setting-alarms\">DS3231 with the ESP8266: Setting Alarms<\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/DS3231-ESP8266-Setting-Alarms.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU with DS3231 Setting Alarms\" class=\"wp-image-165173\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/DS3231-ESP8266-Setting-Alarms.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/DS3231-ESP8266-Setting-Alarms.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The DS3231 RTC Module allows you to set up to two alarms: alarm 1 and alarm 2. When using the <span class=\"rnthl rntliteral\">RTCLib<\/span> Library, these are the accepted modes for the alarms:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Alarm<\/strong><\/td><td><strong>Mode<\/strong><\/td><td><strong>Meaning<\/strong> (Trigger the alarm&#8230;)<\/td><\/tr><tr><td>Alarm 1<\/td><td><span class=\"rnthl rntliteral\">DS3231_A1_PerSecond<\/span><\/td><td>every second<\/td><\/tr><tr><td>Alarm 1<\/td><td><span class=\"rnthl rntliteral\">DS3231_A1_Second<\/span><\/td><td>when the seconds match<\/td><\/tr><tr><td>Alarm 1<\/td><td><span class=\"rnthl rntliteral\">DS3231_A1_Minute<\/span><\/td><td>when the minutes match<\/td><\/tr><tr><td>Alarm 1<\/td><td><span class=\"rnthl rntliteral\">DS3231_A1_Hour<\/span><\/td><td>when the hour matches<\/td><\/tr><tr><td>Alarm 1<\/td><td><span class=\"rnthl rntliteral\">DS3231_A1_Date<\/span><\/td><td>when the date matches<\/td><\/tr><tr><td>Alarm 1<\/td><td><span class=\"rnthl rntliteral\">DS3231_A1_Day<\/span><\/td><td>when the day matches<\/td><\/tr><tr><td>Alarm 2<\/td><td><span class=\"rnthl rntliteral\">DS3231_A2_PerMinute<\/span><\/td><td>every minute<\/td><\/tr><tr><td>Alarm 2<\/td><td><span class=\"rnthl rntliteral\">DS3231_A2_Minute<\/span><\/td><td>when the minutes match<\/td><\/tr><tr><td>Alarm 2<\/td><td><span class=\"rnthl rntliteral\">DS3231_A2_Hour<\/span><\/td><td>when the hour matches<\/td><\/tr><tr><td>Alarm 2<\/td><td><span class=\"rnthl rntliteral\">DS3231_A2_Date<\/span><\/td><td>when the date matches<\/td><\/tr><tr><td>Alarm 2<\/td><td><span class=\"rnthl rntliteral\">DS3231_A2_Day<\/span><\/td><td>when the day matches<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>The following example shows how to set up two alarms and how to use them to trigger an interrupt on the ESP8266 (l<a href=\"https:\/\/randomnerdtutorials.com\/interrupts-timers-esp8266-arduino-ide-nodemcu\/\" title=\"\">earn more about interrupts with the ESP8266 here<\/a>).<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete instructions at https:\/\/RandomNerdTutorials.com\/esp8266-nodemcu-ds3231-real-time-clock-arduino\/\n*********\/\n\/\/ Example based on the library: implementation of an alarm using DS3231\n#include &lt;RTClib.h&gt;\n\nRTC_DS3231 rtc;\n\nchar daysOfTheWeek[7][12] = {&quot;Sunday&quot;, &quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot;};\n\n\/\/ the pin that is connected to SQW\n#define CLOCK_INTERRUPT_PIN 14\n\n\/\/ LED for visual indication\nconst int ledPin = 2;\n\n\/\/ set the alarms\n\/\/ (year, month, day, hour, minutes, seconds)\nDateTime alarm1Time = DateTime(2025, 01, 03, 18, 42, 0);\nDateTime alarm2Time = DateTime(2025, 01, 03, 18, 48, 0);\n\nvoid printCurrentTime(){\n  \/\/ Get the current time from the RTC\n  DateTime now = rtc.now();\n  \n  \/\/ Getting each time field in individual variables\n  \/\/ And adding a leading zero when needed;\n  String yearStr = String(now.year(), DEC);\n  String monthStr = (now.month() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.month(), DEC);\n  String dayStr = (now.day() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.day(), DEC);\n  String hourStr = (now.hour() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.hour(), DEC); \n  String minuteStr = (now.minute() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.minute(), DEC);\n  String secondStr = (now.second() &lt; 10 ? &quot;0&quot; : &quot;&quot;) + String(now.second(), DEC);\n  String dayOfWeek = daysOfTheWeek[now.dayOfTheWeek()];\n\n  \/\/ Complete time string\n  String formattedTime = dayOfWeek + &quot;, &quot; + yearStr + &quot;-&quot; + monthStr + &quot;-&quot; + dayStr + &quot; &quot; + hourStr + &quot;:&quot; + minuteStr + &quot;:&quot; + secondStr;\n\n  \/\/ Print the complete formatted time\n  Serial.println(formattedTime);\n}\n\nICACHE_RAM_ATTR void onAlarm() {\n  Serial.println(&quot;Alarm occured!&quot;);\n  \/\/ toggle the current LED state\n  int state = digitalRead(ledPin);\n  digitalWrite(ledPin, !state);\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  pinMode (ledPin, OUTPUT);\n  digitalWrite(ledPin, LOW);\n\n  \/\/ initializing the rtc\n  if(!rtc.begin()) {\n    Serial.println(&quot;Couldn't find RTC!&quot;);\n    Serial.flush();\n    while (1) delay(10);\n  }\n\n  if(rtc.lostPower()) {\n    \/\/ this will adjust to the date and time at compilation\n    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));\n  }\n  \/\/ Uncomment if you need to adjust the time\n  \/\/ rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));\n\n  \/\/we don't need the 32K Pin, so disable it\n  rtc.disable32K();\n\n  \/\/ Trigger an interrupt when the alarm happens\n  pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP);\n  attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING);\n\n  \/\/ set alarm 1, 2 flag to false (so alarm 1, 2 didn't happen so far)\n  \/\/ if not done, this easily leads to problems, as both register aren't reset on reboot\/recompile\n  rtc.clearAlarm(1);\n  rtc.clearAlarm(2);\n\n  \/\/ stop oscillating signals at SQW Pin, otherwise setAlarm1 will fail\n  rtc.writeSqwPinMode(DS3231_OFF);\n\n  \/\/ turn off alarm 2 (in case it isn't off already)\n  \/\/ again, this isn't done at reboot, so a previously set alarm could easily go overlooked\n  rtc.disableAlarm(2);\n\n  \/\/ Schedule Alarm1 to fire when the minutes match\n  if(!rtc.setAlarm1(alarm1Time, DS3231_A1_Second)) {  \/\/ this mode triggers the alarm when the minutes match\n    Serial.println(&quot;Error, alarm wasn't set!&quot;);\n  }else {\n    Serial.println(&quot;Alarm 1 will happen at specified time&quot;);\n  }\n}\n\nvoid loop() {\n  \/\/ print current date and time\n  printCurrentTime();\n\n  \/\/ Get Details about the alarm1\n  DateTime alarm1 = rtc.getAlarm1();\n  Ds3231Alarm1Mode alarm1mode = rtc.getAlarm1Mode();\n  char alarm1Date[12] = &quot;DD hh:mm:ss&quot;;\n  alarm1.toString(alarm1Date);\n  Serial.print(&quot;[Alarm1: &quot;);\n  Serial.print(alarm1Date);\n  Serial.print(&quot;, Mode: &quot;);\n  switch (alarm1mode) {\n    case DS3231_A1_PerSecond: Serial.print(&quot;PerSecond&quot;); break;\n    case DS3231_A1_Second: Serial.print(&quot;Second&quot;); break;\n    case DS3231_A1_Minute: Serial.print(&quot;Minute&quot;); break;\n    case DS3231_A1_Hour: Serial.print(&quot;Hour&quot;); break;\n    case DS3231_A1_Date: Serial.print(&quot;Date&quot;); break;\n    case DS3231_A1_Day: Serial.print(&quot;Day&quot;); break;\n  }\n  \/\/ the value at SQW-Pin (because of pullup 1 means no alarm)\n  Serial.print(&quot;] SQW: &quot;);\n  Serial.print(digitalRead(CLOCK_INTERRUPT_PIN));\n  \/\/ whether a alarm fired\n  Serial.print(&quot; Fired: &quot;);\n  Serial.print(rtc.alarmFired(1));\n\n  \/\/ Only one alarm can be set at a time, reset alarm 1 and activate alarm 2\n  \/\/ resetting SQW and alarm 1 flag\n  \/\/ the next alarm could now be configurated\n  if (rtc.alarmFired(1)) {\n    rtc.clearAlarm(1);\n    Serial.println(&quot; - Alarm cleared&quot;);\n    \n    \/\/ Set Alarm 2\n    if(!rtc.setAlarm2(alarm2Time, DS3231_A2_Minute)) {  \/\/ this mode triggers the alarm when the minutes match\n      Serial.println(&quot;Error, alarm wasn't set!&quot;);\n    }else {\n      Serial.println(&quot;Alarm 2 will happen at specified time&quot;);\n    }\n\n    \/\/ Get Details about the alarm2\n    DateTime alarm1 = rtc.getAlarm2();\n    Ds3231Alarm2Mode alarm2mode = rtc.getAlarm2Mode();\n    char alarm2Date[12] = &quot;DD hh:mm:ss&quot;;\n    alarm1.toString(alarm2Date);\n    Serial.print(&quot;[Alarm2: &quot;);\n    Serial.print(alarm2Date);\n    Serial.print(&quot;, Mode: &quot;);\n    switch (alarm2mode) {\n      case DS3231_A2_PerMinute: Serial.print(&quot;Every Minute&quot;); break;\n      case DS3231_A2_Minute: Serial.print(&quot;Minute&quot;); break;\n      case DS3231_A2_Hour: Serial.print(&quot;Hour&quot;); break;\n      case DS3231_A2_Date: Serial.print(&quot;Date&quot;); break;\n      case DS3231_A2_Day: Serial.print(&quot;Day&quot;); break;\n    }\n    \/\/ the value at SQW-Pin (because of pullup 1 means no alarm)\n    Serial.print(&quot;] SQW: &quot;);\n    Serial.print(digitalRead(CLOCK_INTERRUPT_PIN));\n    \/\/ whether a alarm fired\n    Serial.print(&quot; Fired: &quot;);\n    Serial.print(rtc.alarmFired(1));\n  }\n\n  Serial.println();\n  delay(2000);\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_DS3231_Set_Alarms.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Important notes about the alarms:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the RTC allows you to save up to two alarms;<\/li>\n\n\n\n<li>you can only have one alarm active at a time;<\/li>\n\n\n\n<li>after an alarm is triggered, you must clear its flag to avoid triggering and crashing the ESP8266;<\/li>\n\n\n\n<li>you must deactivate an alarm before activating the other.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>We&#8217;ve already covered how to initialize the RTC, and set and get the time from the DS3231 module. We&#8217;ll just explain the relevant parts related to the alarms.<\/p>\n\n\n\n<p>Define the GPIO that is connected to the SQW pin. In our case, we&#8217;re using GPIO 14, you can use any <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pinout-reference-gpios\/\" title=\"\">other suitable digital GPIO<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ the pin that is connected to SQW\n#define CLOCK_INTERRUPT_PIN 14<\/code><\/pre>\n\n\n\n<p>First, we create two <span class=\"rnthl rntliteral\">DateTime<\/span> objects to set the time for alarm 1 and alarm 2.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>DateTime alarm1Time = DateTime(2025, 01, 03, 18, 42, 0);\nDateTime alarm2Time = DateTime(2025, 01, 03, 18, 48, 0);<\/code><\/pre>\n\n\n\n<p>Then, we need to disable the 32k pin because we won&#8217;t use it.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>rtc.disable32K();<\/code><\/pre>\n\n\n\n<p>Set the SQW pin as an interrupt so that we can trigger a function when an alarm is fired. The SQW is active low, which means its state is normally HIGH and changes to LOW when an alarm is fired. When the alarm is triggered, we&#8217;ll call the <span class=\"rnthl rntliteral\">onAlarm<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Trigger an interrupt when the alarm happens\npinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP);\nattachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING);<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">onAlarm()<\/span> function, defined previously in the code, prints a message in the Serial Monitor and inverts the current state of GPIO 2 (connected to the ESP8266 onboard LED).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ICACHE_RAM_ATTR void onAlarm() {\n  Serial.println(\"Alarm occured!\");\n  \/\/ toggle the current LED state\n  int state = digitalRead(ledPin);\n  digitalWrite(ledPin, !state);\n}<\/code><\/pre>\n\n\n\n<p><strong>Note:<\/strong> the function to be called when the interrupt is triggered needs to have&nbsp;the <span class=\"rnthl rntliteral\">ICACHE_RAM_ATTR<\/span>&nbsp;before the function definition to run the interrupt code in RAM.<\/p>\n\n\n\n<p>Clear both alarm 1 and alarm 2 before setting any alarm.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>rtc.clearAlarm(1);\nrtc.clearAlarm(2);<\/code><\/pre>\n\n\n\n<p>We&#8217;ll use the SQW pin to trigger the alarms. We won&#8217;t use its functionality to generate square waves. So, we need to stop that.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>rtc.writeSqwPinMode(DS3231_OFF);<\/code><\/pre>\n\n\n\n<p>We can only have one alarm going at a time. So, disable alarm 2 before setting up alarm 1.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>rtc.disableAlarm(2);<\/code><\/pre>\n\n\n\n<p>Set up the alarm 1 using the <span class=\"rnthl rntliteral\">setAlarm1()<\/span> function on the <span class=\"rnthl rntliteral\">rtc<\/span> object. Pass as arguments the time for alarm 1 and the alarm mode. We&#8217;ve already seen the alarm mode options for alarm 1 and alarm 2 before. In this case, we&#8217;re setting it to <span class=\"rnthl rntliteral\">DS3231_A1_Minute<\/span>, which means the alarm will fire when the minutes match.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Schedule Alarm1 to fire when the minutes match\nif(!rtc.setAlarm1(alarm1Time, DS3231_A1_Minute)) {  \/\/ this mode triggers the alarm when the minutes match\n  Serial.println(\"Error, alarm wasn't set!\");\n} else {\n  Serial.println(\"Alarm 1 will happen at specified time\");\n}<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, we print the details of the current alarm.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Get Details about the alarm1\nDateTime alarm1 = rtc.getAlarm1();\nDs3231Alarm1Mode alarm1mode = rtc.getAlarm1Mode();\nchar alarm1Date&#091;12] = \"DD hh:mm:ss\";\nalarm1.toString(alarm1Date);\nSerial.print(\"&#091;Alarm1: \");\nSerial.print(alarm1Date);\nSerial.print(\", Mode: \");\nswitch (alarm1mode) {\n  case DS3231_A1_PerSecond: Serial.print(\"PerSecond\"); break;\n  case DS3231_A1_Second: Serial.print(\"Second\"); break;\n  case DS3231_A1_Minute: Serial.print(\"Minute\"); break;\n  case DS3231_A1_Hour: Serial.print(\"Hour\"); break;\n  case DS3231_A1_Date: Serial.print(\"Date\"); break;\n  case DS3231_A1_Day: Serial.print(\"Day\"); break;\n}\n\/\/ the value at SQW-Pin (because of pullup 1 means no alarm)\nSerial.print(\"] SQW: \");\nSerial.print(digitalRead(CLOCK_INTERRUPT_PIN));\n\/\/ whether a alarm fired\nSerial.print(\" Fired: \");\nSerial.print(rtc.alarmFired(1));<\/code><\/pre>\n\n\n\n<p>We can check whether alarm 1 has fired using the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (rtc.alarmFired(1)) {<\/code><\/pre>\n\n\n\n<p>When it fires, we clear that alarm and start setting up alarm 2.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Set Alarm 2\nif(!rtc.setAlarm2(alarm2Time, DS3231_A2_Minute)) {  \/\/ this mode triggers the alarm when the minutes match\n  Serial.println(\"Error, alarm wasn't set!\");\n} else {\n  Serial.println(\"Alarm 2 will happen at specified time\");\n}<\/code><\/pre>\n\n\n\n<p>This is just a quick example that shows the details about setting up alarms with the DS3231 RTC module. Now, you should be able to modify this example to use alarms in your automation and IoT projects.<\/p>\n\n\n\n<p>After uploading the code, you should get information on the Serial Monitor about the alarms. The ESP8266 onboard LED will toggle every time an alarm is fired.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"928\" height=\"379\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-Setting-Alarms.png?resize=928%2C379&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with DS3231 RTC Module - Triggering Alarms\" class=\"wp-image-165168\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-Setting-Alarms.png?w=928&amp;quality=100&amp;strip=all&amp;ssl=1 928w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-Setting-Alarms.png?resize=300%2C123&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-Setting-Alarms.png?resize=768%2C314&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 928px) 100vw, 928px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you learned how to interface the DS3231 RTC module with the ESP8266 to get the time and trigger alarms. This module can be useful for periodic tasks, datalogging, automation, and more. You can also add an OLED display or LCD to create a digital clock.<\/p>\n\n\n\n<p>We have guides for other modules with the ESP8266 that you may find useful.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-neo-6m-gps-module-arduino\/\">ESP8266 NodeMCU with <strong>NEO-6M GPS Modul<\/strong>e (Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-anemometer-wind-speed-arduino\/\">ESP8266 NodeMCU with an <strong>Anemometer<\/strong>: Measure Wind Speed (Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-0-96-inch-oled-display-with-arduino-ide\/\">ESP8266 with 0.96 inch<strong> OLED Display <\/strong>with Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-i2c-lcd-arduino-ide\/\">How to Use <strong>I2C LCD<\/strong> with ESP32 on Arduino IDE (ESP8266 compatible)<\/a><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP8266 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\">Home Automation using EPS8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\">Free ESP8266 Projects and Tutorials<\/a><\/li>\n<\/ul>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to interface the DS3231 Real Time Clock Module with the ESP8266 to get time and set alarms. The DS3231 RTC module is a great module for accurate timekeeping, &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP8266 NodeMCU: DS3231 Real Time Clock Module (RTC) \u2014 Getting Time and Setting Alarms\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-ds3231-real-time-clock-arduino\/#more-165166\" aria-label=\"Read more about ESP8266 NodeMCU: DS3231 Real Time Clock Module (RTC) \u2014 Getting Time and Setting Alarms\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":165170,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[265,214,246,300,240,264],"tags":[],"class_list":["post-165166","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp8266-project","category-esp8266","category-esp8266-arduino-ide","category-0-esp8266","category-esp8266-projects","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/01\/ESP8266-DS3231-RTC-Arduino-IDE.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/165166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=165166"}],"version-history":[{"count":7,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/165166\/revisions"}],"predecessor-version":[{"id":169482,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/165166\/revisions\/169482"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/165170"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=165166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=165166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=165166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}