Picking the right Real-Time Clock (RTC) module is crucial when building time-sensitive Arduino projects. You’ve got many options – DS1302, DS1307, DS3231, DS3232, and more, but if you want precision, affordability, and reliability, the DS3231 stands out.
In this guide, I’ll break down everything you need to know when working with Arduino and DS3231. You’ll learn:
- How to set up the DS3231 with Arduino.
- How to read time, date, and temperature data.
- How to set an alarm on DS3231 RTC.
- Bonus project: Display everything on an OLED screen.
By the end of this tutorial, you’ll see why the DS3231 is a favorite among makers. Let’s dive in!
Table of Contents
DS3231 RTC Chip Overview and Features
DS3231 is very accurate, budget-friendly, and has all the features a typical clock should have. It has a fast (400kHz) I2C Interface, which makes it very adaptable to any project. Let’s take a look at some key features of the DS3231 I2C Chip.
Key Features of the DS3231 RTC
- Real-Time Clock counts Seconds, Minutes, and Hours.
- Two time-of-day alarms.
- Calculates date of the month, month, day of the week, year, and leap year up to 2100.
- Digital temperature sensor output with ±3 °C accuracy.
- Programmable square-wave output signal.
- Fast (400kHz) I2C interface.
- Backup battery option for continuous timekeeping.
DS3231 is a very popular IC that uses a temperature-compensated crystal oscillator (TCXO) to keep track of time. TCXO makes it very accurate, ±2ppm at an operating temperature of 0 °C to +40 °C and ±3.5ppm at -40 °C to +85 °C range. This translates to a drift of roughly 1.05 to 1.83 minutes per year.
It has a logic unit inside that calculates the seconds, minutes, hours, days, dates, months, and years. It can automatically adjust dates for months with fewer than 31 days, including corrections for the leap year. The leap-year calculation is valid up to 2100.
The clock can operate in the 24-hour or 12-hour format with an AM/PM indicator. There are also options to set two different alarms. Alarms can be programmed to repeat every second, minute, hour, day, or date.
The DS3231 has 19 8-bit registers in its main timekeeping and control register map, ranging from addresses 0x00 to 0x12. These registers hold essential data such as the current time and date, alarm settings, temperature readings, and various control and status flags. For a detailed breakdown of each register and its functionality, refer to the official DS3231 datasheet.
The DS3231 also has a 7-byte user buffer. You can use them for any purpose relevant to your project. For example, you can store additional software-managed alarms by saving their time values in this buffer and checking them in your Arduino code. Or, you can use it to store time zone offsets (like +5:30 and -8:00), to display time in multiple zones based on a single real-time clock.
You can access the clock registers using an I2C bidirectional bus. It supports fast mode communication at up to 400 kHz. This high-speed interface helps quick reading and writing of time/date registers, which makes it ideal to use in real-time systems.
A programmable square-wave output is available at the SQW/OUT pin. It can be used to synchronize external devices such as digital clocks and timers. Also, you can use it to replace the Arduino delay() function, with this real-time clock frequency for more accuracy.
It has an additional connection for a battery backup power supply. So that when the primary power source is unavailable, the clock can continue to run on the battery. So once you set the clock, you don’t have to worry about anything.
DS3231 Chip Pinout
The IC comes with a 16-pin SO (Small Outline) package, but only 8 of those pins are active and functionally used. The pin layout of the IC is shown below.

You can integrate the DS3231 Chip directly into your project, but for this tutorial, I will use a DS3231 module.
DS3231 RTC Module Overview
The DS3231 module makes it easy to integrate the IC into your Arduino projects. It comes with a DS3231 chip, an AT24C32 EEPROM, and a battery holder at the back.
You can access the clock registers and EEPROM using the same I2C bus. The default address for the clock registers is 0x68, and the EEPROM usually uses 0x57.
AT24C32 EEPROM in DS3231 Module
The DS3231 module typically has an AT24C32 EEPROM IC on the board. AT24C32 has 32 kilobits (4KB) of non-volatile memory, which means it retains data even when power is lost.
You can use this memory to store user preferences or settings, such as custom alarm times, time zone offsets, or display settings, or you can use it to save time-stamped sensor data, such as temperature, humidity, etc.
A typical outlook of a DS3231 module is given below.

Onboard Battery Holder (CR2032)
The module comes with a battery holder that can hold a CR2032 coin cell. As the RTC consumes very little power to operate (~1 µA), a 3V 220 mAh battery can last approximately 5–10 years.

