TM1637 display/Two builds and a check/11. A clock that sets itself
Two builds and a check · 11 of 13

A clock that sets itself

An ESP32, a clock panel and four wires. The time comes from the internet, the colon blinks once a second, and the display shows four dashes until the time is real — which matters more than it sounds.

What the sketch is doing

Three things, and only one of them is about the display.

The ESP32 has no battery-backed clock, so it wakes up in 1970 every time. It joins your network, asks a time server what time it is, and the C library keeps count from there.

configTzTime takes a POSIX timezone string rather than an offset in seconds. The string carries the daylight-saving rules, so the clock changes itself in the right week without you reflashing anything in October.

Then the display: hours × 100 + minutes is the number, and the colon is one bit.

The face

The face, at every hour
00:05
Time of day00:05
Format
Leading zeros
The colon, this second
Shows
00:05
Number sent
5
Colon
0b01000000
24 hours, leading zeros on, and the colon is one bit. Hours times a hundred plus minutes is the whole conversion: 13:07 is the number 1307, and 0b01000000 lights the colon between them. Drag the slider through midnight with leading zeros off to see why they are on.

Drag through midnight with leading zeros off and you can watch both failures happen: 00:05 arrives as the number 5 and prints as a bare 5 with a stray colon, and 00:00 loses the colon entirely. With leading zeros on, neither can happen — which is why the sketch passes true.

Twelve-hour time is the opposite: the hour is never 0, and leading zeros off gives you 9:05 rather than 09:05.

int h = t.tm_hour % 12; if (h == 0) h = 12;
display.showNumberDecEx(h * 100 + t.tm_min, COLON, false);

Why the colon blinks

Partly because clocks do. Mostly because it is the only thing on a finished clock that says the sketch is still running.

A display holds its four bytes with no help from your board. If the ESP32 crashes, loses Wi-Fi in a way that blocks, or sits in a watchdog reset loop, the time on the panel simply stops changing — and a clock showing 14:32 looks exactly as convincing at half past three. A colon that blinks once a second is a heartbeat you can see from the doorway.

The dashes do the same job at the other end. Until the year is past 2020 the sketch refuses to show a time at all, because a confidently displayed 00:00 that happens to be 1970 is worse than an obviously blank display.

Making it live somewhere

Two changes turn this from a sketch into a clock on a shelf.

Drop the brightness at night — read t.tm_hour and call setBrightness(0) after nine and setBrightness(5) in the morning. Remember that it is sent with the next write, which here is 200 ms away.

And power it from a USB charger rather than a computer. Nothing in the sketch needs the serial port after the IP address is printed, and an ESP32 with a clock panel is a few hundred milliamps at most — well inside any phone charger.

The code

clock.ino

A 24-hour clock on an ESP32. Put your network name and password at the top, and your own timezone string — the one here is Melbourne, and it carries the daylight-saving dates so the clock changes itself in the right week.

// A clock that sets itself: ESP32 + a TM1637 clock panel, time over Wi-Fi.
//
// Wiring, display to board:
//   Display GND   -> board GND
//   Display VCC   -> board 3V3   (not 5V: the board's pull-ups would then
//                                 hold CLOCK and DATA at 5 V against pins
//                                 rated for 3.3 V)
//   Display CLOCK -> GPIO 18
//   Display DATA  -> GPIO 19
//
// Arduino IDE: ESP32 board support installed, board "ESP32 Dev Module",
// and "TM1637" by Avishay Orpaz from the Library Manager. Serial Monitor
// at 115200.

#include <WiFi.h>
#include <time.h>
#include <TM1637Display.h>

#define CLOCK_PIN 18
#define DATA_PIN  19
#define COLON     0b01000000   // bit 7 of the second digit

const char *SSID     = "your-ssid";
const char *PASSWORD = "your-password";

// POSIX timezone: the offset and the two dates daylight saving changes on,
// so the board handles the switch itself. Replace with your own.
const char *TZ = "AEST-10AEDT,M10.1.0,M4.1.0/3";

TM1637Display display(CLOCK_PIN, DATA_PIN);

// Shown until the time is real. An old or wrong time looks identical to a
// right one; four dashes do not.
const uint8_t DASHES[] = { 0x40, 0x40, 0x40, 0x40 };

void setup() {
  Serial.begin(115200);
  display.setBrightness(4);
  display.setSegments(DASHES);

  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) delay(250);
  Serial.println(WiFi.localIP());

  configTzTime(TZ, "pool.ntp.org", "time.nist.gov");
}

void loop() {
  struct tm t;
  if (!getLocalTime(&t, 100) || t.tm_year + 1900 < 2020) {
    display.setSegments(DASHES);       // no time yet
    delay(500);
    return;
  }

  // Leading zeros on: without them, midnight sends the number 0 and this
  // version of the library drops the colon along with the blank digits.
  display.showNumberDecEx(t.tm_hour * 100 + t.tm_min,
                          (t.tm_sec % 2) ? COLON : 0,
                          true);
  delay(200);
}

The year check is the real test for whether the time has arrived: getLocalTime returns true as soon as the clock has any time at all, and on a cold boot that time is 1970. Until the year looks plausible the display shows four dashes, which is honest in a way that a wrong time is not.

When it does not work

It shows four dashes and never changes

Either Wi-Fi never connected or NTP never answered. Check the serial monitor: the sketch prints the board's IP address once it is on the network. If the IP appears and the dashes stay, NTP is being blocked — it is UDP port 123 outbound, which plenty of guest and corporate networks drop. Most routers run a time server on the gateway address instead.

The time is an hour out half the year

That is a fixed offset instead of a timezone. A POSIX TZ string like the one in the sketch carries the two switch dates, so the board changes itself. gmtOffset plus daylightOffset is correct for one half of the year and wrong for the other.

The colon does not blink

Check the panel first — a digit panel has no colon, only points. If it is a clock panel, check the mask is 0b01000000 and not 0b10000000, and that leading zeros are on.

It shows the right time and then freezes

The display holds whatever it was last sent, so a crashed sketch leaves a perfectly readable frozen clock. That is what the blinking colon is really for: a clock whose colon has stopped blinking is a clock whose sketch has stopped running.

The digits are dim on my blue panel

3.3 V is not enough for blue or white. Use a red, orange, yellow or green panel on an ESP32, or feed the display 5 V with a level converter in the two signal wires.

Where this goes next

The same display with a point instead of a colon, and the arithmetic that puts the point in the right place.

A voltmeter readout

Edit this page — content/books/tm1637-display/a-clock-that-sets-itself.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

This page covers several products. Choose yours to see the right discussions.

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum