Build a Wi‑Fi‑Enabled 7‑Segment Clock Using ESP32

Ever glance at a wall clock and think, “I could make that myself and add a splash of code”? In 2024 the parts are cheap, the tutorials are everywhere, and a Wi‑Fi‑connected clock can even pull the time from the internet so you never have to set it again. That’s why I’m sharing a step‑by‑step guide on the Segmented Light blog – a little project that lets you learn ESP32 basics while getting a useful display for your desk.

What You’ll Need

Below is the minimal list that kept my first build simple and reliable. Feel free to swap parts if you already have them, but try to stay close to the values so the code works out of the box.

  • ESP32‑DevKitC – the brain of the clock, with built‑in Wi‑Fi and plenty of GPIO pins.
  • Common‑anode 4‑digit 7‑segment display – the classic “digital clock” look. I use a red LED version because it pops on my workbench.
  • Four 220 Ω resistors – limit current for each digit’s common anode.
  • Four N‑MOSFETs (e.g., 2N7000) – act as switches to turn each digit on and off.
  • Breadboard and jumper wires – for prototyping before you solder.
  • Micro‑USB cable – to power the ESP32 and upload code.
  • Optional: 0.96″ OLED display – handy for debugging the time before the segments light up.

All of these parts are under $15 on most hobby sites, so the whole clock costs less than a cheap alarm clock you can buy in a store.

Wiring the Segments

1. Connect the segment pins

The 7‑segment display has eight pins per digit: a‑g for the segments and dp for the decimal point. On a common‑anode module the anode pins of each digit are tied together, so you only need one wire per digit to control it.

  • Hook the a‑g pins of each digit to the ESP32 GPIOs you plan to use (I chose GPIO 12‑19).
  • Place a 220 Ω resistor in series with each segment line. This protects the LEDs and keeps the brightness even.

2. Set up the digit control

Each digit’s common anode goes to +5 V through a 220 Ω resistor and then to the drain of an N‑MOSFET.

  • Connect the source of each MOSFET to ground.
  • Wire the gate of each MOSFET to a separate ESP32 pin (GPIO 21‑24).

When the ESP32 drives a gate high, the MOSFET conducts and the corresponding digit lights up. This method lets you multiplex the display – you turn on one digit at a time, fast enough that the human eye sees all four digits together.

3. Power considerations

The ESP32 runs at 3.3 V, but the 7‑segment display likes 5 V. A simple logic‑level shifter (or just the MOSFETs as shown) does the job. Keep the total current under 200 mA; the resistors keep us safe.

Programming the ESP32

1. Install the Arduino core

If you haven’t already, open the Arduino IDE, go to File → Preferences, and add the URL https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json to the Additional Boards Manager URLs. Then install the ESP32 board package.

2. Get the NTP library

We’ll pull the current time from an NTP server. In the IDE, open Sketch → Include Library → Manage Libraries… and install NTPClient. It handles the UDP handshake for you.

3. Write the multiplex code

The core of the sketch is a loop that:

  1. Reads the current epoch time from the NTP client.
  2. Converts it to hours, minutes, and seconds.
  3. Updates an array of segment patterns for each digit.
  4. Turns on one digit, writes its segment pattern, waits ~2 ms, then moves to the next digit.

Here’s a stripped‑down version of the loop (feel free to copy it into your own file):

#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

const char* ssid     = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

WiFiUDP udp;
NTPClient timeClient(udp, "pool.ntp.org", 0, 60000); // update every minute

// GPIO pins for segments a‑g (order matters)
const int segPins[7] = {12, 13, 14, 15, 16, 17, 18};
// GPIO pins for digit control
const int digPins[4] = {21, 22, 23, 24};

// segment patterns for 0‑9 (common‑anode, 1 = off)
const byte digitMap[10] = {
  B00111111, // 0
  B00000110, // 1
  B01011011, // 2
  B01001111, // 3
  B01100110, // 4
  B01101101, // 5
  B01111101, // 6
  B00000111, // 7
  B01111111, // 8
  B01101111  // 9
};

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  timeClient.begin();

  for (int i = 0; i < 7; i++) pinMode(segPins[i], OUTPUT);
  for (int i = 0; i < 4; i++) pinMode(digPins[i], OUTPUT);
}

void displayNumber(int number) {
  int thousands = number / 1000;
  int hundreds  = (number / 100) % 10;
  int tens      = (number / 10) % 10;
  int ones      = number % 10;
  int digits[4] = {thousands, hundreds, tens, ones};

  for (int d = 0; d < 4; d++) {
    // turn off all digits first
    for (int i = 0; i < 4; i++) digitalWrite(digPins[i], HIGH);
    // set segments for this digit
    byte pattern = digitMap[digits[d]];
    for (int s = 0; s < 7; s++) {
      bool segOn = !(pattern & (1 << s)); // common‑anode logic
      digitalWrite(segPins[s], segOn);
    }
    // enable this digit
    digitalWrite(digPins[d], LOW);
    delay(2); // short pause for persistence
  }
}

void loop() {
  timeClient.update();
  int current = timeClient.getEpochTime();
  // convert epoch to hour/minute
  int hour   = (current / 3600) % 24;
  int minute = (current / 60) % 60;
  int displayValue = hour * 100 + minute; // e.g., 0930 for 9:30
  displayNumber(displayValue);
}

4. Tweak the time zone

The NTP client takes a offset in seconds. For example, for Indian Standard Time (UTC+5:30) use 19800. Change the third argument in the NTPClient constructor accordingly.

5. Upload and test

Select ESP32 Dev Module, hit the upload button, and watch the digits flicker into life. If you see only one digit or garbled segments, double‑check the wiring of the MOSFET gates and the segment pins.

Putting It All Together

Once the code runs, I like to move the prototype from the breadboard to a small perf‑board. A neat trick is to cut a piece of acrylic, drill four 12 mm holes, and mount the display inside. The ESP32 can sit behind the board, and a tiny USB‑type‑C connector gives you power and a way to re‑flash later.

I added a push‑button to the side that forces a manual time sync. It’s handy when you’re traveling and the Wi‑Fi network changes. The button simply calls timeClient.forceUpdate(); in the sketch.

Personal note

The first time I built this clock, I accidentally wired the MOSFETs backwards and ended up with a very dim, flickering mess. After a few minutes of sighing, I realized the source and drain were swapped – a classic rookie mistake. The lesson? Double‑check the arrow direction on the MOSFET symbol; it points from source to drain. Once fixed, the clock lit up bright and steady, and I felt like a kid who just discovered a secret level in a video game.

Why this matters

A Wi‑Fi‑enabled clock does more than tell time. It can be a visual cue for network status, a simple IoT node that reports uptime, or a base for adding weather icons later. Building it yourself gives you full control over the look and the code, and you end up with a piece of hardware that you truly understand.

Enjoy the glow of your own 7‑segment clock, and remember: every big project starts with a single LED segment.

Reactions
Do you have any feedback or ideas on how we can improve this page?