Build an RTC Arduino ESP (DS1307 & DS3231)

Posted on

What is RTC?

Real-time clocks (RTCs) are integrated circuits that keep track of the current date and time even when there is a power outage. There are several types of RTCs available in the market, but among the most popular are the DS1302, DS1307, and DS3231. In this article we will learn how to read RTC Arduino ESP DS1307 and DS3231)

Dallas Semiconductor (now a part of Maxim Integrated) is the original manufacturer of the DS1302, DS1307, and DS3231 real-time clock (RTC) integrated circuits. These RTCs are widely used in various electronic projects and are available from many electronic component distributors.

Comparison Table of DS1302, DS1307 and DS3231

here’s a more in-depth comparison table between the DS1302, DS1307, and DS3231 RTCs:

FeatureDS1302DS1307DS3231
Pin ConfigurationDS1302 DS1307 DS3231 RTC Comparison TableDS1302 DS1307 DS3231 RTC Comparison TableDS1302 DS1307 DS3231 RTC Comparison Table
InterfaceSerialI2CI2C
Oscillator32.768kHz32.768kHzTemperature-compensated crystal oscillator (TCXO)
Accuracy±2.5% at 25°C±2.0% at 25°C±2ppm
Operating Voltage2.0V to 5.5V2.0V to 5.5V2.3V to 5.5V
Operating Temperature Range-40°C to +85°C-55°C to +125°C-40°C to +85°C
Battery-backed SRAMNo56 bytesNo
Pin Count888
Date/Time Registers878
Trickle-charge featureYesNoNo
CostLowMediumHigh

Note: The above table is a general comparison and the actual specifications may vary depending on the manufacturer.

As can be seen from the table, the DS3231 offers the highest accuracy. It also has a wider operating voltage range compared to the DS1302 and DS1307. On the other hand, the DS1307 offers battery-backed SRAM, which can be useful for storing data during power outages. The DS1302 has the advantage of being low-cost and having a trickle-charge feature, which allows it to be powered by a small battery even when the main power supply is off.

How it works?

An RTC chip will continue to count time as long as it is supplied with a voltage source. 2 voltage sources can turn on this chip, VCC and Vbat. VCC is the voltage that comes from the main circuit, while Vbat is the voltage that comes from the backup battery (3.3V)

When the chip is given a VCC voltage, the chip will automatically select the VCC voltage to run the system, but when the VCC is disconnected or goes out, the chip will automatically switch to the backup battery voltage. The backup battery is usually a flat battery such as the CR2032 type which has a voltage of 3V.

As long as electrical voltage is available, this RTC chip will continue to output time data sent via the I2C protocol pins (SDA and SCL). A microcontroller such as the Arduino Uno board, will retrieve this data via I2C communication as well.

RTC Module

When we use an RTC chip such as DS1302, DS1307, or DS3231, we need several other separate components such as a crystal, backup battery, resistors, and diodes.

Things like that will make things a bit troublesome if we want to develop fast hardware. Therefore, we can use the RTC module.

In the RTC module, all the components mentioned above are soldered on one PCB board, so using it is much easier and faster, you can search on Google for a variant RTC Module:

Build an RTC Arduino ESP (DS1307 & DS3231)

RTC Library for Arduino

To make it easier to read data from the RTC using the Arduino platform, we need a library. We will use the RTClib library by Adafruit.

For installation instructions for this library, I have created a separate article which you can read here.

Wiring

a. DS1307 to Arduino Uno

Build an RTC Arduino ESP (DS1307 & DS3231)

b. DS3231 to Arduino Uno

Build an RTC Arduino ESP (DS1307 & DS3231)

c. DS3231 NodeMCU ESP8266

Build an RTC Arduino ESP (DS1307 & DS3231)

The Code

Read RTC Data

Now, we will try to read data from RTC. Data includes day, date, month, year, hour, minute and second.

#include "RTClib.h"

RTC_DS1307 rtc;
// RTC_DS3231 rtc;


char daysOfTheWeek[7][7] = {"Ahad", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"};
char Month [13][10] = {" ", "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"};

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


  if (! rtc.begin()) {
    Serial.println("No RTC Detected!");
    Serial.flush();
    abort();
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC not Running!");
  }
}

void loop () {
  DateTime now = rtc.now();

  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 
  Serial.print(", ");
  Serial.print(now.day(), DEC);     
  Serial.print(' ');
  Serial.print(Month[now.month()]); 
  Serial.print(' ');
  Serial.print(now.year(), DEC);    
  Serial.print(", ");


  Serial.print(now.hour(), DEC);    
  Serial.print(':');
  Serial.print(now.minute(), DEC);  
  Serial.print(':');
  Serial.print(now.second(), DEC);  
  Serial.println();

  delay(1000);
}

The Result

After the program is uploaded, open the Arduino IDE Monitor series and you will see data that appears as follows:

Build an RTC Arduino ESP (DS1307 & DS3231)

If you get this error, you must install the BusIO library by Adafruit. For step install, please read Adafruit I2CDevice h No such file or directory.

If The time is not Correct, let’s Set the Time!

Manual Set

If you want the time on the RTC to be the same on the computer, copy this command and paste it into the setup() function:

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

If you want the RTC time to be set manually, use the following command in setup():

// Example January 21, 2014 at 03.00:
rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

Using Serial Monitor

Now we will create a program with which we can set the RTC manually.

Pay attention to the command rtc.adjust(DateTime(year, month, date, hour, minute, second));, this will make the program will set the time at the same time.

For example, if we only want to change the date or time, how do we do that?

Here I include the complete program. This program will display RTC data on the Serial Monitor

