Eine digitale Uhr auf Basis des Wemos D1 Mini (ESP8266) mit 7-Segment-Display, RTC-Modul, WLAN-Zeitsynchronisation, OTA-Updates und einem einfachen Menüsystem mit Laufschrift.
Claude AI von Anthropic half mir dabei, meine Ansprüche und Ideen umzusetzen.
Aktuelle Version: 1.1.0
| Komponente | Beschreibung |
|---|---|
| Wemos D1 Mini | Mikrocontroller (ESP8266, 4 MB Flash) |
| TM1637 | 4-stelliges 7-Segment-Display mit Doppelpunkt |
| DS3231 | RTC-Modul mit Temperaturmessung und Pufferbatterie |
| 2× Taster | Navigation (Menü / Enter) |
| Signal | GPIO | Wemos Pin |
|---|---|---|
| TM1637 CLK | 14 | D5 |
| TM1637 DIO | 0 | D3 |
| DS3231 SDA | 4 | D2 (I²C) |
| DS3231 SCL | 5 | D1 (I²C) |
| Button Menü | 12 | D6 |
| Button Enter | 13 | D7 |
Hinweis zu GPIO0 (D3): Das ist ein Strapping-Pin – er muss beim Booten HIGH sein, sonst startet der ESP8266 in den Flash-Modus. Mit dem TM1637 funktioniert es in der Praxis, weil DIO im Ruhezustand hoch bleibt. Wer umverdrahtet, sollte das im Hinterkopf behalten.
Hinweis zur RTC-Batterie: Viele ZS-042-Module haben eine Ladeschaltung für LIR2032-Akkus. Steckt eine normale CR2032 drin, wird sie dauerhaft geladen. Entweder eine wiederaufladbare LIR2032 verwenden oder die Ladeschaltung (Diode / 200 Ω) auslöten.
- Uhrzeitanzeige mit sekündlich blinkendem Doppelpunkt – der Sekundenwechsel wird per Polling des DS3231 erkannt, kein Hardware-Interrupt nötig
- Startbildschirm: Der Gerätename läuft beim Booten als Laufschrift über das Display
- NTP-Zeitsynchronisation via WLAN bei jedem Start, inklusive korrekter Zeitzone und Sommerzeit (
CET-1CEST,M3.5.0,M10.5.0/3) – danach wird das WLAN wieder abgeschaltet - WLAN-Konfiguration über WiFiManager-Captive-Portal (kein hardcodiertes Passwort nötig)
- Fallback ohne WLAN: Läuft das Portal in den Timeout, arbeitet die Uhr einfach mit der gepufferten RTC-Zeit weiter
- OTA-Update über GitHub Releases mit Versionsvergleich, Bestätigungs-Countdown und Fortschrittsanzeige in Prozent
- Temperaturanzeige über den integrierten Sensor des DS3231
- Helligkeitseinstellung (0–7) mit persistenter Speicherung via Preferences (NVS)
- Menüsystem mit Laufschrift für lange Einträge und automatischem Rücksprung zur Uhr nach Inaktivität
- Long-Press auf den Enter-Button springt jederzeit zur Uhr zurück
Uhr (Standardanzeige)
│
└── [Enter kurz] → Hauptmenü
│
├── HELLIGKEIT → Helligkeit 0–7 (Menü-Button zum Verstellen)
├── TEMPERATUR → Temperaturanzeige des DS3231
├── RESET INTERNET CONFIG → WLAN-Daten löschen & Neustart
│
└── [Enter lang] → zurück zur Uhr
Menüeinträge mit mehr als vier Zeichen laufen automatisch als Laufschrift über das Display. Der Inaktivitäts-Timeout pausiert, solange gescrollt wird – ein Eintrag wird also immer vollständig angezeigt, bevor die Uhr zurückkehrt.
Folgende Arduino-Bibliotheken werden in der jeweiligen Version benötigt: (❗wichtig und unbedingt beachten❗)
| Bibliothek | Version | Link |
|---|---|---|
| TM1637Display | 1.2.0 | avishorp/TM1637 |
| 1.1.0 | hasenradball/DS3231-RTC | |
| WiFiManager | 2.0.17 | tzapu/WiFiManager |
| Preferences | 2.2.2 | vshymanskyy/Preferences |
digital-clock/
├── digital-clock.ino – Einstiegspunkt (setup & loop)
├── config.h – Zentrale Konfiguration: Pins, Timings, Texte, URLs
├── globals.h / .cpp – Globale Objekte & Menüdefinition
├── displayHelper.h – Segment-Encoding, showTime(), showLabel()
└── src/
├── lib/ – Wiederverwendbare, hardwarenahe Klassen
│ ├── Button.h – Interrupt-basierte Button-Klasse (inkl. Long-Press)
│ ├── Menu.h – Generische Menü-Klasse (Zustandsautomat)
│ ├── Marquee.h – Laufschrift für 4-stellige Displays
│ └── RTC.h – DS3231-Wrapper mit Sekundenerkennung per Polling
├── hal/ – Hardware Abstraction Layer
│ ├── display.h / .cpp – Display-Ausgabe, Menü-Callbacks, Textmeldungen
│ └── input.h / .cpp – Button-Callbacks & Menüsteuerung
└── services/ – Anwendungslogik
├── boot.h / .cpp – Start-Sequenz (Begrüßung)
├── clock.h / .cpp – RTC-Tick & Uhrzeitanzeige
├── settings.h / .cpp– Persistente Einstellungen (Preferences/NVS)
├── wifi.h / .cpp – WLAN, WiFiManager, NTP-Sync
└── ota.h / .cpp – Versionsprüfung & Firmware-Update
Hinweis: Ich habe mich ganz bewusst für diese Struktur entschieden, da damit das Projekt vollständig in der Arduino IDE 2.x.x geöffnet werden kann.
Die Reihenfolge in setup() ist nicht beliebig:
settingsSetup()– Preferences öffnenclockSetup()– RTC undWire.begin(), muss vor allen I²C-Zugriffen laufendisplaySetup()– Display mit gespeicherter HelligkeitbootSplash()– Begrüßung, Display gehört hier exklusiv der LaufschriftinputSetup()– Buttons registrierenwifiSetup()– WLAN, NTP-Sync und OTA-Check bei bestehender VerbindungotaSetup()– Version im Serial-Log ausgeben
- Bibliotheken installieren (siehe oben)
- Sketch auf den Wemos D1 Mini flashen
- Beim ersten Start öffnet der Controller einen WLAN-Access-Point namens
WILHELM 1 - Mit dem Handy oder Laptop mit
WILHELM 1verbinden - Im Browser öffnet sich automatisch das Konfigurationsportal
- Heimnetzwerk auswählen und WLAN-Passwort eingeben
- Nach erfolgreicher Verbindung synchronisiert sich die Uhr automatisch via NTP
- WLAN wird danach wieder getrennt – die Uhr läuft offline weiter
Die WLAN-Zugangsdaten bleiben dauerhaft gespeichert. Bei jedem weiteren Start verbindet sich der Controller automatisch und synchronisiert die Zeit.
Wird innerhalb von 120 Sekunden nichts konfiguriert, schließt das Portal und die Uhr läuft mit der Zeit aus dem gepufferten DS3231 weiter.
Im Menü den Punkt RESET INTERNET CONFIG auswählen und mit Enter bestätigen. Der Controller löscht die gespeicherten WLAN-Daten und startet neu – das Konfigurationsportal öffnet sich automatisch.
Beim Start prüft die Uhr – solange das WLAN noch verbunden ist – ob im GitHub-Repository ein neueres Release vorliegt. Verglichen wird FIRMWARE_VERSION aus config.h mit dem Inhalt von version.txt aus dem letzten Release.
Ist ein Update verfügbar, zeigt das Display eine Meldung und anschließend einen Countdown. Ein Druck auf Enter startet den Download, ohne Bestätigung läuft der Countdown ab und die Uhr startet normal. Nach dem Flashen rebootet der Controller selbstständig.
FIRMWARE_VERSIONinconfig.herhöhen- Sketch → Kompilierte Binärdatei exportieren (
Strg+Alt+S), die.binnachfirmware.binumbenennen version.txtmit exakt derselben Versionsnummer anlegen (nur die Zahl, z. B.1.1.0)- Auf GitHub ein Release anlegen und beide Dateien als Assets hochladen
Ein als Pre-Release markiertes Release wird nicht gefunden –
releases/latest/download/…überspringt Pre-Releases.
In config.h OTA_TEST_MODE auf 1 setzen und unter OTA_TEST_HOST die IP des eigenen Rechners eintragen. Dann einen Ordner mit version.txt und firmware.bin anlegen und darin einen Webserver starten:
python -c "open('version.txt','w').write('1.1.0')"
python -m http.server 8000 --bind 0.0.0.0version.txt bewusst mit Python schreiben – PowerShell erzeugt mit echo > eine UTF-16-Datei mit BOM, die der Parser auf dem ESP nicht lesen kann.
Wichtig beim Testen: Die Versionsnummer in version.txt muss zu der Version passen, mit der firmware.bin kompiliert wurde. Sonst bietet die Uhr nach dem Update dasselbe Update erneut an.
- Sommerzeitwechsel: Die lokale Zeit wird in den DS3231 geschrieben und nur beim Start synchronisiert. Nach der Umstellung im März und Oktober geht die Uhr eine Stunde falsch, bis sie neu gestartet wird.
- Lesbarkeit auf 7 Segmenten: Die Buchstaben K, M, W, X, V und Z lassen sich nicht sinnvoll darstellen. Displaytexte in
config.hsollten ohne sie auskommen. - Laufschrift: Die Fensterposition ist als
uint8_tgehalten, Texte über 252 Zeichen laufen über.
MIT License – feel free to use, modify and share.

