DS1307 Real Time Clock and Arduino

Electronics Electronics Project Ideas Micro-controller

There are many applications where a real time clock (RTC) is of use for display, data logging with date/time stamp, etc. When you find yourself needing a RTC for your project, this article will help guide you to completion.

There are many, probably thousands, of articles on RTC’s and how to interface them with an Arduino. My goal is to bring the best of that information into a single place for you to use as a reference. The articles and references used here have been listed below.

Why a Real Time Clock?

Virtually all micro-controllers have a built-in timers (including all Arduino’s). These timers are initialized on power-up and are fairly accurate. The problem with these internal timers is twofold:

  • They are power dependent. When power is removed, the internal timers are reset to 0.
  • They do not maintain month, day, year, hour, minute, etc. type data. For example, in Arduino, you use the mills() function to return the internal timer counter value.

DS1307 Real Time Clock

The DS1307 serial real-time clock (RTC) is a low-power, full binary-coded decimal (BCD) clock/calendar plus 56 bytes of NV SRAM. Address and data are transferred serially through an I2C, bidirectional bus. The clock/calendar provides seconds, minutes, hours, day, date, month, and year information. The end of the month date is automatically adjusted for months with fewer than 31 days, including corrections for leap year. The clock operates in either the 24-hour or 12-hour format with AM/PM indicator. The DS1307 has a built-in power-sense circuit that detects power failures and automatically switches to the backup supply. Timekeeping operation continues while the part operates from the backup supply.

DS1307 Technical Details

DS1307 Pinout

DA1307 Pinout
PINDESCRIPTION
X1 & X2Connections for standard 32.768 kHz quartz crystal. The internal oscillator circuitry is intended for operation with a crystal having a specified load capacitance of 12.5pF. X1 is the input to the oscillator and can alternatively be connected to an external 32.768 kHz oscillator. The output of the internal oscillator, X2 is drifted if an external oscillator is connected to X1.
VBATBattery input for any standard 3V lithium cell or other energy source.

Battery voltage should be between 2V and 3.5V for suitable operation. The nominal write protect trip point voltage at which access to the RTC and user RAM is denied is set by the internal circuitry as 1.25 x VBAT nominal. A lithium battery with 48mAhr or greater will backup the DS1307 for more than 10 years in the absence of power at 25ºC. UL recognized to ensure against reverse charging current when utilized as a part of conjunction with a lithium battery.
GNDGround.
SDASerial Data Pin. It is the Data Input/Output pin of the I2C Interface. An external pull-up of 5V is required, usually through a 10KΩ Resistor.
SCLSerial Clock Input Pin. It is the clock input pin of the I2C Interface. An external pull-up of 5V is required, usually through a 10KΩ Resistor.
SQW/OUTSquare wave/output driver. When enabled, the SQWE bit set to 1, the SQW/OUT pin outputs one of four square-wave frequencies (1Hz, 4 kHz, 8 kHz, and 32 kHz). This is also open drain and requires an external pull-up resistor. It requires application of either Vcc or Vb at to operate SQW/OUT, with an allowable pull up voltage of 5.5V and can be left floating, if not used.
(I will write a separate article with information on how this output can be used with interrupts and an Arduino.)
VccMain power in; 4.5v minimum and 5.5v maximum.

DS1307 Common Wiring Diagram


Real Time Clock Breakout Boards

Understanding the common wiring diagram above is quite useful if you wish to connect the components yourself. However, if you are prototyping or in quick need of a solution for your project, there are literally hundreds of RTC breakout boards available.

I have my preferences as to where I purchase electronic parts. I personally prefer manufactures who have great products, documentation and support. It really doesn’t matter what vendor you choose to purchase your DS1307 breakout board from. You can find hundreds of variations on Amazon if you’d like to look there.

The breakout board I’ll use for the demonstration below is from Adafruit (one of my goto Maker companies).


Adafruit DS1307 Breakout and Arduino UNO Example

In this simple example, I will show you how to connect an Adafruit DS1307 breakout to an Arduino UNO then program it to display the current time in the serial monitor.

Initializing DS1307 Current Time

Something you may be thinking about is how do you initialize the DS1307 clock? The first time the DS1307 chip is powered up, the internal clock registers must be set. This can be accomplished in code by using constants, reading the current world clock from the Internet, etc.

For the purposes of this example, we will be setting the current time to the date and time the sketch was compiled. This gives us a good starting point and is usually only a few seconds off.

Adafruit DS1307 RTC Breakout wired to Arduino UNO
My personal prototype – Adafruit DS1307 Breakout wired to Arduino UNO

Arduino Code to Initialize and Read the Current Time

Below is the code for this example. I will provide you with the entire code sample first then provide details as to what each section is doing.

The code for this example can be found in my GitHub repository here:

https://github.com/bobmixon/AdafruitDS1307RTCBreakout/tree/master/aide/ArduinoUNO

Download this file and place it in your local Arduino program directory. Then open it in the Arduino IDE.

Install Required Library

This example requires the Adafruit RTClib library to be installed. To accomplish this, do the following.

  1. Select the Tools -> Manage Librariesmenu option. This will open the library manager.
  2. Search for RTClib.
  3. Select and install the latest version of the RTClib.

Understanding the Code

The code starts off with the inclusion of the Arduino.h and RTClib.h header files then identifies the board the code is running on. I include board detection to indicate what boards I’ve tested on. As of this writing, I have only tested it on an Arduino UNO. As I test on additional boards, I will update the code accordingly.

Note if you are wanting to run this on a board other than the Arduino UNO, please leave me a comment below and I will update accordingly.

At a high level, this example code does the following:

  1. setup – Initialize the Serial and rtc objects.
  2. loop – Read the RTC values and display them on the Serial Terminal.
  3. There are 3 supporting functions
    • initializeRTC – Initializes the rtc object.
    • initializeSerial – Initializes the Serial Terminal interface.
    • serialPrintDateTime – Prints the current date/time on the Serial Terminal.
//**************************************************************************************************
// ArduinoUNOExample1
// This example demonstrates how to connect and use the Adafruit DS1307 RTC Breakout.
//
// REVISIONS
// 02/29/2020   Bob Mixon
// Initial module creation and testing.
//**************************************************************************************************

#include <Arduino.h>

// The Adafruit RTC library.
#include "RTClib.h"

// These are the boards this code has been tested with. Other boards will be added as time permits.
#if defined(ARDUINO_AVR_UNO)       
  #define BOARD_NAME "Arduino UNO"
#else
  #error "UNKNOWN BOARD"
#endif

The next section of code creates an instance of the RTC_DS1307 class. This class represents the RTC breakout board and provides the interface necessary to access all the DS1307 RTC features.

After that is the initialization of a boolean flag named rtcRunning. This flag is set during the setup function and will indicate whether or not the DS1307 RTC has been correctly initialized and is running.

Next is a define, RTC_INITIALIZE, that indicates whether or not the DS1307 board requires initialization.

Lastly, in this section, I define a character array to contain the days of week.

// DS1307 RTC Breakout.
RTC_DS1307 rtc;
bool rtcRunning = false;
#define RTC_INITIALIZE true

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

The next section is the setup function. Here we initialize the default Serial class and DS1307 RTC. The initializeSerial and initializeRTC are described, in detail, further down in this code description.

//--------------------------------------------------------------------------------------------------
// setup
// Called and run only once.
//--------------------------------------------------------------------------------------------------
void setup()
{
  // Initialize the serial communications. This is for displaying status and RTC values only.
  initializeSerial();

  // Initialize the RTC.
  rtcRunning = initializeRTC();
}

Next is the standard Arduino loop function. Here I check to see if the DS1307 RTC is running then get the RTC data and print it to the Serial Terminal.

Note if the RTC is not running, determined in the initializeRTC function, the loop will simply exit without going any further.