To change the data, send the following characters to the serial monitor:

  • TG to change the Date
  • BL to change the Moon
  • TH for changing the Year
  • JM to change Hours
  • MT to change Minutes
  • DT to change Seconds
/*
   www.chippiko.com

   This program will display RTC data on Serial Monitor

   To change the data, send the following characters to the serial monitor:
    - TG to change Date
    - BL to change the Moon
    - TH for changing Year
    - JM to change Hours
    - MT to change Minutes
    - DT to change Seconds
*/

#include "RTClib.h"

RTC_DS1307 rtc;
// RTC_DS3231 rtc;

char daysOfTheWeek[7][10] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
char Month [13][10] = {" ", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
String read_string = " ";
int read_int = 0;

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


  if (! rtc.begin()) {
    Serial.println("RTC Not Found");
    Serial.flush();
    abort();
  }

  if (rtc.lostPower()) {
    Serial.println("RTC is losing power, let's set the time!");
  }
}

void loop () {
  readRTC();
  setRTC();
  delay(1000);
}

void readRTC()
{
  DateTime now = rtc.now();

  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 
  Serial.print(", ");
  Serial.print(now.day(), DEC);    
  Serial.print(' ');
  Serial.print(Month[now.month()]);
  Serial.print(' ');
  Serial.print(now.year(), DEC);  
  Serial.print(", ");
  Serial.print(now.hour(), DEC); 
  Serial.print(':');
  Serial.print(now.minute(), DEC);  
  Serial.print(':');
  Serial.print(now.second(), DEC);  
  Serial.println('\n');
}
void setRTC() {
  DateTime now = rtc.now();

  while (Serial.available() > 0) {

    read_string = Serial.readStringUntil('\n');
    read_string.trim();
    delay(100);

    // The day cannot be changed because it will change itself according to the date
    
    if (read_string == "TG") {
      Serial.print("Insert the date: ");

      //Wait a moment for new data to be sent
      while (!Serial.available()) {}

      read_int = Serial.parseInt();
      Serial.println(read_int);

      rtc.adjust(DateTime(now.year(), now.month(), read_int, now.hour(), now.minute(), now.second()));
    }

   
    if (read_string == "BL") {
      Serial.print("Insert month: ");

      //Wait a moment for new data to be sent
      while (!Serial.available()) {}

      read_int = Serial.parseInt();
      Serial.println(read_int);

      rtc.adjust(DateTime(now.year(), read_int, now.day(), now.hour(), now.minute(), now.second()));
    }

    
    if (read_string == "TH") {
      Serial.print("Insert Year: ");

      //Wait a moment for new data to be sent
      while (!Serial.available()) {}

      read_int = Serial.parseInt();
      Serial.println(read_int);

      rtc.adjust(DateTime(read_int, now.month(), now.day(), now.hour(), now.minute(), now.second()));
    }

    
    if (read_string == "JM") {
      Serial.print("Insert hour: ");

      //Wait a moment for new data to be sent
      while (!Serial.available()) {}

      read_int = Serial.parseInt();
      Serial.println(read_int);

      rtc.adjust(DateTime(now.year(), now.month(), now.day(), read_int, now.minute(), now.second()));
    }

    //Jika menit
    if (read_string == "MT") {
      Serial.print("Insert minute: ");

      //Wait a moment for new data to be sent
      while (!Serial.available()) {}

      read_int = Serial.parseInt();
      Serial.println(read_int);

      rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), read_int, now.second()));
    }

    
    if (read_string == "DT") {
      Serial.print("Insert second: ");

      //Wait a moment for new data to be sent
      while (!Serial.available()) {}

      read_int = Serial.parseInt();
      Serial.println(read_int);

      rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), read_int));
    }
  }
}

Displays RTC in AM/PM Format

Now, let’s learn how to display the time format in 12 hours i.e. AM and PM. By default, the program above will display the time in a 24-hour format such as:

  • 9.14
  • 14.20
  • 18.30 

With 12 hour format, the time displayed is:

  • 9.14 AM
  • 2.20 PM 
  • 6.30 PM

The basic commands are:

(h > 12) ? h – 12 : ((h == 0) ? 12 : h), DEC
and 
(h < 12) ? ” AM” : ” PM”

Here is the code:

#include "RTClib.h"

RTC_DS1307 rtc;
// RTC_DS3231 rtc;

char daysOfTheWeek[7][7] = {"Ahad", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"};
char Month [13][10] = {" ", "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"};

int h = 0;

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


  if (! rtc.begin()) {
    Serial.println("Tidak ada RTC");
    Serial.flush();
    abort();
  }
}

void loop () {
  DateTime now = rtc.now();
  h = now.hour();
  
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); // Menampilkan Hari
  Serial.print(", ");
  Serial.print(now.day(), DEC);     // Menampilkan tanggga
  Serial.print(' ');
  Serial.print(Month[now.month()]); // Menampilkan bulan
  Serial.print(' ');
  Serial.print(now.year(), DEC);    // Menampilkan tahun
  Serial.print(", ");


  Serial.print((h > 12) ? h - 12 : ((h == 0) ? 12 : h), DEC);    // Menampilkan jam
  Serial.print(':');
  Serial.print(now.minute(), DEC);  // Menampilkan menit
  Serial.print(':');
  Serial.print(now.second(), DEC);  // Menampilkan detik
  Serial.print((h < 12) ? " AM" : " PM");
  Serial.println('n');

  delay(1000);
}

The results displayed are as follows:

Build an RTC Arduino ESP (DS1307 & DS3231)

Now, open the serial monitor on Arduino IDE. Please follow the instructions. Done. I hope this Build an RTC Arduino ESP (DS1307 & DS3231) article is useful.