← До всіх проєктів
Дисплеї Початковий

Точний годинник на OLED-дисплеї з синхронізацією через інтернет (NTP)

ESP32 бере точний час з NTP-серверів, сам перемикається на літній/зимовий час і показує його на дисплеї SSD1306 128×64.

Складність
Початковий
Час
45 min
Категорія
Дисплеї

Навіщо

У ESP32 немає батарейного годинника реального часу, зате є Wi-Fi і вбудований SNTP-клієнт. Достатньо один раз вказати часовий пояс — і плата сама синхронізуватиметься та переходитиме на літній час.

Компоненти

  • ESP32 DevKit
  • OLED-дисплей SSD1306 0.96" 128×64, I²C (4 виводи)
  • 4 дроти

Підключення

OLED ESP32
VCC 3V3
GND GND
SDA GPIO 21
SCL GPIO 22

Бібліотеки

  • Adafruit SSD1306
  • Adafruit GFX Library

Код

#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-рядок часового поясу: Київ, з автоматичним літнім часом
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 на символ → 96 px ширина
  display.setCursor(16, 16);
  display.print(timeStr);
  display.setTextSize(1);
  display.setCursor(34, 44);
  display.print(dateStr);
  display.display();

  delay(200);
}

Як це працює

  • configTzTime() вмикає SNTP-клієнт ESP-IDF і задає часовий пояс. Синхронізація далі відбувається у фоні приблизно раз на годину.
  • getLocalTime() повертає локальний час з урахуванням літнього/зимового.
  • Рядок EET-2EEST,M3.5.0/3,M10.5.0/4 означає: базовий пояс UTC+2, літній час з останньої неділі березня 03:00 до останньої неділі жовтня 04:00.

Інші часові пояси

Місто TZ-рядок
Варшава / Берлін CET-1CEST,M3.5.0,M10.5.0/3
Лондон GMT0BST,M3.5.0/1,M10.5.0
Нью-Йорк EST5EDT,M3.2.0,M11.1.0

Якщо дисплей порожній

  • Деякі модулі мають адресу 0x3D замість 0x3C.
  • Запустіть приклад Wire → I2C Scanner, щоб побачити адресу.

Покращення

  • Вимикайте Wi-Fi після синхронізації (WiFi.disconnect(true)) — годинник продовжить іти, а плата менше грітиметься.
  • Додайте DHT22 з проєкту «Міні-метеостанція» і показуйте температуру в нижньому рядку.
  • Великий шрифт: display.setFont(&FreeSansBold18pt7b) з бібліотеки Adafruit GFX.