//--------------------------------------------------------------------------------------------------
// loop
// Called continuously..
//--------------------------------------------------------------------------------------------------
void loop()
{
  // We won't do anything if the RTC is not available or running.
  if(!rtcRunning)
  {
    Serial.println(F("RTC is not running"));
    delay(1000);
    return;
  }

  // Return the date and time as a DateTime object.
  DateTime curDateTime = rtc.now();

  // Display the date and time on the serial terminal.
  serialPrintDateTime(curDateTime);

  delay(500);
}

Next is the initializeRTC function. It’s entire purpose is to initialize and configure the DS1307 RTC breakout board.

The rtc.begin() call will return false if the DS1307 RTC board cannot be found. If the board cannot be found, the user is notified and the function returns false. If the board is found, the RTC is then checked to make sure it’s running. And if the RTC is not running, the user is notified and the function returns false.

The last part of this function is to initialize the RTC date and time values. As long as you have a battery in the DS1307 board, you only need to initialize it once. For the purposes of this example, I am using the date and time the sketch was compiled. This provides a date and time that is close to the current; usually only off by a few seconds.

//--------------------------------------------------------------------------------------------------
// initializeRTC
//--------------------------------------------------------------------------------------------------
bool initializeRTC()
{
  Serial.print(F("RTC  : "));
  if(!rtc.begin()){
    Serial.println(F("Couldn't find RTC"));
    return(false);
  }
  if(!rtc.isrunning())
  {
    Serial.println(F("RTC is not running"));
    return(false);
  }
  Serial.println(F("RTC is running!"));
  
  // If this is the first time you are running this, the RTC requires initialization or it will not
  // operate correctly. The following line sets the RTC to the date & time this sketch was compiled.
  if(RTC_INITIALIZE)
  {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  
  // If you'd like to set the RTC with an explicit date & time...
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

  // RTC initialization successful.
  return(true);
}

Next is the initializeSerial function which simply initializes the default Serial communications object (Serial) with a baud rate of 57600.

//--------------------------------------------------------------------------------------------------
// initializeSerial
//--------------------------------------------------------------------------------------------------
void initializeSerial()
{
  while(!Serial);
  Serial.begin(57600);
  Serial.print(F("Board: "));
  Serial.println(BOARD_NAME);
}

And lastly, the function serialPrintDateTime simply displays the specified DateTime value on the Serial Terminal.

//--------------------------------------------------------------------------------------------------
// serialPrintDateTime
// Prints the specified date and time to the serial terminal.
//--------------------------------------------------------------------------------------------------
void serialPrintDateTime(DateTime dt)
{
  Serial.print(dt.month(), DEC);
  Serial.print('/');
  Serial.print(dt.day(), DEC);
  Serial.print('/');
  Serial.print(dt.year(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[dt.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(dt.hour(), DEC);
  Serial.print(':');
  Serial.print(dt.minute(), DEC);
  Serial.print(':');
  Serial.print(dt.second(), DEC);
  Serial.println();
}

That’s all there is to the code! Compile and upload the code, open your Serial Terminal window and you should see similar results.

Results of Adafruit DS1307 RTC Breakout Example Code

Article References


References to Other DS1307 RTC Examples

Note, I have not tested the references below. If you have an issue with one, please contact the author of that article first. If you are having difficulties doing so, leave me a comment below and I will take a look at it with you.

Conclusion

In this article I showed you how to connect the Adafruit DS1307 RTC breakout board to an Arduino UNO and communicate with it for display on the Serial Terminal. I am hoping this provides enough information to get you started on your project.

In the next article I do on this topic, I will demonstrate how to read the date and time from an Internet based world clock and initialize the RTC.

As usual if you have any questions, comments or needs, please leave me a comment below and I’ll answer as soon as I can.

Until next time… stay a #Maker and share!

Bob Mixon

My primary goal in life is to support my family, be a friend and enjoy each day as it may be my last. For work, I am a Senior Office 365 and SharePoint Solution Architect, Senior Information Architect and Microsoft SharePoint MVP. You can read my entire profile here.

More Posts - Website

Follow Me:
LinkedIn

Tagged

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.