Digitální Hodiny na OLED
Popis
Tento projekt zobrazuje digitální hodiny na OLED displeji. Po připojení k WiFi se zařízení synchronizuje s internetovým časovým serverem (NTP) a zobrazuje aktuální čas ve formátu HH:MM:SS spolu s datem v levém horním rohu.
Použitý font připomíná 7-segmentový displej. Projekt podporuje automatické přepínání mezi letním a zimním časem (Evropa / Praha).
Značka
Ukázkový výstup na OLED
- Vlevo nahoře: datum ve formátu
DD.MM.YYYYpř. 15.05. 2025 - Ve středu: čas ve formátu
HH:MM:SSpř. 13:22:34
Ukázkový kód
#include <Arduino.h>
#include <WiFi.h>
#include <Wire.h>
#include <U8g2lib.h>
#include <time.h>
// ======== VLASTNÍ FONT: 7SEG =================
// Tento font je uložen přímo v poli (bdf_font)
const uint8_t bdf_font[372] U8G2_FONT_SECTION("bdf_font") =
"\21\0\4\4\4\5\5\6\6\21\37\0\341\376\0\0\0\0\0\0\0\1W \6\0 \70\3+\16\231"
"\344\322\316\260i\36\260\31\66\15\0,\7\63dpB\2-\10\71\244\323\302\3\6.\7\63dpB"
"\2/\6\0 \330\2\60 \337e\60G\213\20+F\244(i\177Yvtx\0\241\307\226\264\277,"
"\221b\304\212\20-\0\61\22\323q\60K\210\7\17D\10\11\25\342\201\13I\2\62\36\337e\60\203\23"
"\26AT\10\236\177-dE\210\26!\226\210\36<\177,BI\10&\16\63\35\337e\60\203\23\26A"
"T\10\236\177-dE\210\66+B\13\236\177\242B\4\213\27\0\64\31\337e\60C\350\261%\355_\226"
"\35\261\42D\233\25\241\5\317\177-<\0\65\35\337e\60\307\13\26\42\224\14\236\77\26\35bM\233\25"
"\241\5\317\77Q!\202\305\13\0\66 \337e\60\307\13\26\42\224\14\236\77\26\35bM\213\20+\306\226"
"\264\277,\221b\304\212\20-\0\67\30\337e\60\203\23\26AT\10\236\177-<<\360\320\202\347\277\26"
"\36\0\70\42\337e\60G\213\20+F\244(i\177Yv\304\212\20-B\254\30[\322\376\262D\212\21"
"+B\264\0\71\37\337e\60G\213\20+F\244(i\177Yv\304\212\20mV\204\26<\377D\205\10"
"\26/\0:\11\363$rBz\300\11\0\0\0\4\377\377\0";
// Inicializace OLED displeje SH1107 (128x128)
U8G2_SH1107_PIMORONI_128X128_F_HW_I2C oled(U8G2_R1, U8X8_PIN_NONE);
// WiFi připojení – zadej své údaje
const char* ssid = "jmeno-wifi";
const char* password = "heslo-k-wifi";
// ======= Pomocné funkce =======
// OLED: Zobrazí dvouřádkový text na střed displeje
void showCenteredText(const char* line1, const char* line2 = nullptr) {
oled.clearBuffer(); // Smazat předchozí obsah
oled.setFont(u8g2_font_6x12_tf); // Nastavit základní malý font
// První řádek
int w1 = oled.getStrWidth(line1);
oled.setCursor((128 - w1) / 2, 50); // Vodorovné zarovnání
oled.print(line1);
// Druhý řádek (volitelný)
if (line2 && line2[0] != '\0') {
int w2 = oled.getStrWidth(line2);
oled.setCursor((128 - w2) / 2, 65);
oled.print(line2);
}
oled.sendBuffer(); // Vykreslit na displej
}
// Připojení k WiFi + výpis na OLED
void connectToWiFi() {
WiFi.disconnect(true); // Odpojit předchozí spojení
WiFi.mode(WIFI_STA); // Režim klienta
delay(1000);
WiFi.begin(ssid, password); // Připojit
showCenteredText("WiFi se", "pripojuje...");
unsigned long start = millis();
const unsigned long timeout = 20000; // 20 sekund limit
while (WiFi.status() != WL_CONNECTED && millis() - start < timeout) {
delay(500);
}
oled.clearBuffer();
oled.setFont(u8g2_font_6x12_tf);
if (WiFi.status() == WL_CONNECTED) {
// Získat a zobrazit IP adresu
String ip = WiFi.localIP().toString();
oled.drawStr(10, 30, "Pripojeno k WiFi");
oled.drawStr(10, 45, ip.c_str());
oled.sendBuffer();
delay(2000);
} else {
oled.drawStr(10, 30, "Nelze se");
oled.drawStr(10, 45, "pripojit k WiFi");
oled.sendBuffer();
delay(3000);
}
}
// OLED: Zobrazí datum vlevo nahoře ve formátu DD.MM.YYYY
void drawDate(struct tm *timeinfo) {
char dateStr[11];
sprintf(dateStr, "%02d.%02d.%04d", timeinfo->tm_mday, timeinfo->tm_mon + 1, timeinfo->tm_year + 1900);
oled.setFont(u8g2_font_6x12_tf);
oled.setCursor(0, 12); // Levý horní roh
oled.print(dateStr);
}
// OLED: Zobrazí čas HH:MM:SS na střed s vlastním fontem
void drawCenteredTime(struct tm *timeinfo) {
char timeStr[9];
sprintf(timeStr, "%02d:%02d:%02d", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
oled.setFont(bdf_font); // Vlastní 7-segmentový font
int textWidth = oled.getStrWidth(timeStr);
int textHeight = 19;
int x = (128 - textWidth) / 2; // Vodorovný střed
int y = 64 + textHeight / 2 - textHeight; // Korekce na střed výšky
oled.setCursor(x, y);
oled.print(timeStr);
}
// ======= Hlavní inicializace =======
void setup() {
Serial.begin(115200); // Seriová konzole
Wire.begin(14, 15); // I2C pro LOLIN S3 Mini
oled.begin(); // Inicializace OLEDu
oled.setI2CAddress(0x3C << 1); // Typická I2C adresa
connectToWiFi(); // Připojit k síti
// Správné nastavení časové zóny (Evropa + letní čas)
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", "pool.ntp.org");
// Počkat na synchronizaci času
while (time(nullptr) < 100000) {
delay(100);
}
}
// ======= Hlavní smyčka =======
void loop() {
struct tm timeinfo;
getLocalTime(&timeinfo); // Načti aktuální čas
oled.clearBuffer();
drawDate(&timeinfo); // Vykresli datum
drawCenteredTime(&timeinfo); // Vykresli čas
oled.sendBuffer(); // Vykreslit do OLEDu
delay(1000); // Aktualizace každou sekundu
}