Guide for Real Time Clock (RTC) Module with Arduino (DS1307 and DS3231)

This post is about how to use the DS1307 Real Time Clock (RTC) module with the Arduino. You can also follow this guide for other similar modules like the DS3231 RTC.

Introducing the Real Time Clock module

The real time clock module is the one in the figure below (front and back view).

rtc-front-and-back-view

When you first use this module, you need to solder some header pins.

As you can see in the picture above, the module has a backup battery installed. This allows the module to retain the time, even when it’s not being powered up by the Arduino. This way, every time you turn on and off your module, the time doesn’t reset.

This module uses I2C communication. This means that it communicates with the Arduino using just 2 pins.

Where to buy?

The Real Time Clock is an affordable module. You can check the DS1307 Real Time Clock module on Maker Advisor and find the best price.

Pin Wiring

Wiring the RTC module is pretty straightforward!

Pin Wiring to Arduino Uno
SCL A5
SDA A4
VCC 5V
GND GND

If you’re using other Arduino board rather than the uno, chek out what are their SCL and SDA pins.

  • Nano: SDA (A4); SCL(A5)
  • MEGA: SDA (20); SCL(21)
  • Leonardo: SDA (20); SCL(21)

Example: Displaying date and time on the serial monitor

This example displays date and time on the serial monitor.

Parts required

For this example you need the following parts (click the links below to find the best price at Maker Advisor):

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematics

Connect your Real Time Clock module to your Arduino as in the schematics below.

Code

Working with the RTC requires two important steps:

  • setting the current time, so that the RTC knows what time is it
  • retaining the time, so that the RTC always gives the correct time, even when it is turned off

Set the current time in the Real Time Clock

For setting the current time you need to change the code provided.

  • set your current time int the function setDS3231time()

set-the-time

The parameters for the function are highlighted in red: seconds, minutes, hours, day of the week, date, month and year (in this order). Sunday is the day 1 of the week and Saturday is 7. Don’t forget to uncomment that line of code.

After setting the current time, you can upload the provided code with the required modifications.

The code provided was written by John Boxall from tronixstuff. You can read his tutorial here.

// Written by John Boxall from http://tronixstuff.com

#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val){
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val){
  return( (val/16*10) + (val%16) );
}
void setup(){
  Wire.begin();
  Serial.begin(9600);
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
  setDS3231time(30,42,16,5,13,10,16);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year){
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x0E); // select register
  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOS
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime(){
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10){
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10){
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch(dayOfWeek){
  case 1:
    Serial.println("Sunday");
    break;
  case 2:
    Serial.println("Monday");
    break;
  case 3:
    Serial.println("Tuesday");
    break;
  case 4:
    Serial.println("Wednesday");
    break;
  case 5:
    Serial.println("Thursday");
    break;
  case 6:
    Serial.println("Friday");
    break;
  case 7:
    Serial.println("Saturday");
    break;
  }
}
void loop(){
  displayTime(); // display the real-time clock data on the Serial Monitor,
  delay(1000); // every second
}

View raw code

Retain the time in the Real Time Clock

If you don’t want to reset the time everytime the RTC is turned off, you should do the following:

  • after setting up the time, you should comment the function that sets the time and upload the code again.

comment-the-code

This is a very important step to set up the time in your RTC. If you don’t do this, everytime your RTC resets, it will display the time that you’ve set up previously and not the current time.

Demonstration

Open the serial monitor at a baud rate of 9600 and you’ll see the results.

Here’s the Serial Monitor displaying the current date and time.

demonstration

Wrapping up

I hope you’ve found this guide useful.

The RTC module is really useful and you can use it as a clock, timer, etc..

If you would like to display the date and time with the RTC module in the OLED display, check the following post:

What projects have you done or are you expecting to build with this module?

Let me know by writing a comment down below.

Thanks for reading,

Rui and Sara



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

