DS1307 Real Time Clock and Arduino: Complete Setup and Code Tutorial

DS1307 Real Time Clock and Arduino: Complete Setup and Code Tutorial

Are you looking to add precise timekeeping to your Arduino projects? Whether you're creating a home automation system, a data logger, or any project that requires accurate time tracking, the DS1307 Real Time Clock (RTC) module is an excellent choice.

 

In this article, we will dive deep into using the DS1307 RTC module with Arduino, provide a step-by-step guide, and offer a comparison between the DS1307 and DS1302 RTC modules. This guide is designed for beginners and will help you get your projects up and running in no time.

 

 

Why Use an RTC Module in Your Arduino Projects?

 

An RTC module, like the DS1307, allows your Arduino to keep track of the time even when it's powered off. This is crucial for applications such as:

  • Data Logging: Record timestamps with your sensor readings.
  • Home Automation: Schedule tasks like turning lights on and off.
  • Alarm Systems: Trigger alarms at specific times.

 

The DS1307 Tiny RTC I2C Module
The DS1307 Tiny RTC I2C Module with a 3-volt coin cell.

 

DS1307 RTC Module
This is what the DS1307 Tiny RTC Module looks like from the back. You can see the DS1307 chip here.

 

 

Key Features of the DS1307 RTC Module

  • Battery Backup: Keeps track of time even during power outages.
  • I2C Communication: Simple two-wire interface for easy connection with Arduino.
  • Timekeeping: Provides seconds, minutes, hours, day, date, month, and year information.

 

 

Comparing DS1307 and DS1302 RTC Modules

 

When selecting an RTC module for your project, you might come across the DS1302. Here's a comparison between the DS1307 and DS1302 to help you decide which one to use.

Feature DS1307 RTC Module DS1302 RTC Module
Communication I2C (2-wire) SPI (3-wire)
Voltage 5V 2V to 5.5V
Battery Backup Yes Yes, with a separate pin for battery input
Timekeeping Seconds, minutes, hours, day, date, month, year Seconds, minutes, hours, day, date, month, year, and supports leap year compensation up to 2100
Communication Protocol Simpler (I2C requires fewer wires) More complex (SPI requires more wires)
Voltage Range Narrower Broader, more versatile
Battery Backup Pin No dedicated pin Dedicated pin for battery input

 

Key Differences

 

  • Communication Protocol: The DS1307 uses I2C, which is simpler and requires fewer wires compared to the DS1302's SPI.
  • Voltage Range: The DS1302 has a broader voltage range, making it more versatile in different projects.
  • Battery Backup: Both modules offer battery backup, but the DS1302 provides a dedicated pin for battery input, which might be beneficial for certain designs.

 

 

 

Getting Started with DS1307 RTC Module and Arduino

 

DS1307 RTC Module pinout.
The DS1307 RTC Module pinout.

 

Components Needed

  • Arduino Board (e.g., Arduino Uno)
  • DS1307 RTC Module
  • Breadboard and Jumper Wires
  • 3V Lithium Coin Cell Battery (for RTC module backup)

 

Circuit Diagram

To connect the DS1307 RTC module to the Arduino, follow the circuit diagram below:

 

DS1307 RTC Module

Arduino

VCC 5V
GND GND
SDA A4
SCL A5

 

 

 

 

 

 

 

 

DS1307 Tiny RTC Module circuit
The DS1307 Tiny RTC Module circuit connected via I2C.

 

 

Installing the Required Libraries

 

Before we start coding, we need to install the necessary libraries. Download the DS1307 library here:

 

To install the library:

Open the Arduino IDE and go to Sketch > Include Library > Add .ZIP Library. Search for the downloaded library and click OK.

 

 

Arduino Code for DS1307 RTC Module

 

Here's a basic example code to get you started with the DS1307 RTC module.



#include "DS1307.h"

DS1307 clock;//define a object of DS1307 class

