Den kleinen Seeed Studio XIAO ESP32-C6 habe ich bereits in einem separaten Beitrag vorgestellt. Dieses Mal geht es um das passende XIAO Expansion Board, das den Mikrocontroller um einige nützliche Funktionen erweitert. Dazu gehören unter anderem ein OLED-Display, ein Buzzer, verschiedene Grove-Schnittstellen und eine Echtzeituhr – kurz RTC.
In diesem Beitrag beschäftigen wir uns ausschließlich mit dieser RTC. Ich zeige dir, wie du Datum und Uhrzeit mit MicroPython einstellst, anschließend wieder ausliest und die Zeitdaten in deinen eigenen Projekten weiterverwendest.




Transparenzhinweis: Das Seeed Studio XIAO Expansion Board inklusive XIAO ESP32-C6 wurde mir von OpenELAB kostenfrei für diesen Beitrag zur Verfügung gestellt. Auf den Inhalt und meine Bewertung wurde kein Einfluss genommen.
Du findest den XIAO ESP32-C6 hier:
- bei OpenELAB (Affiliate-Link)
- direkt bei Seeed Studio
Was ist eine RTC?
Die Abkürzung RTC steht für Real-Time Clock, auf Deutsch Echtzeituhr. Dabei handelt es sich um einen speziellen Baustein, der Datum und Uhrzeit unabhängig vom eigentlichen Programm des Mikrocontrollers verwaltet.
Auf dem XIAO Expansion Board ist dafür eine PCF8563-RTC verbaut. Eine eingesetzte CR1220-Knopfzelle versorgt die Echtzeituhr auch dann, wenn der XIAO ESP32-C6 nicht über USB oder eine andere Stromquelle mit Energie versorgt wird. Dadurch läuft die eingestellte Uhrzeit weiter und muss nicht nach jedem Neustart erneut gesetzt werden.
Die RTC kennt allerdings weder eine Zeitzone noch die Sommer- und Winterzeit. Sie speichert und zählt lediglich die Werte weiter, die wir zuvor eingestellt haben. Die Umrechnung in eine bestimmte Zeitzone muss deshalb bei Bedarf durch das Programm erfolgen.
Benötigte Hard- und Software
Für dieses Projekt benötigst du neben dem XIAO ESP32-C6 das passende Expansion Board. Auf diesem befinden sich sowohl die PCF8563-Echtzeituhr als auch das OLED-Display, auf dem wir später Datum und Uhrzeit anzeigen.
Hardware
Für dieses Projekt benötigst du:
- einen Mikrocontroller aus der Seeed-Studio-XIAO-Familie
- das XIAO Expansion Board
- eine CR1220-Knopfzelle für die RTC
- ein USB-C-Datenkabel
- einen Computer mit einem freien USB-Anschluss
Das XIAO Expansion Board ist nicht ausschließlich für den XIAO ESP32-C6 vorgesehen. Es kann auch mit verschiedenen anderen Mikrocontrollern aus der XIAO-Familie verwendet werden, beispielsweise dem XIAO ESP32-S3, XIAO ESP32-C3 oder XIAO RP2040. Wichtig ist vor allem der einheitliche Formfaktor des XIAO-Ökosystems.

