Displays
Beginner
Accurate OLED Clock Synced over the Internet (NTP)
The ESP32 fetches accurate time from NTP servers, handles daylight saving automatically and shows it on an SSD1306 128×64 display.
Why
The ESP32 has no battery-backed real-time clock, but it does have Wi-Fi and a built-in SNTP client. Set the time zone once and the board keeps itself in sync and handles daylight saving on its own.
Parts
- ESP32 DevKit
- SSD1306 0.96" 128×64 I²C OLED display (4 pins)
- 4 jumper wires
Wiring
| OLED | ESP32 |
|---|---|
| VCC | 3V3 |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
Libraries
- Adafruit SSD1306
- Adafruit GFX Library
Code
#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <time.h>
const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASS = "YOUR_PASSWORD";
// POSIX time zone string: Kyiv, with automatic daylight saving
const char* TZ_INFO = "EET-2EEST,M3.5.0/3,M10.5.0/4";
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void showMessage(const char* text) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print(text);
display.display();
}
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 not found");
while (true) delay(1000);
}
display.setTextColor(SSD1306_WHITE);
showMessage("Connecting WiFi...");
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(300);
showMessage("Syncing time...");
configTzTime(TZ_INFO, "pool.ntp.org", "time.google.com");
}
void loop() {
struct tm now;
if (!getLocalTime(&now)) {
delay(500);
return;
}
char timeStr[9], dateStr[11];
strftime(timeStr, sizeof timeStr, "%H:%M:%S", &now);
strftime(dateStr, sizeof dateStr, "%d.%m.%Y", &now);
display.clearDisplay();
display.setTextSize(2); // 12×16 px per char → 96 px wide
display.setCursor(16, 16);
display.print(timeStr);
display.setTextSize(1);
display.setCursor(34, 44);
display.print(dateStr);
display.display();
delay(200);
}
How it works
configTzTime()starts the ESP-IDF SNTP client and sets the time zone. Re-sync then happens in the background roughly every hour.getLocalTime()returns local time with daylight saving applied.EET-2EEST,M3.5.0/3,M10.5.0/4means: base zone UTC+2, summer time from the last Sunday of March 03:00 to the last Sunday of October 04:00.
Other time zones
| City | TZ string |
|---|---|
| Warsaw / Berlin | CET-1CEST,M3.5.0,M10.5.0/3 |
| London | GMT0BST,M3.5.0/1,M10.5.0 |
| New York | EST5EDT,M3.2.0,M11.1.0 |
Blank display?
- Some modules use address 0x3D instead of 0x3C.
- Run the Wire → I2C Scanner example to find the address.
Improvements
- Turn Wi-Fi off after syncing (
WiFi.disconnect(true)) — the clock keeps running and the board runs cooler. - Add the DHT22 from the "Mini Weather Station" project and show the temperature on the bottom line.
- Bigger digits:
display.setFont(&FreeSansBold18pt7b)from Adafruit GFX.