void setup() {
    Serial.begin(9600);
    clock.begin();

    //uncomment the next 4 lines to set a new date and time, then upload
    //clock.fillByYMD(2024, 6, 25); //June 25,2024 (year, month, date)
    //clock.fillByHMS(13, 55, 30); //1:55 PM 30 13:55:30 (hh:mm:ss)24 hr format
    //clock.fillDayOfWeek(TUE);//Tuesday
    //clock.setTime();//write time to the RTC chip

    //comment the 4 lines again then upload so that the date and time will not be reset
}
void loop() {
    clock.getTime();
    Serial.print(clock.hour, DEC);
    Serial.print(":");
    Serial.print(clock.minute, DEC);
    Serial.print(":");
    Serial.print(clock.second, DEC);
    Serial.print("  ");
    Serial.print(clock.month, DEC);
    Serial.print("/");
    Serial.print(clock.dayOfMonth, DEC);
    Serial.print("/");
    Serial.print(clock.year + 2000, DEC);
    Serial.println();

    delay(1000);

}

 

This should be the output once you upload the code and open the Serial Monitor:

 

 

Step-by-Step Explanation of the Code

 

Including the Library and Creating an Object


#include "DS1307.h"

DS1307 clock; // Define an object of DS1307 class

  • #include "DS1307.h": This line includes the DS1307 library, which contains the necessary functions and definitions for interacting with the DS1307 RTC module.
  • DS1307 clock;: This line creates an instance of the DS1307 class named clock. This object will be used to call the functions provided by the library to interact with the RTC module.

 

 

Setup Function


void setup() {
    Serial.begin(9600);
    clock.begin();

    // Uncomment the next 4 lines to set a new date and time, then upload
    // clock.fillByYMD(2024, 6, 25); // June 25, 2024 (year, month, date)
    // clock.fillByHMS(13, 55, 30); // 1:55 PM (13:55:30) in 24-hour format
    // clock.fillDayOfWeek(TUE); // Tuesday
    // clock.setTime(); // Write time to the RTC chip

    // Comment the 4 lines again then upload so that the date and time will not be reset
}

  • Serial.begin(9600);: Initializes the serial communication at a baud rate of 9600 bits per second. This is used for communication between the Arduino and the computer.
  • clock.begin();: Initializes the RTC module. It sets up the communication between the Arduino and the DS1307 RTC module.

 

The following lines are commented out. If you want to set the time and date on the RTC module, you need to uncomment these lines, upload the sketch to the Arduino, and then comment them out again before uploading the sketch a second time:

 

  • clock.fillByYMD(2024, 6, 25);: Sets the year, month, and day (June 25, 2024).
  • clock.fillByHMS(13, 55, 30);: Sets the hour, minute, and second (13:55:30 in 24-hour format).
  • clock.fillDayOfWeek(TUE);: Sets the day of the week to Tuesday.
  • clock.setTime();: Writes the set time and date to the RTC module.

 

 

Loop Function


void loop() {
    clock.getTime();
    Serial.print(clock.hour, DEC);
    Serial.print(":");
    Serial.print(clock.minute, DEC);
    Serial.print(":");
    Serial.print(clock.second, DEC);
    Serial.print("  ");
    Serial.print(clock.month, DEC);
    Serial.print("/");
    Serial.print(clock.dayOfMonth, DEC);
    Serial.print("/");
    Serial.print(clock.year + 2000, DEC);
    Serial.println();

    delay(1000);
}

  • clock.getTime();: Retrieves the current time from the RTC module and updates the properties of the clock object with the current hour, minute, second, day, month, and year.
  • Serial.print(clock.hour, DEC);: Prints the current hour to the serial monitor.
  • Serial.print(":");: Prints a colon (:) to separate the hour and minute.
  • Serial.print(clock.minute, DEC);: Prints the current minute to the serial monitor.
  • Serial.print(":");: Prints a colon (:) to separate the minute and second.
  • Serial.print(clock.second, DEC);: Prints the current second to the serial monitor.
  • Serial.print(" ");: Prints two spaces to separate the time from the date.
  • Serial.print(clock.month, DEC);: Prints the current month to the serial monitor.
  • Serial.print("/");: Prints a forward slash (/) to separate the month and day.
  • Serial.print(clock.dayOfMonth, DEC);: Prints the current day of the month to the serial monitor.
  • Serial.print("/");: Prints a forward slash (/) to separate the day and year.
  • Serial.print(clock.year + 2000, DEC);: Prints the current year to the serial monitor. The clock.year value is offset by 2000 because the DS1307 typically returns the year as a number from 0 to 99 (representing 2000 to 2099).
  • Serial.println();: Prints a newline character, moving the cursor to the next line on the serial monitor.
  • delay(1000);: Pauses the loop for 1000 milliseconds (1 second) before repeating, resulting in the time being updated every second.

 

 

Code Summary

 

This code sets up an Arduino to interact with a DS1307 RTC module, allowing it to keep track of and display the current time and date via the serial monitor. Initially, you can set the time and date by uncommenting certain lines, uploading the code, and then commenting them out and re-uploading to ensure the time isn't reset each time the Arduino restarts. The loop function continually retrieves and displays the current time and date every second.

 

 

 

Practical Application: Creating a Simple Alarm Clock

 

Let's take the DS1307 RTC module and build a simple alarm clock. You can add a buzzer, LED, and an LCD display to show the current time and trigger the alarm at a set time. Here's an extended code snippet to incorporate an alarm feature:

 

Components Needed:

  1. Arduino Uno
  2. DS1307 RTC Module
  3. 16x2 Liquid Crystal Display (LCD)
  4. Buzzer
  5. Breadboard
  6. Jumper wires
  7. LED
  8. 220-ohm resistor for the LED

 

This is the complete breadboard circuit:

DS1307 RTC Clock with Alarm Function
This is the circuit I made for the DS1307 RTC Clock with an alarm function. Note that you can connect 2 devices to the A4 and A5 pins. In this case, the I2C LCD and DS1307 Tiny RTC modules are connected to the SDA and SCL pins through the breadboard.

 

 

DS1307 RTC Alarm Setup
My completed DS1307 RTC Clock with alarm setup

 

Learn more about I2C LCD

For detailed knowledge about I2C LCD, read this article:

Displaying Characters Using the I2C Liquid Crystal Display (LCD)

(This link opens in another window)

 

Learn more about Piezo Buzzer

Get more information on Piezo Buzzer in this article:

Exploring Piezo Buzzer Integration with Arduino: A Comprehensive Guide

(This link opens in another window)

 

 

Arduino Code for DS1307 RTC Module with Alarm Function

 

Here is the code for this application:



#include <Wire.h>
#include "DS1307.h"
#include <LiquidCrystal_I2C.h> //enables us to use the lcd functions

int buzzer = 8; // Pin for the buzzer
int led=9;
int ampm;
int hourNow=0;
int minuteNow=0;
int alarmHour =14; //set alarm at 2:00 PM
int alarmMinute =0;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 
DS1307 clock;//define a object of DS1307 class

// Make a custom bell character:

byte Bell[] = {
  B00100,
  B01110,
  B01110,
  B01110,
  B11111,
  B00000,
  B00100,
  B00000
};

void setup() {
    //Serial.begin(9600);
    lcd.begin(16,2);
    pinMode(buzzer,OUTPUT);
    pinMode(led,OUTPUT);
    clock.begin();

    //uncomment the next 4 lines to set a new date and time, then upload
    //clock.fillByYMD(2024, 6, 25); //June 25,2024 (year, month, date)
    //clock.fillByHMS(13, 55, 30); //1:55 PM 30 13:55:30 (hh:mm:ss)24-hr format
    //clock.fillDayOfWeek(TUE);//Tuesday
    //clock.setTime();//write time to the RTC chip

    //comment the 4 lines again then upload so that the date and time will not be reset
    
    // Create new character:
    lcd.createChar(0, Bell);
     
}

