Arduino Nano Digital Clock Using DS3231 RTC and TM1637 4-Digit Display – Circuit Diagram and Project Guide
Arduino Nano
Digital Clock
Interface the DS3231 Real Time Clock with a TM1637 4-digit 7-segment display using I2C and 2-wire communication. Beginner-friendly, battery-backed, and always accurate.
Project Overview & Components
This project builds an accurate, battery-backed digital clock using an Arduino Nano V3, a DS3231 RTC module (ZS-042), and a TM1637 4-digit 7-segment display. The DS3231 uses the I2C bus (SDA/SCL), while the TM1637 uses its own 2-wire protocol (CLK/DIO) — both are simple and beginner-friendly.
Arduino Nano V3
ATmega328P microcontroller — reads RTC data and drives the display
DS3231 RTC (ZS-042)
High-precision real-time clock with I2C interface and onboard TCXO
TM1637 Display
4-digit 7-segment module with built-in driver chip — only 2 wires needed
CR2032 Battery
Onboard backup battery — DS3231 keeps time even when power is off
Breadboard & Wires
Standard breadboard + jumper wires — no soldering required for prototyping
5V Power (USB)
Powered directly from Arduino 5V pin — no external supply needed
DS3231 I2C & TM1637 Protocol
DS3231 — I2C Protocol
The DS3231 communicates over I2C (Inter-Integrated Circuit) — a 2-wire bus using SDA (data) and SCL (clock). On the Arduino Nano, these map to A4 (SDA) and A5 (SCL). The DS3231's I2C address is 0x68. Multiple I2C devices can share the same bus, making this extremely versatile.
Why DS3231 over DS1307? The DS3231 includes a temperature-compensated crystal oscillator (TCXO) which gives accuracy to ±2ppm — roughly 1 minute drift per year. The DS1307 drifts significantly more, especially with temperature changes.
TM1637 — 2-Wire Protocol
The TM1637 uses its own proprietary 2-wire serial protocol (not standard I2C), controlled via any two GPIO pins. CLK is the clock line and DIO is the data line. The TM1637Display library handles all timing — you just call showNumberDecEx().
| Module | Protocol | Wires | Arduino Nano Pins | Notes |
|---|---|---|---|---|
| DS3231 RTC | I2C | SDA + SCL | A4 + A5 | Address 0x68 |
| TM1637 Display | 2-Wire (custom) | CLK + DIO | D11 + D10 | Any GPIO pins work |
Pin Assignment & Wiring Guide
DS3231 RTC → Arduino Nano
| DS3231 Pin | Arduino Nano Pin | Wire Colour | Function |
|---|---|---|---|
| VCC | 3.3V or 5V | 🔴 Red | Power |
| GND | GND | ⚫ Black | Ground |
| SDA | A4 | 🔵 Blue | I2C Data |
| SCL | A5 | 🟡 Yellow | I2C Clock |
TM1637 Display → Arduino Nano
| TM1637 Pin | Arduino Nano Pin | Wire Colour | Function |
|---|---|---|---|
| VCC | 5V | 🔴 Red | Power (5V only) |
| GND | GND | ⚫ Black | Ground |
| CLK | D11 | 🟠 Orange | Clock signal |
| DIO | D10 | 🟢 Green | Data signal |
The DS3231 ZS-042 module can run on 3.3V or 5V. The TM1637 display requires 5V. If you power the DS3231 from 5V, ensure the onboard charging circuit doesn't overcharge a non-rechargeable CR2032 battery — remove the 200Ω resistor + diode on the ZS-042 board if using a standard CR2032.
Wiring Diagram
Circuit diagram: DS3231 connects via I2C (A4/A5), TM1637 connects via 2-wire protocol (D10/D11). Both share the Arduino's GND bus.
How It Works — Step by Step
RTC Initialisation
Arduino calls rtc.begin() to detect the DS3231 on the I2C bus. If the RTC lost power (battery dead), it auto-sets the time from the compile timestamp.
Read Current Time
rtc.now() returns a DateTime object. now.hour() and now.minute() extract the values we need for display.
Format as HHMM
The time is packed into a single integer: hours × 100 + minutes. For example, 14:35 becomes the integer 1435.
Drive TM1637
showNumberDecEx(1435, 0b01000000, true) sends the time to the display. The 0b01000000 bitmask enables the colon between digits 2 and 3.
1-Second Update
delay(1000) waits one second before the loop repeats. The colon flash can be added by toggling the colon bit each second for a classic clock effect.
Battery Backup
If the Arduino loses power, the CR2032 battery keeps the DS3231 counting. When power returns, the clock is already correct — no resetting needed.
Full Arduino Code
The sketch uses three libraries: Wire.h (built-in I2C), RTClib.h (DS3231 driver), and TM1637Display.h (display driver). Install both non-built-in libraries via the Library Manager before uploading.
Library Manager → Install: "RTClib by Adafruit" and "TM1637 by Avishay Orpaz". Wire.h is built into the Arduino IDE.
/* * Arduino Nano Digital Clock — DS3231 RTC + TM1637 4-Digit Display * Reads real-time from DS3231 via I2C and shows HH:MM on TM1637. * Battery-backed: clock keeps time even when Arduino is powered off. * * Libraries required: * Wire.h — built-in (I2C) * RTClib.h — install via Library Manager (Adafruit RTClib) * TM1637Display — install via Library Manager (Avishay Orpaz) */ #include <Wire.h> #include <RTClib.h> #include <TM1637Display.h> // ── TM1637 Display pins ─────────────────────────────────────────── #define CLK_PIN 11 // Any digital pin works for TM1637 #define DIO_PIN 10 // ── Colon bitmask for showNumberDecEx() ─────────────────────────── #define COLON_ON 0b01000000 #define COLON_OFF 0b00000000 // ── Object declarations ──────────────────────────────────────────── RTC_DS3231 rtc; TM1637Display display(CLK_PIN, DIO_PIN); bool colonState = true; // Toggle for blinking colon effect void setup() { Serial.begin(9600); // ── Initialise DS3231 RTC ────────────────────────────────────── if (!rtc.begin()) { Serial.println("ERROR: DS3231 not found on I2C bus!"); Serial.println("Check SDA→A4, SCL→A5 connections."); while (1); // Halt } // Auto-set time if RTC lost power (first run or dead battery) if (rtc.lostPower()) { Serial.println("RTC lost power — setting time from compile timestamp"); rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } // ── Initialise TM1637 display ───────────────────────────────── display.setBrightness(0x0f); // Maximum brightness (0x00–0x0f) display.clear(); Serial.println("Digital Clock Ready!"); } void loop() { // ── Read current time from DS3231 ───────────────────────────── DateTime now = rtc.now(); int h = now.hour(); int m = now.minute(); int s = now.second(); // ── Pack into HHMM integer for TM1637 ──────────────────────── int displayTime = h * 100 + m; // ── Toggle colon each second for blinking effect ────────────── byte colonMask = colonState ? COLON_ON : COLON_OFF; colonState = !colonState; // ── Send to TM1637 ──────────────────────────────────────────── // showNumberDecEx(number, dots, leading_zeros, length, pos) // 0b01000000 = colon ON between digit 1 and 2 (positions 1&2) display.showNumberDecEx(displayTime, colonMask, true); // ── Serial debug output ─────────────────────────────────────── Serial.print(h < 10 ? "0" : ""); Serial.print(h); Serial.print(":"); Serial.print(m < 10 ? "0" : ""); Serial.print(m); Serial.print(":"); Serial.print(s < 10 ? "0" : ""); Serial.println(s); delay(1000); // Update every second }
Setting the time manually: Replace rtc.adjust(DateTime(F(__DATE__), F(__TIME__))) with a specific time, e.g. rtc.adjust(DateTime(2026, 4, 4, 14, 30, 0)) for 14:30:00 on April 4, 2026. Upload once, then comment out the line and re-upload to prevent time reset on every power cycle.
Step-by-Step Build Instructions
Install Libraries
Open Arduino IDE → Sketch → Include Library → Manage Libraries. Search for and install "RTClib" by Adafruit and "TM1637" by Avishay Orpaz. Wire.h is already included.
Wire the DS3231 RTC
Place the DS3231 on the breadboard. Connect: VCC→3.3V (or 5V), GND→GND, SDA→A4, SCL→A5. Verify the CR2032 battery is inserted in the module.
Wire the TM1637 Display
Connect: VCC→5V, GND→GND, CLK→D11, DIO→D10. The TM1637 module has its own driver IC so no current-limiting resistors are needed on CLK/DIO.
Check I2C Connectivity
Before uploading the clock sketch, optionally run an I2C Scanner sketch (available at arduino.cc) to confirm the DS3231 appears at address 0x68 in the Serial Monitor.
Upload the Sketch
Select Tools → Board → Arduino Nano, set the correct COM port, and upload. If using an older Nano clone, change the Processor to ATmega328P (Old Bootloader).
Verify in Serial Monitor
Open Serial Monitor at 9600 baud. You should see the time printing every second in HH:MM:SS format. The TM1637 display will show HH:MM with a blinking colon.
Set Accurate Time (Optional)
The lostPower() check sets time from your computer's compile timestamp, which may be off by upload delay. For exact time, use rtc.adjust(DateTime(2026, 4, 4, 14, 30, 0)), upload, then remove the line and re-upload.
Adjust Brightness
Change the argument in display.setBrightness() from 0x0f (max) down to 0x00 (min) to suit your ambient lighting. Values 0x04–0x08 are comfortable for indoor use.
Key Features
±2 ppm Accuracy
DS3231's temperature-compensated oscillator drifts less than 1 minute per year
Battery-Backed
CR2032 keeps time through power cuts — no re-setting required
I2C Bus Sharing
Add sensors (BME280, OLED displays) on the same SDA/SCL bus with no extra pins
Adjustable Brightness
8 brightness levels (0x00–0x07) on TM1637 — controllable in software
Low Power
Nano + DS3231 + TM1637 draws under 50mA — USB-powered or battery-friendly
Beginner Friendly
Just 3 libraries, 30 lines of code — ideal for learning I2C and display interfacing
Comments
Post a Comment