4-Digit 7-Segment
Digital Clock with Arduino
Build a real digital clock displaying HH:MM with a blinking colon, adjustable time buttons, and millis() timing — all in the free Wokwi browser simulator!
Overview
What You'll Build
A fully functional digital clock showing hours and minutes on a bright red 7-segment display — with real time-keeping and manual set buttons.
Components
What You Need
Virtual components in Wokwi — nothing to buy!
TM1637Display — available in Wokwi's library manager with one click.
Wiring
Pin Connections
The TM1637 module uses only 2 data wires (CLK + DIO). Buttons connect through 10kΩ pull-down resistors.
Full Connection Table
| From | To (Arduino) | Wire Color |
|---|---|---|
| TM1637 CLK | Pin 2 | 🔵 Blue |
| TM1637 DIO | Pin 3 | 🟢 Green |
| TM1637 VCC | 5V | 🔴 Red |
| TM1637 GND | GND | ⬛ Black |
| SET btn pin 1 | Pin 6 | 🟢 Green |
| SET btn pin 2 → R1 → GND | GND | ⬛ Black |
| HOUR btn pin 1 | Pin 4 | 🔵 Blue |
| HOUR btn pin 2 → R2 → GND | GND | ⬛ Black |
| MIN btn pin 1 | Pin 5 | 🟡 Yellow |
| MIN btn pin 2 → R3 → GND | GND | ⬛ Black |
Segment Pins (a–g)
| Segment | Arduino Pin |
|---|---|
| a | 2 |
| b | 3 |
| c | 4 |
| d | 5 |
| e | 6 |
| f | 7 |
| g | 8 |
Digit Control Pins
| Digit | Arduino Pin |
|---|---|
| D1 (leftmost) | 9 |
| D2 | 10 |
| D3 | 11 |
| D4 (rightmost) | 12 |
Use 220Ω resistors on segment pins for raw 7-seg. The TM1637 module handles this internally.
Instructions
Step-by-Step Guide
8 simple steps to get your digital clock ticking in Wokwi.
-
Open the Wokwi Simulation
Go to wokwi.com/projects/459618020796829697 or click ▶ Run Simulation above. The TM1637 display and Arduino Uno are pre-loaded.
-
Add the TM1637 Library
In Wokwi, click the Libraries 📚 icon in the sidebar. Search for
TM1637Displayand add it. This handles all the 7-segment display communication. -
Paste the diagram.json
Click the diagram.json tab and paste the JSON from the Diagram JSON section below. This auto-wires the TM1637, all 3 buttons, and their 10kΩ resistors.
-
Paste the Arduino code
Open the sketch.ino tab and paste the full code from the Code section. The code starts the clock at 12:00 and uses
millis()for accurate timekeeping. -
Click ▶ Start Simulation
Hit the green play button. The display shows
12:00with a blinking colon. Check the Serial Monitor for startup messages and live time output every second.Expected output: Serial Monitor printsTime: 12:00:01,12:00:02... every second. -
Press the SET button (green)
Click the green SET button to enter Set Mode. The colon stays on steady (not blinking) to indicate you're setting the time. Serial Monitor prints
*** SET MODE ENABLED ***. -
Adjust time with HOUR and MIN buttons
Click the blue HOUR button to increment hours (wraps at 24). Click the yellow MIN button to increment minutes (wraps at 60). Each press is debounced to prevent double-counting.
-
Press SET again to save and run
Press the green SET button again to exit Set Mode. Seconds reset to 0 and the clock resumes from the new time. Colon starts blinking again!
Source Code
Arduino Sketch
Paste this into sketch.ino in Wokwi. Uses the TM1637Display library.
/* * 4-Digit 7-Segment Clock Display * Displays time in HH:MM format using TM1637 display module * Features: Clock display, adjustable time, blinking colon * MakeMindz.com — Summer Class Project */ #include <TM1637Display.h> // ── Pin definitions for TM1637 ── #define CLK_PIN 2 // Clock pin #define DIO_PIN 3 // Data pin // ── Button pins ── #define HOUR_BTN 4 // Increment hours #define MIN_BTN 5 // Increment minutes #define SET_BTN 6 // Enter / exit set mode // ── Display object ── TM1637Display display(CLK_PIN, DIO_PIN); // ── Time variables ── int hours = 12; int minutes = 0; int seconds = 0; // ── State variables ── bool setMode = false; bool colonBlink = true; unsigned long lastUpdate = 0; unsigned long lastBlink = 0; // ── Button debouncing (200 ms) ── unsigned long lastHourPress = 0; unsigned long lastMinPress = 0; unsigned long lastSetPress = 0; const int debounceDelay = 200; // ─────────────────── SETUP ─────────────────── void setup() { Serial.begin(9600); pinMode(HOUR_BTN, INPUT_PULLUP); pinMode(MIN_BTN, INPUT_PULLUP); pinMode(SET_BTN, INPUT_PULLUP); display.setBrightness(0x0f); // Max brightness // Clear display on start uint8_t blank[] = {0x00, 0x00, 0x00, 0x00}; display.setSegments(blank); delay(500); Serial.println("4-Digit 7-Segment Clock Initialized"); Serial.println("SET=enter/exit set mode HOUR=+1hr MIN=+1min"); } // ─────────────────── LOOP ──────────────────── void loop() { unsigned long now = millis(); checkButtons(); // Advance time every 1 second (paused in set mode) if (!setMode && now - lastUpdate >= 1000) { lastUpdate = now; updateTime(); } // Blink colon every 500 ms if (now - lastBlink >= 500) { lastBlink = now; colonBlink = !colonBlink; } displayTime(); delay(10); } // ─────────────────── TIME UPDATE ───────────── void updateTime() { seconds++; if (seconds >= 60) { seconds = 0; minutes++; if (minutes >= 60) { minutes = 0; hours++; if (hours >= 24) hours = 0; } } // Print to Serial Monitor Serial.print("Time: "); if (hours < 10) Serial.print("0"); Serial.print(hours); Serial.print(":"); if (minutes < 10) Serial.print("0"); Serial.print(minutes); Serial.print(":"); if (seconds < 10) Serial.print("0"); Serial.println(seconds); } // ─────────────────── DISPLAY TIME ──────────── void displayTime() { int val = hours * 100 + minutes; if (setMode) { // Steady colon in set mode display.showNumberDecEx(val, 0b01000000, true); } else { // Blinking colon in normal mode display.showNumberDecEx(val, colonBlink ? 0b01000000 : 0b00000000, true); } } // ─────────────────── BUTTON CHECK ──────────── void checkButtons() { unsigned long now = millis(); // SET — toggle set mode if (digitalRead(SET_BTN) == LOW && now - lastSetPress > debounceDelay) { lastSetPress = now; setMode = !setMode; if (setMode) { Serial.println("*** SET MODE ENABLED — Use HOUR/MIN buttons ***"); } else { seconds = 0; // Reset seconds on save lastUpdate = now; // Reset 1-second timer Serial.println("*** TIME SAVED — Clock running ***"); } delay(200); } // HOUR — only active in set mode if (setMode && digitalRead(HOUR_BTN) == LOW && now - lastHourPress > debounceDelay) { lastHourPress = now; hours = (hours + 1) % 24; Serial.print("Hours → "); Serial.println(hours); } // MIN — only active in set mode if (setMode && digitalRead(MIN_BTN) == LOW && now - lastMinPress > debounceDelay) { lastMinPress = now; minutes = (minutes + 1) % 60; Serial.print("Minutes → "); Serial.println(minutes); } }
Diagram JSON
Wokwi diagram.json
Paste this into the diagram.json tab in Wokwi. It auto-places all parts and wires — including the 10kΩ pull-down resistors for the buttons.
{
"version": 1,
"author": "4-Digit Clock Display",
"editor": "wokwi",
"parts": [
{
"type": "wokwi-arduino-uno",
"id": "uno",
"top": 0, "left": 0,
"attrs": {}
},
{
"type": "wokwi-tm1637-7segment",
"id": "tm1637",
"top": -96, "left": 144,
"attrs": { "color": "red" }
},
{
"type": "wokwi-pushbutton",
"id": "btn_set",
"top": 124.8, "left": -124.8,
"attrs": { "color": "green", "label": "SET" }
},
{
"type": "wokwi-pushbutton",
"id": "btn_hour",
"top": 124.8, "left": -28.8,
"attrs": { "color": "blue", "label": "HOUR" }
},
{
"type": "wokwi-pushbutton",
"id": "btn_min",
"top": 124.8, "left": 67.2,
"attrs": { "color": "yellow", "label": "MIN" }
},
{
"type": "wokwi-resistor",
"id": "r1",
"top": 220.15, "left": -124.8,
"rotate": 90,
"attrs": { "value": "10000" }
},
{
"type": "wokwi-resistor",
"id": "r2",
"top": 220.15, "left": -28.8,
"rotate": 90,
"attrs": { "value": "10000" }
},
{
"type": "wokwi-resistor",
"id": "r3",
"top": 220.15, "left": 67.2,
"rotate": 90,
"attrs": { "value": "10000" }
}
],
"connections": [
[ "tm1637:CLK", "uno:2", "blue", ["v0"] ],
[ "tm1637:DIO", "uno:3", "green", ["v0"] ],
[ "tm1637:VCC", "uno:5V", "red", ["v0"] ],
[ "tm1637:GND", "uno:GND.1", "black", ["v0"] ],
[ "btn_set:1.l", "uno:6", "green", ["v0"] ],
[ "btn_set:2.l", "r1:1", "black", ["v0"] ],
[ "r1:2", "uno:GND.2", "black", ["v0"] ],
[ "btn_hour:1.l", "uno:4", "blue", ["v0"] ],
[ "btn_hour:2.l", "r2:1", "black", ["v0"] ],
[ "r2:2", "uno:GND.2", "black", ["v0"] ],
[ "btn_min:1.l", "uno:5", "yellow", ["v0"] ],
[ "btn_min:2.l", "r3:1", "black", ["v0"] ],
[ "r3:2", "uno:GND.2", "black", ["v0"] ]
],
"dependencies": {}
}
Explanation
How It Works
Three core systems work together — timekeeping, display refresh, and button handling.
millis() Timekeeping
Instead of using delay(1000), this project uses millis() to check if 1000 ms have passed since the last update. This keeps the loop() running fast so buttons always respond instantly — delay() would freeze the processor and miss button presses. Every 1000 ms, updateTime() increments seconds → minutes → hours in a nested rollover chain.
TM1637 Display Module
The TM1637 uses its own 2-wire protocol (not I2C or SPI) over CLK and DIO pins. The library's showNumberDecEx() function takes an integer like 1230 and displays it as 12:30. The second argument is a bitmask — 0b01000000 turns the colon on, 0b00000000 turns it off. Toggling this every 500 ms creates the blinking effect.
Debouncing
Mechanical buttons bounce — they rapidly open and close for a few milliseconds after being pressed. Without debouncing, one press can register as 5–10 presses. This code compares millis() with the last press timestamp and only acts if 200 ms have passed. This is software debouncing — clean, no extra capacitors needed.
Education
What You'll Learn
Key embedded systems and electronics concepts all in one project.
FAQ
Frequently Asked Questions
displayTime() to show seconds — though you'd need a 6-digit display or a second 4-digit module for the full HH:MM:SS format."color": "red" to "color": "green" or "color": "blue" in the diagram.json parts section. On real hardware, just use a different colour TM1637 module — the code is identical.
Comments
Post a Comment