void loop() {
  
 lcd.clear();//Clear the lcd screen
 clock.getTime();

 //Name of the day
 String s_day;
 switch (clock.dayOfWeek) { // Friendly printout the weekday
     case MON:
         s_day="MON";
         break;
     case TUE:
         s_day="TUE";
         break;
     case WED:
         s_day="WED";
         break;
     case THU:
         s_day="THU";
         break;
     case FRI:
         s_day="FRI";
         break;
     case SAT:
         s_day="SAT";
         break;
     case SUN:
         s_day="SUN";
         break;
    }


  //Name of the month
  String s_month;
  switch (clock.month)
  {
    case 1:
      s_month="JAN ";
      break;
    case 2:
      s_month="FEB ";
      break;
    case 3:
      s_month="MAR ";
      break;
    case 4:
      s_month="APR ";
      break;
    case 5:
      s_month="MAY ";
      break;
    case 6:
      s_month="JUN ";
      break;
    case 7:
      s_month="JUL ";
      break;
    case 8:
      s_month="AUG ";
      break;
    case 9:
      s_month="SEP ";
      break;
    case 10:
      s_month="OCT ";
      break;
    case 11:
      s_month="NOV ";
      break;
    case 12:
      s_month="DEC ";
      break;
  }

    //alarm
    hourNow=clock.hour;
    minuteNow=clock.minute;
    if (hourNow == alarmHour && minuteNow == alarmMinute) {
      tone(buzzer,1300);
      digitalWrite(led, HIGH);
    } else {
      noTone(buzzer);
      digitalWrite(led, LOW);
    }


  //display date       
  lcd.setCursor(1,0);
  lcd.print(s_day);
  lcd.print(" ");
  lcd.print(s_month);

  if (clock.dayOfMonth<=9){
      lcd.print("0");
      lcd.print(clock.dayOfMonth,DEC);
    }
  else{
    lcd.print(clock.dayOfMonth, DEC);
  }
  
  lcd.print(" ");
  lcd.print(clock.year + 2000);
  
          
  // display time
  lcd.setCursor(2,1);

  
  //Time AM/PM
  if (clock.hour>=12){
    ampm = 1;
    clock.hour = clock.hour-12;
     if (clock.hour== 0) {
        clock.hour = 12; // Day 12 PM
     }
  if (clock.hour<=9){
    lcd.print("0");
    lcd.print(clock.hour);
    lcd.print(":");
  }
  else {
    lcd.print(clock.hour);
    lcd.print(":");}
  }
  else {
    ampm = 0;
    if(clock.hour==0){
      clock.hour=12; // Night 12 AM
    }
    if (clock.hour<=9){
      lcd.print("0");
      lcd.print(clock.hour);
      lcd.print(":");
    }
    else {
      lcd.print(clock.hour);
      lcd.print(":");}
    }
    if (clock.minute<=9){
      lcd.print("0");
      lcd.print(clock.minute);
      lcd.print(":");
    }
    else {
      lcd.print(clock.minute);
      lcd.print(":");}
    if (clock.second<=9){
      lcd.print("0");
      lcd.print(clock.second);
      lcd.print(" ");
    }
    else {
      lcd.print(clock.second);
      lcd.print(" ");
    }
  
    //AM/PM
    if (ampm==1){
      lcd.print("PM");
    }else{
      lcd.print("AM"); }

    
    //display bell character
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); 



delay(1000);
}

 

This is my demonstration of this application:

 

 

Step-by-Step Explanation of the Code

 

Here's a step-by-step explanation of the provided Arduino code that uses the DS1307 RTC module and an I2C LCD display to create an alarm clock with a buzzer and LED:

 

Including Libraries and Defining Objects


#include <Wire.h>
#include "DS1307.h"
#include <LiquidCrystal_I2C.h> // Enables us to use the LCD functions

int buzzer = 8; // Pin for the buzzer
int led = 9; // Pin for the LED
int ampm;
int hourNow = 0;
int minuteNow = 0;
int alarmHour = 14; // Set alarm at 2:00 PM
int alarmMinute = 0;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 
DS1307 clock; // Define an object of DS1307 class

