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).
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()
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
}
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.
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.
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
Excellent!!
Long ago I bought one of these and I have never tested…
Thanks for sharing!!
You’re welcome! Thanks for reading
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?
You should be able to do that, but I don’t have any tutorials on that exact subject.
Thanks for asking,
Rui
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.
Simply search for “RTC Arduino fritzing part” and add it to your Fritzing parts lits
thank you very much riu
how to apply this to RFID attendance system
Hi.
You can take a look at the following tutorial that uses RFID and RTC.
Arduino Time Attendance System with RFID
Regards,
Sara 🙂
Hi! The day of the month doesn’t change, what line am I missing that controls this. Everything else works fine. Thanks! Great project.
Hi Jim.
That’s weird that you’re getting everything ok, except the day of the month.
The lines that control the day of the month are lines 29, 50, 73 on our code: https://github.com/RuiSantosdotme/Random-Nerd-Tutorials/blob/master/Projects/rtc_example.ino
Can you double-check that your code is similar to our example?
Regards,
Sara
Sara Santos Thank you very much for your information
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.
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
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 !
Good question, so our rtc will update despite DST changes.
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.
Hi Mike.
I’m not sure I completely understood what you want to do.
But take a look at this tutorial and see if it helps: https://randomnerdtutorials.com/how-to-do-daily-tasks-with-arduino/
Regards,
Sara
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?
Hi.
We have this tutorial that might help:
https://randomnerdtutorials.com/how-to-do-daily-tasks-with-arduino/
Regards,
Sara
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.
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
i cant use rfid and sd card together, becuse if sd card avelable, rfid cant worked and conflict miso pin, plz hep to me
Hi.
You can use the same SPI pins as long as you use a different CS (select pin) for each module.
Regards,
Sara
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
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.
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!
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”);
}
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.
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.
hi rui i want to interface the ds3231 with esp8266 ow do i go about it
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.
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)
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