34 thoughts on “Guide for Real Time Clock (RTC) Module with Arduino (DS1307 and DS3231)”

  1. Hi Rui. I plan to pay the book tomorrow (home automation vith esp8266). But now i wonder can i use RTC and arduino as trigger at some def moment to send me a message etc information on my serial monitor from analog sensor via SIM800L modul on my mobile phone?

    Reply
  2. Hello, good morning. Could you please tell me how you did this figure on fritzing, because I’ve tried and I don’t found on it? Thank you.

    Reply
  3. Hiđź‘‹ I’m trying to work on RTC with ESP32 Cam but unfortunately I don’t know where to connect SDA and SCL of RTC to esp32 cam. Can you please help me on how to make it work?
    Thank you so much for your fast response.

    Reply
    • Hi.
      Are you using microSD card?
      If you’re using microSD card, you can use GPIO 1, GPIO 3, and GPIO 16 (but you’ll be left without serial pins to use the Serial Monitor). However, these are the only pins that are not being used by the microSD card.
      If you’re not using the microSD card, you can use any other of the exposed GPIOs.
      Then, you need to create an I2C instance with the chosen pins. You can follow this guide for I2C communication: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/
      I hope this helps.
      Regards,
      Sara

      Reply
  4. Hi, do you have an idea on how to update the RTC time directly with an NTP server ?

    It could be done once at the initialisation to be sure the RTC remains precise.

    Thanks Rui and Sara !

    Reply
  5. Hi Rui and Sara, and congratulations always for your instructive and interesting guides.
    I have tested this scketch on a Nano and it works great.
    I was wondering if it’s possible with this form, turn on and hold my card for 6 hours a day .. (for example) every day. A kind of deep sleep, but for long periods of time.
    I have looked for a pattern of this type here and on the internet, but every time I find an example of deep sleep it seems that these do not exceed a few seconds of interval between one ignition and another. Do you have a suggestion for me? Thanks.
    Mike.

    Reply
  6. Thanks for putting this together. Just learning how to deal with all of this. Is there any info on using the rtc to drive an action every other day?

    Reply
  7. Is it safe to connect the VCC to the pin which i have defined HIGH?
    Idea is about ESP deep sleep, External wakeup.

    void setup() {
    pinMode(15,OUTPUT);
    digitalWrite(15,HIGH);
    delay(2000);
    ESP.deepSleep(0);
    }

    I have connected led to gpio 15 of my esp8266. I left the gpip15 high, after 2sec led will be off because of sleep. So can i use that 2sec to read time? Or is there any risk that I’m missing? I don’t want to destroy my ds3231.
    Deep sleep is like destructor, ~setup(), correct?

    I have learnt too much from here because your tutorial are filtered beautifully.

    Thanks.
    I really need the answer before i try something faulty.

    Reply
    • Hi.
      When you define a pin as HIGH with the ESP32 or ESP8266, it outputs 3.3V.
      So, you can connect the RTC VCC pin to that pin.
      Regards,
      Sara

      Reply
  8. Interesting, I noted that this isn’t dependent upon an external library. Is that because the sketch provides all the utility that’s needed? Thank you

    Reply
  9. Hello Rui,
    I would like to ask how is possible to set time by buttons. Is there any way how to do it? I want to build wall clock and sometimes is necessary correct time settings.

    Reply
  10. Awesome! I am currently working on building a seven segment 4 digit clock using the uno, ds3231, and 114 ws2812b leds. I wanted to build a large display. I’m new at all of this so I’m hoping to find enough info to make it work. Thanks!

    Reply
  11. Hi Rui and Sara, and congratulations always for your instructive and interesting guides.
    I have tested this scketch on a ESP-32 and it works great.

    Can u Add this for Temperature on DS3231on your exemple ?? Maybe this help.

    //——————————————————————————————-
    // Routine pour Lire la Température dans le DS3231
    // Par: Luc Verville
    // Mars 21
    // Rev :1.0
    //————————————————————————————————

    void showTemperature() {
    uint8_t lsb;
    int8_t msb;
    Wire.beginTransmission(DS3231_I2C_ADDRESS);
    Wire.write(0x11); //Temperature registers (11h-12h) get updated automatically every 64s
    // Wire._I2C_WRITE(DS3231_TEMPERATUREREG);
    Wire.endTransmission();

    Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
    msb = Wire.read(); // msb = bcdToDec(Wire.read());
    lsb = Wire.read(); // lsb = bcdToDec(Wire.read());

    // Serial.print(“Temperature : “); Serial.print ((float)msb + (lsb >> 6) * 0.25f ); Serial.print(” C “);
    // Serial.print (( 1.8 * ((float)msb + (lsb >> 6) * 0.25f) + 32)); Serial.println(” F”);

    }

    Reply
  12. I see that there is nearly full consensus that this code works for setting and keeping the time even when disconnected from power. I have done this and many other “ideas” from various people on the web and my DS3231 clocks never keep the correct time if I unplug it from power with a battery in it. I have wasted hours taking out and replacing batteries, restarting, etc. etc. etc. Yes, etc. So, what I do now is put in two buttons to manually advance the hour and/minute settings when my clock starts up. All I need are the clock times so this works well for my clocks and I never have to worry again about the RTC keeping the correct time. No need to respond, I have given up on having my RTC’s retain the correct time.

    Reply
  13. Buy another DS3231 – your unit must be faulty.
    These units are amazingly accurate – I have quite a few running for years!!
    Check if the temperature in your unit does not exceed the temperature as per spec – this might affect it by a few seconds per month!
    Not the extract below…

    Retain the time in the Real Time Clock
    If you don’t want to reset the time every time the RTC is turned off, you should do the following:

    after setting up the time, you should comment the function that sets the time and upload the code again.
    comment-the-code

    This is a very important step to set up the time in your RTC. If you don’t do this, everytime your RTC resets, it will display the time that you’ve set up previously and not the current time.

    Reply
  14. Hi Rui and Sara,

    Thank you for publishing the example using a RTC.
    I just have bought a RTC module and connected it as you show in the schematics.
    The layout is the same as the model you have showed in the schematics.
    I have put no battery in the module for now. It is continuously connected and the power is up.
    I am using a Nano using the same connections (A4 and A5) as the Uno.
    Then I copied today the raw code (written by John Boxall from http://tronixstuff.com) as the sketch from your page.
    I changed the line “setDS3231time(30,42,16,5,13,10,16);” for the initial time (16:32:00 at Wednesday 4th of October 2023) as
    sec=0, minutes=32, hours=16, day (Monday)=2, date=9, month October=10, year=23
    as follows: setDS3231time(0,32,16,2,9,10,23);
    Then I uploaded this sketch and opened the Serial Monitor and saw this as result:

    23:10:09 1/1/0 Day of week: Sunday
    23:10:10 1/1/0 Day of week: Sunday
    23:10:11 1/1/0 Day of week: Sunday
    23:10:12 1/1/0 Day of week: Sunday
    23:10:13 1/1/0 Day of week: Sunday

    The year is used as hours etc, it looks as all is in reverse order. Always 1/1/0 Day of week:Sunday

    I have also used your I2C scanner, downloaded from your page about the OLED display SSD1306 to determine the Address of this RTC
    with this output in the Serial Monitor:

    Scanning…
    I2C device found at address 0x57
    I2C device found at address 0x5F
    I2C device found at address 0x68
    done

    I believe it is address 0x68.
    In your I2C sketch I have looked but can not find where the other two addresses are coming from.

    Reply
  15. Little correction:
    The line (16:32:00 at Wednesday 4th of October 2023) had to be
    (16:32:00 at Monday, the 9th of October 2023)

    Reply
  16. hi Guys

    im working on a timer using ds1307 but im facing a problem when i set the start time lets say to 23:00 & stop time to 00:05

    here is the code to turn on
    if ((out1TimeControl) == 0 && (settingsDisplay1) == 0) {
    if ((out1OffTimeSetHours) < out1OnTimeSetHours) {
    if ((tm.Hour) >= out1OnTimeSetHours && (tm.Minute) >= out1OnTimeSetMinutes) {
    out1TimeControl = 1;
    }
    }
    }

    im looking for idea to turn off please

    thanks

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.