// Make a custom bell character
byte Bell[] = {
  B00100,
  B01110,
  B01110,
  B01110,
  B11111,
  B00000,
  B00100,
  B00000
};

 

  • #include <Wire.h>: Includes the Wire library for I2C communication.
  • #include "DS1307.h": Includes the DS1307 library for RTC functions.
  • #include <LiquidCrystal_I2C.h>: Includes the LiquidCrystal_I2C library for using I2C LCD functions.
  • Variable Declarations: Defines pins for the buzzer and LED, as well as variables for handling the time and alarm.
  • LiquidCrystal_I2C lcd(...);: Creates an object for the I2C LCD with specified address and pin configuration.
  • DS1307 clock;: Creates an object for the DS1307 RTC module.
  • Custom Bell Character: Defines a custom bell character for the LCD.

 

You may download all the required libraries at the end of this article.

 

 

Setup Function


void setup() {
    // Serial.begin(9600);
    lcd.begin(16, 2);
    pinMode(buzzer, OUTPUT);
    pinMode(led, OUTPUT);
    clock.begin();

    // Uncomment the next 4 lines to set a new date and time, then upload
    // clock.fillByYMD(2024, 6, 25); // June 25, 2024 (year, month, date)
    // clock.fillByHMS(13, 55, 30); // 1:55 PM (13:55:30) in 24-hr format
    // clock.fillDayOfWeek(TUE); // Tuesday
    // clock.setTime(); // Write time to the RTC chip

    // Comment the 4 lines again then upload so that the date and time will not be reset
    
    // Create new character
    lcd.createChar(0, Bell);
}

 

  • lcd.begin(16, 2);: Initializes the LCD with 16 columns and 2 rows.
  • pinMode(buzzer, OUTPUT); and pinMode(led, OUTPUT);: Sets the buzzer and LED pins as output.
  • clock.begin();: Initializes the RTC module.
  • Setting Time (Commented Out): Provides code to set the time on the RTC module, which should be uncommented, uploaded, then commented again.
  • lcd.createChar(0, Bell);: Creates a custom character (bell) for the LCD.

 

 

Loop Function

This function runs repeatedly after the setup() function is executed. Its main tasks are to update the LCD display with the current date and time, check for an alarm condition, and sound a buzzer and light an LED if the alarm time is reached.

 

Here's a step-by-step explanation:

 

Clear the LCD Screen


lcd.clear(); // Clear the LCD screen

This line clears any previous content on the LCD screen.

 

Get the Current Time from the RTC


clock.getTime();

This method retrieves the current time from the DS1307 RTC module and updates the clock object with the new time.

 

Get the Day of the Week


String s_day;
switch (clock.dayOfWeek) { // Friendly printout of the weekday
    case MON: s_day = "MON"; break;
    case TUE: s_day = "TUE"; break;
    case WED: s_day = "WED"; break;
    case THU: s_day = "THU"; break;
    case FRI: s_day = "FRI"; break;
    case SAT: s_day = "SAT"; break;
    case SUN: s_day = "SUN"; break;
}

This block converts the numerical value of clock.dayOfWeek to a string representing the name of the day (e.g., MON, TUE).

 

Get the Month


String s_month;
switch (clock.month) {
    case 1: s_month = "JAN "; break;
    case 2: s_month = "FEB "; break;
    case 3: s_month = "MAR "; break;
    case 4: s_month = "APR "; break;
    case 5: s_month = "MAY "; break;
    case 6: s_month = "JUN "; break;
    case 7: s_month = "JUL "; break;
    case 8: s_month = "AUG "; break;
    case 9: s_month = "SEP "; break;
    case 10: s_month = "OCT "; break;
    case 11: s_month = "NOV "; break;
    case 12: s_month = "DEC "; break;
}

This block converts the numerical value of clock.month to a string representing the name of the month (e.g., JAN, FEB).

 

Check and Handle Alarm Condition