In diesem Beitrag verwende ich den Seeed Studio XIAO ESP32-C6. Wenn du einen anderen XIAO einsetzt, können sich die GPIO-Nummern und damit die Initialisierung der I²C-Schnittstelle unterscheiden. Die grundsätzliche Kommunikation mit der PCF8563-RTC bleibt jedoch gleich.
Falls dein XIAO noch keine Stiftleisten besitzt, musst du diese zunächst anlöten. Nur so kann der Mikrocontroller auf das Expansion Board gesteckt werden. Achte beim Einsetzen darauf, den XIAO richtig ausgerichtet und mittig in die beiden Buchsenleisten zu stecken.
Die CR1220-Knopfzelle sorgt dafür, dass die RTC auch bei unterbrochener USB-Stromversorgung weiterläuft. Für einen ersten Funktionstest ist sie nicht zwingend erforderlich. Ohne Knopfzelle kann die eingestellte Uhrzeit jedoch verloren gehen, sobald das Expansion Board nicht mehr mit Strom versorgt wird.
Software
Für die Programmierung verwende ich MicroPython und die Entwicklungsumgebung Thonny. Folgende Software beziehungsweise Dateien werden benötigt:
- eine aktuelle MicroPython-Firmware für den XIAO ESP32-C6
- die Entwicklungsumgebung Thonny
- der MicroPython-Treiber
ssd1306.pyfür das OLED-Display - die im Laufe dieses Beitrags erstellte Datei
xiao_rtc.py
Mit der Datei xiao_rtc.py greife ich später aus eigenen Projekten auf die RTC zu. Die darin enthaltene Klasse XiaoRTC stellt mir einfache Methoden bereit, mit denen ich Datum und Uhrzeit setzen, auslesen, prüfen und als formatierten Zeitstempel ausgeben kann.
RTC und OLED über I²C ansprechen
Sowohl die PCF8563-RTC als auch das OLED-Display des XIAO Expansion Boards werden über I²C angesprochen. Bei I²C können mehrere Geräte dieselben beiden Datenleitungen verwenden. Damit der Mikrocontroller sie unterscheiden kann, besitzt jedes Gerät eine eigene Adresse.
Beim XIAO ESP32-C6 werden dafür die folgenden Anschlüsse verwendet:
| Funktion | XIAO-Pin | GPIO |
|---|---|---|
| SDA | D4 | GPIO22 |
| SCL | D5 | GPIO23 |
Das OLED-Display und die RTC sind auf dem Expansion Board bereits mit diesen Anschlüssen verbunden. Zusätzliche Kabel werden daher nicht benötigt.
I²C-Geräte suchen
Mit einem kurzen I²C-Scan prüfe ich nun, welche Geräte der XIAO ESP32-C6 am gemeinsamen Bus erkennt.
from machine import I2C, Pin
i2c = I2C(
0,
sda=Pin(22),
scl=Pin(23),
freq=100000
)
devices = i2c.scan()
print("Gefundene I2C-Geräte:")
for address in devices:
print(hex(address))
Nachdem du das Skript gestartet hast, werden die gefundenen Geräte in der MicroPython-Konsole ausgegeben. Bei meinem XIAO Expansion Board in der Revision 1.2 erscheint folgende Ausgabe:
Für unser Projekt sind vor allem die folgenden beiden Adressen wichtig:
| I²C-Adresse | Komponente |
|---|---|
0x3C | OLED-Display |
0x51 | PCF8563-Echtzeituhr |
Die zusätzlich erkannte Adresse 0x6B wird für das Auslesen der RTC und die spätere Anzeige auf dem OLED nicht benötigt. Seeed stellt in der offiziellen Dokumentation derzeit lediglich den Schaltplan der älteren Boardrevision 1.0 bereit. Eine eindeutige Zuordnung des zusätzlichen I²C-Geräts auf meiner Revision 1.2 ist daher anhand der verfügbaren Unterlagen nicht möglich.
Der MicroSD-Kartenleser ist nicht für die Adresse 0x6B verantwortlich. Er wird über die SPI-Schnittstelle angesprochen und verwendet D2 als Chip-Select-Leitung. SPI-Geräte erscheinen bei einem I²C-Scan nicht.
Für den weiteren Verlauf ist entscheidend, dass mindestens die Adressen 0x3C und 0x51 erkannt werden. Damit wissen wir, dass der XIAO sowohl das OLED-Display als auch die PCF8563-RTC über den gemeinsamen I²C-Bus erreichen kann.
Sollte eine der beiden Adressen fehlen, überprüfe zunächst, ob der XIAO richtig auf dem Expansion Board sitzt. Verwendest du einen anderen Mikrocontroller aus der XIAO-Familie, musst du gegebenenfalls die GPIO-Nummern für SDA und SCL anpassen.
RTC zum ersten Mal auslesen
Nachdem die PCF8563 beim I²C-Scan unter der Adresse 0x51 gefunden wurde, können wir erstmals ihre Zeitregister auslesen. Dabei erhalten wir bereits Werte für Datum und Uhrzeit – auch wenn die RTC noch nicht korrekt eingestellt wurde.
Die PCF8563 speichert ihre Zeitinformationen in sieben aufeinanderfolgenden Registern. Die einzelnen Werte liegen im sogenannten BCD-Format vor. Damit wir sie als normale Zahlen verwenden können, müssen wir sie nach dem Auslesen zunächst umwandeln.
Erstelle in Thonny ein neues Skript und füge den folgenden Code ein:
from machine import I2C, Pin
RTC_ADDRESS = 0x51
i2c = I2C(
0,
sda=Pin(22),
scl=Pin(23),
freq=100000
)
def bcd_to_decimal(value):
return (value >> 4) * 10 + (value & 0x0F)
data = i2c.readfrom_mem(RTC_ADDRESS, 0x02, 7)
second = bcd_to_decimal(data[0] & 0x7F)
minute = bcd_to_decimal(data[1] & 0x7F)
hour = bcd_to_decimal(data[2] & 0x3F)
day = bcd_to_decimal(data[3] & 0x3F)
weekday = data[4] & 0x07
month = bcd_to_decimal(data[5] & 0x1F)
year = 2000 + bcd_to_decimal(data[6])
voltage_low = bool(data[0] & 0x80)
print("Ausgelesene RTC-Daten:")
print("Datum: {:02d}.{:02d}.{:04d}".format(day, month, year))
print("Uhrzeit: {:02d}:{:02d}:{:02d}".format(hour, minute, second))
print("Wochentag:", weekday)
if voltage_low:
print("Warnung: Die RTC-Zeit ist möglicherweise nicht gültig.")
Die Ausgabe kann beispielsweise wie folgt aussehen:
Das ausgelesene Datum 10.14.2142 kann offensichtlich nicht stimmen: Einen Monat 14 gibt es nicht und auch das Jahr liegt außerhalb des erwarteten Bereichs. Die PCF8563 liefert zwar bereits Inhalte aus ihren Zeitregistern, diese wurden jedoch noch nicht korrekt initialisiert.
Zusätzlich ist das Voltage-Low-Flag gesetzt. Damit signalisiert die RTC, dass ihre Versorgungsspannung zwischenzeitlich zu niedrig war und die gespeicherten Zeitwerte nicht zuverlässig sind. Die ausgelesenen Daten dürfen daher noch nicht als gültiges Datum verwendet werden.
Unsere I²C-Kommunikation funktioniert trotzdem: Der XIAO ESP32-C6 konnte die sieben Zeitregister der PCF8563 erfolgreich auslesen. Im nächsten Schritt stellen wir Datum und Uhrzeit korrekt ein und prüfen die Werte anschließend erneut.
Datum und Uhrzeit der RTC einstellen
Nachdem wir die vorhandenen, aber noch ungültigen Registerinhalte ausgelesen haben, stellen wir nun ein korrektes Datum und die aktuelle Uhrzeit ein.
Auch beim Schreiben erwartet die PCF8563 die Werte im BCD-Format. Deshalb benötigen wir dieses Mal eine Funktion, die normale Dezimalzahlen in das entsprechende Format umwandelt.
Im folgenden Skript werden Datum und Uhrzeit zunächst über mehrere Konstanten festgelegt. Passe diese Werte vor dem Start an die aktuelle Zeit an:
from machine import I2C, Pin
RTC_ADDRESS = 0x51
i2c = I2C(
0,
sda=Pin(22),
scl=Pin(23),
freq=100000
)
# Datum und Uhrzeit vor dem Start anpassen
YEAR = 2026
MONTH = 8
DAY = 19
HOUR = 18
MINUTE = 45
SECOND = 0
# Montag = 0, Dienstag = 1, ..., Sonntag = 6
WEEKDAY = 2
def decimal_to_bcd(value):
return ((value // 10) << 4) | (value % 10)
def bcd_to_decimal(value):
return (value >> 4) * 10 + (value & 0x0F)
# Uhr anhalten
control = i2c.readfrom_mem(RTC_ADDRESS, 0x00, 1)[0]
i2c.writeto_mem(
RTC_ADDRESS,
0x00,
bytes([control | 0x20])
)
# Zeitregister vorbereiten
rtc_data = bytes([
decimal_to_bcd(SECOND),
decimal_to_bcd(MINUTE),
decimal_to_bcd(HOUR),
decimal_to_bcd(DAY),
WEEKDAY,
decimal_to_bcd(MONTH),
decimal_to_bcd(YEAR - 2000)
])
# Register 0x02 bis 0x08 schreiben
i2c.writeto_mem(RTC_ADDRESS, 0x02, rtc_data)
# Uhr wieder starten
i2c.writeto_mem(
RTC_ADDRESS,
0x00,
bytes([control & 0xDF])
)
print("Datum und Uhrzeit wurden gesetzt.")
# Werte zur Kontrolle erneut auslesen
data = i2c.readfrom_mem(RTC_ADDRESS, 0x02, 7)
second = bcd_to_decimal(data[0] & 0x7F)
minute = bcd_to_decimal(data[1] & 0x7F)
hour = bcd_to_decimal(data[2] & 0x3F)
day = bcd_to_decimal(data[3] & 0x3F)
weekday = data[4] & 0x07
month = bcd_to_decimal(data[5] & 0x1F)
year = 2000 + bcd_to_decimal(data[6])
voltage_low = bool(data[0] & 0x80)
print("Gespeicherte RTC-Daten:")
print("Datum: {:02d}.{:02d}.{:04d}".format(day, month, year))
print("Uhrzeit: {:02d}:{:02d}:{:02d}".format(hour, minute, second))
print("Wochentag:", weekday)
if voltage_low:
print("Warnung: Die RTC-Zeit ist möglicherweise nicht gültig.")
else:
print("Die RTC-Zeit ist gültig.")
Die Uhr wird vor dem Schreiben kurz angehalten. Anschließend übertragen wir alle sieben Zeitwerte gemeinsam in die Register 0x02 bis 0x08 und starten die RTC wieder.
Nach dem Start des Skripts sollte eine Ausgabe ähnlich der folgenden erscheinen:

Die Meldung bestätigt, dass das zuvor gesetzte Voltage-Low-Flag gelöscht wurde und die Zeitwerte jetzt verwendet werden können. Wenn du das reine Ausleseskript aus dem vorherigen Abschnitt erneut startest, sollte die Uhrzeit inzwischen weitergelaufen sein.
Bedeutung des Wochentags
In diesem Beispiel verwenden wir für die Wochentage Zahlen von 0 bis 6:
| Wert | Wochentag |
|---|---|
0 | Montag |
1 | Dienstag |
2 | Mittwoch |
3 | Donnerstag |
4 | Freitag |
5 | Samstag |
6 | Sonntag |
Der Wochentag muss zum eingestellten Datum passen. Für den 19. August 2026 verwende ich den Wert 2, da dieser Tag ein Mittwoch ist.
Hinweis zur Zeitzone
Die PCF8563 kennt weder Zeitzonen noch die automatische Umstellung zwischen Sommer- und Winterzeit. Sie zählt lediglich die Werte weiter, die wir in ihren Registern speichern.
Für eine einfache Uhr auf dem OLED kannst du die aktuelle lokale Uhrzeit einstellen. Wenn die Zeit später für Berechnungen oder für den Datenaustausch mit anderen Systemen verwendet werden soll, ist es häufig sinnvoller, die RTC auf UTC einzustellen und die lokale Uhrzeit erst im Programm zu berechnen.
Da ich die Werte in diesem Beispiel noch direkt im Quellcode eintragen muss, verwende ich im nächsten Schritt die wiederverwendbare Bibliothek xiao_rtc.py. Sie stellt eine einfache Schnittstelle bereit, über die ich Zeitstempel setzen, auslesen, prüfen und in unterschiedlichen Formaten ausgeben kann.
Wiederverwendbare Bibliothek für die RTC
Bisher habe ich die Register der PCF8563 direkt gelesen und beschrieben. Für die ersten Tests war das sinnvoll, weil dadurch sichtbar wurde, wie die Echtzeituhr im Hintergrund arbeitet. In meinen späteren Projekten möchte ich mich jedoch nicht jedes Mal erneut mit I²C-Adressen, Registern, Bitmasken und der Umwandlung des BCD-Formats beschäftigen.
Deshalb habe ich die Datei xiao_rtc.py erstellt. Die darin enthaltene Klasse XiaoRTC bildet eine einfache Schnittstelle zwischen meinem MicroPython-Programm und der PCF8563. Zum Setzen und Auslesen der Zeit benötige ich dadurch nur noch wenige verständliche Methoden. Die Kommunikation mit den Registern, die BCD-Umwandlung und die Behandlung der Zeitzone übernimmt die Klasse im Hintergrund.
Die fertige Datei kannst du hier herunterladen:
Die Bibliothek enthält zusätzlich eine ausführliche Dokumentation mit mehreren Anwendungsbeispielen. Dadurch findest du die wichtigsten Informationen auch direkt in der Datei, wenn du sie später in einem anderen Projekt verwendest.
Bibliothek auf den XIAO übertragen
Lade zunächst die Datei xiao_rtc.py herunter und öffne sie anschließend in Thonny. Die Bibliothek wird auf dem Mikrocontroller im Verzeichnis lib gespeichert.
Die Dateistruktur auf dem XIAO sieht anschließend folgendermaßen aus:

Falls das Verzeichnis lib noch nicht vorhanden ist, kannst du es über die Dateiansicht von Thonny auf dem MicroPython-Gerät anlegen. Speichere die Datei anschließend unter folgendem Pfad: /lib/xiao_rtc.py



Das eigentliche Projektprogramm bleibt als main.py im Hauptverzeichnis des Mikrocontrollers.
MicroPython durchsucht das Verzeichnis lib automatisch nach importierbaren Modulen. Deshalb kann ich die Klasse anschließend wie gewohnt in meinem Programm importieren:
from xiao_rtc import XiaoRTC
Eine Angabe des vollständigen Pfades ist beim Import nicht erforderlich.
I²C und Zeitzone festlegen
Zunächst initialisiere ich die I²C-Schnittstelle und erzeuge ein Objekt der Klasse XiaoRTC:
from machine import I2C, Pin
from xiao_rtc import XiaoRTC
i2c = I2C(
0,
sda=Pin(22),
scl=Pin(23),
freq=100000
)
rtc = XiaoRTC(
i2c,
timezone="+02:00"
)
Mit timezone="+02:00" lege ich einen festen Versatz von zwei Stunden gegenüber UTC fest. Die Bibliothek speichert die Zeit intern als UTC in der PCF8563 und rechnet sie beim Setzen und Auslesen automatisch um.
Verwende ich beispielsweise die lokale Uhrzeit 12:30 Uhr mit der Zeitzone +02:00, speichert die Bibliothek intern 10:30 Uhr in der RTC.
Diese Trennung ist besonders praktisch, wenn ich den Zeitstempel später für Berechnungen oder den Datenaustausch mit anderen Systemen benötige.
Hinweis zur Sommer- und Winterzeit
Die Bibliothek verwendet einen festen UTC-Versatz. Eine automatische Umstellung zwischen Sommer- und Winterzeit findet nicht statt, da MicroPython normalerweise keine vollständige Zeitzonendatenbank mitbringt.
Für Deutschland verwende ich üblicherweise:
| Zeitraum | Zeitzone |
|---|---|
| Winterzeit | +01:00 |
| Sommerzeit | +02:00 |
Den Versatz kann ich jederzeit ändern:
rtc.set_timezone("+01:00")
Dabei wird die in der RTC gespeicherte UTC-Zeit nicht verändert. Lediglich die daraus berechnete lokale Uhrzeit wird mit dem neuen Versatz ausgegeben.
Zeitstempel setzen
Zum Einstellen von Datum und Uhrzeit verwende ich die Methode set_timestamp():
rtc.set_timestamp("2026-08-19 19:22:54")
Der Zeitstempel muss dabei in folgendem Format übergeben werden:
YYYY-MM-DD HH:MM:SS
Die einzelnen Bestandteile bedeuten:
| Bestandteil | Bedeutung |
|---|---|
YYYY | vierstelliges Jahr |
MM | Monat |
DD | Tag |
HH | Stunde |
MM | Minute |
SS | Sekunde |
Die Bibliothek interpretiert den übergebenen Wert standardmäßig als lokale Zeit. Bei der zuvor eingestellten Zeitzone +02:00 wird der Zeitstempel daher vor dem Speichern automatisch in UTC umgerechnet.
Möchte ich direkt einen UTC-Zeitstempel speichern, kann ich die Umrechnung deaktivieren:
rtc.set_timestamp(
"2026-08-19 17:22:54",
local=False
)
Beide Beispiele speichern in diesem Fall denselben Zeitpunkt in der PCF8563.
Zeitstempel auslesen
Mit get_timestamp() lese ich die Zeit wieder aus:
print(rtc.get_timestamp())
Die Ausgabe erfolgt standardmäßig im ISO-ähnlichen Format:
2026-08-19 19:22:54
Dabei wird die in der RTC gespeicherte UTC-Zeit automatisch mit dem eingestellten Zeitzonenversatz in die lokale Zeit umgerechnet.
Benötige ich stattdessen den unveränderten UTC-Zeitstempel, verwende ich:
print(rtc.get_utc_timestamp())
Die Ausgabe lautet bei diesem Beispiel:
2026-08-19 17:22:54
Vorgegebene Datumsformate verwenden
Die Bibliothek enthält mehrere häufig verwendete Formatvorlagen:
| Konstante | Beispiel |
|---|---|
FORMAT_ISO | 2026-08-19 19:22:54 |
FORMAT_RFC3339 | 2026-08-19T19:22:54+02:00 |
FORMAT_GERMAN | 19.08.2026 19:22:54 |
FORMAT_DATE_ISO | 2026-08-19 |
FORMAT_DATE_GERMAN | 19.08.2026 |
FORMAT_TIME | 19:22:54 |
Das deutsche Datumsformat gebe ich beispielsweise folgendermaßen aus:
print(
rtc.get_timestamp(
XiaoRTC.FORMAT_GERMAN
)
)
Die Ausgabe lautet:
19.08.2026 19:22:54
Für einen Zeitstempel mit Zeitzonenangabe verwende ich das RFC-3339-Format:
print(
rtc.get_timestamp(
XiaoRTC.FORMAT_RFC3339
)
)
Ausgabe:
2026-08-19T19:22:54+02:00
Eigenes Format festlegen
Neben den vorgegebenen Formaten kann ich auch ein eigenes Muster übergeben:
print(
rtc.get_timestamp(
"%A, %d. %B %Y - %H:%M:%S"
)
)
Das Ergebnis lautet:
Mittwoch, 19. August 2026 - 19:22:54
Die Bibliothek unterstützt unter anderem folgende Platzhalter:
| Platzhalter | Bedeutung | Beispiel |
|---|---|---|
%Y | Jahr, vierstellig | 2026 |
%y | Jahr, zweistellig | 26 |
%m | Monat | 08 |
%d | Tag | 19 |
%H | Stunde | 19 |
%M | Minute | 22 |
%S | Sekunde | 54 |
%a | kurzer Wochentag | Mi |
%A | vollständiger Wochentag | Mittwoch |
%b | kurzer Monatsname | Aug |
%B | vollständiger Monatsname | August |
%z | UTC-Versatz | +02:00 |
%Z | Zeitzonenbezeichnung | UTC+02:00 |
%% | Prozentzeichen | % |
Damit kann ich die Ausgabe an das jeweilige Projekt anpassen, ohne die Bibliothek selbst verändern zu müssen.
Einzelne Zeitwerte verwenden
Benötige ich nicht den formatierten Zeitstempel, sondern die einzelnen Bestandteile, verwende ich get_datetime():
year, month, day, hour, minute, second = (
rtc.get_datetime()
)
print("Jahr:", year)
print("Monat:", month)
print("Tag:", day)
print("Stunde:", hour)
print("Minute:", minute)
print("Sekunde:", second)
Diese Variante ist besonders hilfreich, wenn ich das Datum für weitere Berechnungen benötige. In meinem späteren Projekt kann ich damit beispielsweise die aktuelle Mondphase bestimmen.
Für die UTC-Werte rufe ich die Methode mit local=False auf:
year, month, day, hour, minute, second = (
rtc.get_datetime(local=False)
)
Gültigkeit der RTC-Zeit prüfen
Die Bibliothek prüft beim Auslesen unter anderem das Voltage-Low-Flag und die Plausibilität der gespeicherten Werte. Vor der weiteren Verarbeitung kann ich deshalb kontrollieren, ob die RTC eine gültige Zeit enthält:
if rtc.is_valid():
print(rtc.get_timestamp())
else:
print("Die RTC muss zunächst eingestellt werden.")
Damit verhindere ich, dass ungültige Werte wie der zuvor ausgelesene Monat 14 in meinem eigentlichen Projekt weiterverarbeitet werden.
Welche Aufgaben übernimmt die Bibliothek?
Mit der Klasse XiaoRTC verstecke ich die technischen Details der PCF8563 hinter einer einfachen Schnittstelle. Die Bibliothek übernimmt für mich unter anderem:
- die Kommunikation mit der I²C-Adresse
0x51 - das Lesen und Schreiben der RTC-Register
- die Umwandlung zwischen Dezimalzahlen und BCD
- die automatische Berechnung des Wochentags
- die Prüfung von Datum und Uhrzeit
- die Erkennung eines Spannungsverlusts
- die Speicherung der RTC-Zeit in UTC
- die Umrechnung in eine lokale Zeitzone
- die Formatierung des Zeitstempels
Dadurch kann ich die Datei xiao_rtc.py in meinen späteren Projekten wiederverwenden, ohne mich erneut mit dem internen Aufbau der PCF8563 beschäftigen zu müssen.
Datum und Uhrzeit auf dem OLED anzeigen
Zum Abschluss zeige ich das aktuelle Datum und die Uhrzeit auf dem OLED-Display des XIAO Expansion Boards an. Da sowohl das Display als auch die PCF8563 am selben I²C-Bus angeschlossen sind, benötige ich keine zusätzlichen Kabel oder eine zweite Schnittstelle.
Für dieses Beispiel müssen sich die beiden Bibliotheken xiao_rtc.py und ssd1306.py im Verzeichnis lib befinden. Das eigentliche Programm speichere ich als main.py im Hauptverzeichnis des XIAO:

Programm für die OLED-Anzeige
In der Datei main.py initialisiere ich zunächst die gemeinsame I²C-Schnittstelle. Anschließend erzeuge ich jeweils ein Objekt für das OLED-Display und die RTC:
MicroPython-Quellcode zur Anzeige von Datum & Uhrzeit auf dem OLED-Display
from machine import I2C, Pin
from time import sleep
from ssd1306 import SSD1306_I2C
from xiao_rtc import XiaoRTC
OLED_WIDTH = 128
OLED_HEIGHT = 64
i2c = I2C(
0,
sda=Pin(22),
scl=Pin(23),
freq=100000
)
oled = SSD1306_I2C(
OLED_WIDTH,
OLED_HEIGHT,
i2c,
addr=0x3C
)
rtc = XiaoRTC(
i2c,
timezone="+02:00"
)
def centered_x(text):
text_width = len(text) * 8
return max(0, (OLED_WIDTH - text_width) // 2)
while True:
if rtc.is_valid():
values = rtc.get_datetime()
date_text = rtc.format_datetime(
values,
XiaoRTC.FORMAT_DATE_GERMAN
)
time_text = rtc.format_datetime(
values,
XiaoRTC.FORMAT_TIME
)
oled.fill(0)
oled.text(
"XIAO RTC",
centered_x("XIAO RTC"),
4
)
oled.text(
date_text,
centered_x(date_text),
26
)
oled.text(
time_text,
centered_x(time_text),
46
)
oled.show()
else:
oled.fill(0)
oled.text("RTC-Zeit", 32, 20)
oled.text("ungueltig!", 24, 38)
oled.show()
sleep(0.5)
Nach dem Start zeigt das OLED beispielsweise folgende Inhalte an:
Die Methode get_datetime() liest alle Bestandteile von Datum und Uhrzeit gemeinsam aus. Dadurch stammen Datum und Uhrzeit garantiert aus demselben Lesevorgang. Das ist vor allem während eines Tageswechsels wichtig.
Anschließend formatiere ich die Werte mit den bereits in der Bibliothek vorhandenen Formatvorlagen:
XiaoRTC.FORMAT_DATE_GERMAN XiaoRTC.FORMAT_TIME
Mit der Hilfsfunktion centered_x() berechne ich die horizontale Position der Texte. Die Standardschrift des SSD1306-Treibers ist acht Pixel breit. Aus der Anzahl der Zeichen kann ich deshalb näherungsweise bestimmen, an welcher Position der Text beginnen muss, damit er mittig auf dem 128 Pixel breiten Display erscheint.
Zeitzone anpassen
In diesem Beispiel verwende ich für die deutsche Sommerzeit den UTC-Versatz +02:00:
rtc = XiaoRTC(
i2c,
timezone="+02:00"
)
Während der Winterzeit ändere ich den Wert auf +01:00:
rtc = XiaoRTC(
i2c,
timezone="+01:00"
)
Die in der RTC gespeicherte UTC-Zeit muss dabei nicht erneut gesetzt werden. Die Bibliothek berechnet die angezeigte lokale Uhrzeit aus dem gewählten Versatz.
Wenn auf dem Display stattdessen die Meldung RTC-Zeit ungueltig! erscheint, konnte die Bibliothek keinen plausiblen Zeitwert auslesen. In diesem Fall muss ich Datum und Uhrzeit zunächst erneut setzen.
Damit kann ich die PCF8563 nun nicht nur einstellen und auslesen, sondern ihre Zeitdaten auch direkt in einem eigenen MicroPython-Projekt verwenden. Die Bibliothek xiao_rtc.py bildet dabei die wiederverwendbare Grundlage für weitere Projekte – beispielsweise für meine geplante Berechnung und Darstellung der aktuellen Mondphase.
Häufige Probleme und mögliche Lösungen
RTC verliert nach dem Ausschalten die Uhrzeit
Gehen Datum und Uhrzeit nach dem Trennen der USB-Verbindung verloren, überprüfe ich die CR1220-Knopfzelle. Sie versorgt die PCF8563 weiter, wenn das Expansion Board keine andere Stromversorgung erhält.
Mögliche Ursachen sind:
- es wurde keine CR1220-Knopfzelle eingesetzt
- die Knopfzelle ist leer
- die Knopfzelle wurde falsch herum eingesetzt
Nach einem Spannungsverlust kann das Voltage-Low-Flag gesetzt sein. In diesem Fall muss ich die RTC erneut einstellen.
Der JST-Anschluss und der Batterieschalter dienen dagegen der LiPo-Stromversorgung des XIAO und des Expansion Boards. Sie sind nicht für die Pufferung der RTC zuständig.
Angezeigte Uhrzeit weicht um eine oder zwei Stunden ab
Eine Abweichung um genau eine oder zwei Stunden deutet meistens auf einen falsch eingestellten UTC-Versatz hin. Für Deutschland verwende ich normalerweise:
+01:00während der Winterzeit+02:00während der Sommerzeit
Die Bibliothek nimmt keine automatische Umstellung zwischen Sommer- und Winterzeit vor. Den verwendeten Versatz muss ich deshalb bei Bedarf selbst anpassen:
rtc.set_timezone("+01:00")
oder:
rtc.set_timezone("+02:00")
Die in der RTC gespeicherte UTC-Zeit wird dabei nicht verändert.
RTC-Zeit wird als ungültig erkannt
Gibt rtc.is_valid() den Wert False zurück, sind entweder die gespeicherten Datumswerte unplausibel oder das Voltage-Low-Flag ist gesetzt. Das kann beispielsweise nach einer fehlenden oder unterbrochenen Stromversorgung auftreten.
In diesem Fall stelle ich Datum und Uhrzeit erneut ein:
rtc.set_timestamp("2026-08-19 19:22:54")
Anschließend kann ich die Gültigkeit erneut prüfen:
if rtc.is_valid():
print(rtc.get_timestamp())
else:
print("Die RTC-Zeit ist weiterhin ungültig.")
OLED-Display bleibt leer
Bleibt das OLED-Display leer, prüfe ich zunächst mit dem I²C-Scanner, ob die Adresse 0x3C gefunden wird. Anschließend kontrolliere ich, ob sich der benötigte Treiber unter diesem Pfad auf dem Mikrocontroller befindet:
/lib/ssd1306.py
Die Initialisierung muss außerdem zur erkannten Displayadresse passen:
oled=SSD1306_I2C(128,64,i2c,addr=0x3C)
Da sich RTC und OLED denselben I²C-Bus teilen, muss für beide Komponenten dasselbe I2C-Objekt verwendet werden.
Fazit und Ausblick
In diesem Beitrag habe ich gezeigt, wie ich die PCF8563-RTC auf dem XIAO Expansion Board mit MicroPython anspreche. Datum und Uhrzeit lassen sich nun einstellen, auslesen, als Zeitstempel formatieren und auf dem OLED-Display anzeigen. Mit der Bibliothek xiao_rtc.py steht mir dafür eine wiederverwendbare Grundlage für weitere XIAO-Projekte zur Verfügung.
Die manuelle Einstellung hat allerdings einen kleinen Nachteil: Ich muss die gewünschte Uhrzeit zunächst im Quellcode eintragen und anschließend das Programm starten. Zwischen dem Eintragen, Übertragen und Ausführen vergehen einige Sekunden. Dadurch kann die gespeicherte RTC-Zeit leicht von der tatsächlichen Uhrzeit abweichen.
Eine genauere und komfortablere Lösung besteht darin, die aktuelle Uhrzeit während der Laufzeit von einem NTP-Server abzurufen. Der XIAO ESP32-C6 verbindet sich dafür kurz mit dem WLAN, übernimmt die Netzwerkzeit und speichert sie in der RTC. Anschließend kann ich die WLAN-Schnittstelle wieder deaktivieren und die weitere Zeitmessung der stromsparenden Echtzeituhr überlassen.
Wie die automatische Synchronisierung über einen NTP-Server funktioniert und wie ich das WLAN danach wieder abschalte, zeige ich dir im kommenden Beitrag.
Letzte Aktualisierung am: 14. September 2026