DS3231 RTC Module Pinout
As you can see below, the module has 6 pins on the left to connect to the Arduino. On the right side, it has 4 pins to connect to any I2C device in series.

A brief description of each pin is given below.
32K | ➟ | Output a stable 32.768 kHz square wave. |
INT/SQW | ➟ | Configurable square-wave output or interrupt signal. |
SCL | ➟ | Serial Clock Line for I2C communication. |
SDA | ➟ | Serial data Line for I2C communication |
VCC | ➟ | Power input (2.3V to 5.5V). |
GND | ➟ | Ground connection. |
How to Connect DS3231 RTC to Arduino
Connect VCC to the Arduino’s 5V pin and GND to GND. Then, connect the SCL and SDA pins of the DS3231 to the corresponding SCL and SDA pins on the Arduino. Also, place a CR2032 battery at the back of the module.
Note: The position of SCL and SDA varies between Arduino boards. On an Arduino UNO R3, they are located near the AREF pin and are also labeled as A5 (SCL) and A4 (SDA). Make sure to connect them correctly based on your board.

In this tutorial, we’ll focus only on the clock functionality, so the 32K and INT/SQW pins won’t be used.
Arduino Code for DS3231 Real-Time Clock
Working with a DS3231 RTC involves handling several tasks, such as reading and writing data via the I2C protocol, converting binary values into human-readable time and date formats, and managing calendar-related operations.
There are many Arduino libraries available to make the process easier, such as uRTCLib, Adafruit RTCLib, DS3232RTC, and the Rtc library by Makuna. In this tutorial, we’ll use uRTCLib because it’s lightweight, easy to use, and ideal for basic timekeeping projects.
Let’s start by installing the library.
Installing the uRTCLib Library
To install the uRTCLib library, open the Arduino IDE and go to Tools > Manage Libraries. Now type uRTCLib into the search bar, and you’ll see results similar to the image below.