hourNow = clock.hour;
minuteNow = clock.minute;
if (hourNow == alarmHour && minuteNow == alarmMinute) {
    tone(buzzer, 1300);
    digitalWrite(led, HIGH);
} else {
    noTone(buzzer);
    digitalWrite(led, LOW);
}

  • hourNow and minuteNow store the current hour and minute.
  • If the current time matches the alarm time (alarmHour and alarmMinute), the buzzer sounds, and the LED turns on.
  • Otherwise, the buzzer and LED are turned off.

 

Display the Date


lcd.setCursor(1, 0);
lcd.print(s_day);
lcd.print(" ");
lcd.print(s_month);
if (clock.dayOfMonth <= 9) {
    lcd.print("0");
    lcd.print(clock.dayOfMonth, DEC);
} else {
    lcd.print(clock.dayOfMonth, DEC);
}
lcd.print(" ");
lcd.print(clock.year + 2000);

  • The cursor is positioned to the first row (0) and second column (1) of the LCD.
  • The day of the week (s_day), month (s_month), day of the month, and year are printed to the LCD.
  • If the day of the month is a single digit (less than or equal to 9), a leading zero is added for formatting.

 

 

Display the Time


lcd.setCursor(2, 1);
// Time AM/PM
if (clock.hour >= 12) {
    ampm = 1;
    clock.hour = clock.hour - 12;
    if (clock.hour == 0) {
        clock.hour = 12; // 12 PM
    }
    if (clock.hour <= 9) {
        lcd.print("0");
        lcd.print(clock.hour);
        lcd.print(":");
    } else {
        lcd.print(clock.hour);
        lcd.print(":");
    }
} else {
    ampm = 0;
    if (clock.hour == 0) {
        clock.hour = 12; // 12 AM
    }
    if (clock.hour <= 9) {
        lcd.print("0");
        lcd.print(clock.hour);
        lcd.print(":");
    } else {
        lcd.print(clock.hour);
        lcd.print(":");
    }
}
if (clock.minute <= 9) {
    lcd.print("0");
    lcd.print(clock.minute);
    lcd.print(":");
} else {
    lcd.print(clock.minute);
    lcd.print(":");
}
if (clock.second <= 9) {
    lcd.print("0");
    lcd.print(clock.second);
    lcd.print(" ");
} else {
    lcd.print(clock.second);
    lcd.print(" ");
}

  • The cursor is positioned to the second row (1) and third column (2) of the LCD.
  • The current hour, minute, and second are printed to the LCD.
  • The time is converted from 24-hour format to 12-hour format with AM/PM indicators.
  • Leading zeros are added for single-digit hours, minutes, and seconds.

 

 

Display AM/PM


if (ampm == 1) {
    lcd.print("PM");
} else {
    lcd.print("AM");
}

Prints "AM" or "PM" based on the value of ampm.

 

 

Display Custom Bell Character


lcd.setCursor(15, 1);
lcd.write(byte(0));

  • The cursor is positioned to the second row (1) and sixteenth column (15) of the LCD.
  • The custom bell character is displayed.

 

Delay Before Next Loop Iteration


delay(1000);

The loop pauses for 1 second before repeating, ensuring the display updates once per second.

 

 

Code Summary

 

This code displays the current date and time on an I2C LCD, checking for an alarm condition every second. When the alarm time is reached, a buzzer sounds, and an LED lights up. The date and time are displayed in a user-friendly format, with the day of the week and month names converted from numerical values to strings.

 

 

 

Conclusion

 

Using the DS1307 RTC module with Arduino is a straightforward process that adds accurate timekeeping capabilities to your projects. This guide has provided you with the basic setup, code examples, and a practical application to get you started. Whether you're a beginner or an experienced maker, the DS1307 RTC module is a valuable addition to your toolkit.

 

For those looking to explore further, consider comparing the DS1307 with the DS1302 to determine which module best fits your needs. Happy making!

 

Downloads:

 

 

 

 

No comments

Leave your comment

In reply to Some User

Arduino Intro

Arduino Intro is dedicated to providing high-quality, beginner-friendly resources for learning Arduino and electronics. Our mission is to make technology accessible to everyone through comprehensive tutorials, hands-on projects, and a supportive community.