Eine einfache Uhr auf dem ESP32 bauen
Unser erstes ESP32-Firmwarebeispiel zeigt, wie aus Zählimpulsen eine Uhrzeit wird, wie sich der Gang einer zu schnellen Uhr korrigieren lässt und wie eine Uhr ohne Zeitsprung aufholt.

Stell zwei Uhren gleich und schau später noch einmal nach. Ist eine von beiden vorgelaufen, kannst du sie neu stellen. Dann zeigen beide für einen Moment wieder dieselbe Zeit. Damit sie gleich bleiben, musst du auch den Gang der schnelleren Uhr korrigieren.
Das ist die Idee der Uhrenregelung: Anhand einer Referenz werden sowohl die angezeigte Zeit als auch der Gang einer Uhr korrigiert. Unsere ESP32-Firmware-Reihe beginnt mit Beispiel 00: Grundlagen einer Softwareuhr. Es läuft am Computer mit simulierten Eingaben. So kannst du nachvollziehen, was jede Korrektur bewirkt, bevor ein ESP32-Board, Funk oder eine UTC-Referenz dazukommen.
Aus Zählimpulsen Zeit berechnen
Ein Zähler erfasst, wie viele Takte vergangen sind. Um daraus eine Zeit zu berechnen, braucht die Software einen Ausgangspunkt: einen Zählerstand, dem ein bekannter Zeitwert zugeordnet ist. Außerdem muss sie wissen, wie viel Zeit pro Takt vergeht. Das Beispiel verwendet einen simulierten 80-MHz-Zähler und beginnt bei der relativen Zeit null.
Bei einem Überlauf springt der Zähler auf null zurück, während die Zeit weiterläuft. Das Beispiel verfolgt den Zählerstand über diese Grenze hinweg und zählt die Takte fortlaufend weiter. Es zeigt auch, warum die ursprünglichen Zählerstände wichtig sind: Bei der Nennfrequenz dauert ein Takt 12,5 Nanosekunden. Wer jeden Takt einzeln rundet, verliert Information. Ein Zeitstempel kann in Nanosekunden angegeben sein, auch wenn die Uhr deutlich ungenauer ist.
Den Gang korrigieren
Im Beispiel läuft der simulierte Zähler um 20 Millionstel zu schnell. Rechnet die Software weiterhin mit der Nennfrequenz, wächst der Zeitfehler um 20 Mikrosekunden pro Sekunde. Nach zehn Sekunden geht die Uhr um 200 Mikrosekunden vor.
Das Beispiel gibt die Korrektur vor. Die Software rechnet jedem Takt etwas weniger Zeit zu. Dadurch schreitet ihre Uhr fast genauso schnell voran wie die Referenz. Der Oszillator läuft unverändert weiter. In einer späteren Folge wird die Korrektur aus Beobachtungen geschätzt.
Ohne Zeitsprung aufholen
Zwei Uhren können gleich schnell laufen und trotzdem verschiedene Zeiten anzeigen. Die Differenz ihrer Zeitwerte heißt Phasenfehler. Geht die Softwareuhr nach, kann sie eine Weile etwas schneller laufen, bis sie aufgeholt hat. Dann kehrt sie zu ihrem üblichen Gang zurück. Diese allmähliche Korrektur heißt Slew. Geht die Uhr vor, kann sie entsprechend langsamer laufen, ohne stehen zu bleiben oder rückwärtszulaufen.
Im Beispiel geht eine Uhr zunächst zwei Mikrosekunden nach. Unmittelbar vor und nach dem Beginn der Korrektur zeigt sie denselben Wert. In den folgenden zwei Sekunden holt sie den Rückstand auf. Ein solcher Verlauf ohne Sprung ist wichtig, wenn ein anderer Programmteil Ereignisse zeitlich einordnet oder Zeitabstände misst.
Den ursprünglichen Zeitwert festhalten
Manchmal liegt die Referenzzeit für ein Ereignis erst vor, nachdem es stattgefunden hat. Halte fest, welchen Zeitwert die Uhr beim Ereignis vorhersagt. Sobald die Referenzzeit vorliegt, vergleiche sie mit diesem gespeicherten Wert, bevor du die Uhr korrigierst. So erfährst du, wie genau die Uhr in dem Moment war, in dem dein Programm sie brauchte.
Eine Uhr muss auch melden können, dass kein brauchbarer Zeitwert vorliegt. In Beispiel 00 liefert eine Abfrage ab der Gültigkeitsgrenze keinen Wert, selbst wenn du die Uhr kurz zuvor korrigiert hast. Eine Korrektur verlängert die Gültigkeit nicht. Auch ein Zählerstand kann unbrauchbar werden: Liegen zwei Abfragen zu weit auseinander, lässt sich unter Umständen nicht mehr feststellen, um wie viele Takte der Zähler weitergelaufen ist.
Die Uhr auf dem Board prüfen
Wenn du von der Simulation auf ein Board wechselst, hilft dir das ESP32-S3-Schaubild zur Zeitarchitektur. Es zeigt den Zeitpfad im W12: von der lokalen Zeitbasis und der Ereigniserfassung bis zur Softwareuhr. Wähle einen Block aus, um die passenden Prüfschritte zu sehen. Wächst der Fehler stetig, prüfe zuerst die Abstände in Zählertakten und ihre Umrechnung. Schwanken die Zeitstempel unter Last, kläre, ob du den Zeitpunkt des Ereignisses erfasst hast oder erst den Moment, in dem die Software es verarbeitet hat. Fehlt nach einem Neustart oder einer Lücke plötzlich die Zeit, prüfe, ob der Zähler lückenlos weiterlief und ob die Uhr noch eine brauchbare Referenz hat.
Um den Unterschied zwischen Gang und Phase selbst zu sehen, starte Beispiel 00 am Computer und kehre das Vorzeichen der Gangkorrektur um. Überlege vor dem nächsten Lauf, in welche Richtung die Abweichung wächst. In Teil 2 leitet die Uhr die Korrektur aus Bluetooth-Beobachtungen ab. ESP32-Sensoren über BLE synchronisieren