Click the Install button next to the library.
Once the installation is complete, we’ll take a quick look at the key functions provided by the uRTCLib library.
Important uRTCLib Functions
Initialize an RTC object
The default I2C address for the RTC is 0x68, but you can confirm the exact address using an Arduino I2C scanner.
uRTCLib myRTC(0x68); // Initialize an RTC Object with address 0x68.
URTCLIB_WIRE.begin(); // Start I2C communication (in setup).
The function to set the date and time
The set()
function is used to set the current date and time on the RTC module. The following example shows how to use this function to set the RTC with a specific date and time.
myRTC.set(sec, min, hr, dayOfWeek, day, month, year);
myRTC.set(0, 30, 14, 5, 13, 03, 25); // Sets 14:30:00, 13 March 2025.
Reading time and date
The following functions will return the hour, minute, second, date, month, year, and day of the week.
myRTC.hour(); // returns hours (24h format)
myRTC.minute(); // returns minutes
myRTC.second(); // returns seconds
myRTC.day(); // returns day of month
myRTC.month(); // returns month (1-12)
myRTC.year(); // returns last 2 digits of year (e.g., 24 for 2024)
myRTC.dayOfWeek(); // Returns 1-7 (1 = Sunday)
myRTC.refresh(); // Refresh RTC data (call before reading)
Note that if dayOfWeek()
returns 1, it represents Sunday; a return value of 2 indicates Monday, and so on through the week.
Use the refresh()
function to update the clock data before reading it.
Reading temperature
The function below returns the temperature in hundredths of °C, so divide the result by 100 to get the actual value.
myRTC.temp();
Use it like myRTC.temp() / 100.0 to get a result like 25.00 °C.
DS3231 Arduino Code Examples
I have covered almost all the functions available in the uRTCLib. Now, I will show some basic operations, such as setting the clock and reading the clock data.
Set the Date and Time on DS3231 RTC
The code below will set the time in the RTC using the set()
function.
#include "uRTCLib.h"
uRTCLib myRTC(0x68);
void setup() {
URTCLIB_WIRE.begin();
myRTC.set(0, 30, 14, 5, 13, 03, 25); // Sets 14:30:00, 13 March 2025.
}
void loop() {}
If you are using the backup battery at the back of the module, you only need to set the clock once, and it will run for ~ 5-7 years.
Reading Time, Date, and Temperature via Serial Monitor
The Arduino code below prints the DS3231 RTC data to the Serial Monitor.
#include "Arduino.h"
#include "uRTCLib.h"
uRTCLib myRTC(0x68);
const char* dayName[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup() {
Serial.begin(9600);
delay (2000);
Serial.println("Serial OK");
URTCLIB_WIRE.begin();
}
void loop() {
myRTC.refresh();
Serial.print("Time: ");
Serial.print(myRTC.hour());
Serial.print(':');
Serial.print(myRTC.minute());
Serial.print(':');
Serial.print(myRTC.second());
Serial.print(" | Date: ");
Serial.print(20);
Serial.print(myRTC.year());
Serial.print('/');
Serial.print(myRTC.month());
Serial.print('/');
Serial.print(myRTC.day());
Serial.print(" | Day: ");
Serial.print(dayName[myRTC.dayOfWeek() - 1]);
Serial.print(" | Temp: ");
Serial.print(myRTC.temp() / 100);
Serial.print("\xC2\xB0"); // degrees character
Serial.println("C");
delay(1000);
}
Upload the code to your Arduino board and open the Serial Monitor to view the clock data.
Display DS3231 Time & Temperature on OLED with Arduino
In this section, I’ll show you how to build a simple digital clock using the DS3231 RTC module and an I2C OLED display.
An I2C OLED display is a great choice because it requires only two data pins, uses little memory, and provides a crisp 128×64 pixel interface – perfect for a clean digital clock UI.
If you haven’t used an OLED display before, check our guide on Arduino OLED Display. You can also use an LCD display by following our Arduino LCD Display Tutorial.
Wiring DS3231 and OLED to Arduino
Connecting an OLED display to the circuit is very simple. The OLED module has four pins: VCC, GND, SCL, and SDA. Connect VCC to the 5V power line, GND to the ground line, and SCL/SDA to the corresponding I2C lines on the Arduino.

Arduino Code to Display Clock on OLED
The Arduino code below will display the DS3231 RTC data on the OLED using a simple interface.
#include <U8g2lib.h>
#include <Wire.h>
#include <uRTCLib.h>
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64
#define DISPLAY_TYPE U8G2_R0
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(DISPLAY_TYPE, U8X8_PIN_NONE);
uRTCLib myRTC(0x68);
const char* dayName[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup() {
Serial.begin(9600);
u8g2.begin();
URTCLIB_WIRE.begin();
}
void loop() {
myRTC.refresh();
u8g2.clearBuffer();
u8g2.drawLine(0, 0, 127, 0);
u8g2.drawLine(0, 63, 127, 63);
u8g2.drawLine(0, 0, 0, 63);
u8g2.drawLine(127, 0, 127, 63);
u8g2.setFont(u8g2_font_logisoso24_tf);
char timeStr[5];
sprintf(timeStr, "%02d:%02d", myRTC.hour(), myRTC.minute());
u8g2.drawStr(12, 44, timeStr);
u8g2.setFont(u8g2_font_inb16_mf);
char secStr[2];
sprintf(secStr, "%02d", myRTC.second());
u8g2.drawStr(88, 44, secStr);
u8g2.setFont(u8g2_font_7x14B_tf);
u8g2.setCursor(4, 13);
u8g2.print(dayName[myRTC.dayOfWeek() - 1]);
char tempStr[5];
sprintf(tempStr, "%02d\xB0""C", myRTC.temp() / 100);
u8g2.drawStr(94, 13, tempStr);
u8g2.setFont(u8g2_font_7x14B_tf);
char dateStr[11];
sprintf(dateStr, "%02d/%02d/20%02d", myRTC.day(), myRTC.month(), myRTC.year());
u8g2.drawStr(28, 60, dateStr);
u8g2.sendBuffer();
delay(1000);
}
Upload the above code, and you will see a display like this.

Conclusion
In this tutorial, you learned how to use the DS3231 RTC module with Arduino and display the real-time clock data on an OLED screen using a simple digital clock UI. We covered everything from wiring and setup to printing accurate time, date, day, and temperature.
Now that you’ve built a basic digital clock, let’s take it further. In the next part, we’ll use a 128×128 OLED display to create an analog clock interface—a more visually engaging way to show the time. Stay tuned!
You’ll also learn how to use the DS3231 as a precision time source instead of relying on the Arduino’s internal clock.
Stay tuned for a more advanced and visually engaging project!