Raspberry Pi: Hardware Clock DS3231

Die Raspberry Pi verfügen über keine batteriegepufferte Uhr. D.h. mit jedem Stromausfall verliert der Pi seine Uhrzeit. Durch fake-hwclock und NTP wird dieser Nachteil ausgeglichen, wenn eine LAN-Anbindung an einen NTP-Server besteht. Durch ein kleines Bauteil kann der Raspberry Pi um eine batteriegepufferte Uhr ergänzt werden.

RTC DS3231

Das Modell der DS3231 RTC muss nur an die richtige Stelle der GPIO Pins aufgesteckt werden.

RTC auf den GPIO Pins eines Raspberry Pi 4

Bei dem Gehäuse des Raspberry Pi sind die GPIO-Pins schön herausgeführt, aber leider passt der Deckel nicht mehr drauf, wenn die Pins belegt werden.

Nun muss dem Raspberry Pi nur noch mitgeteilt werden, dass er eine RTC hat. Dies geht on-the-fly, ohne reboot.

Zuerst können wir den Service fake-hwclock deaktivieren. Er wird nicht mehr benötigt. Wer mag, kann ihn mit dem dritten Befehl gänzlich entfernen.

sudo systemctl stop fake-hwclock 
sudo systemctl disable fake-hwclock
# Optional:
sudo apt remove fake-hwclock

Nun müssen wir die Tools für die Schnittstelle I2C installieren,

sudo apt install i2c-tools

und mit modprobe laden. Zusätzlich benötigen wir das Modul i2c-bcm2708, das nicht über raspi-config gestartet werden kann.

sudo dtparam ic2_arm=on
sudo modprobe i2c-dev
sudo modprobe i2c-bcm2708

I2C kann mit raspi-config aktiviert werden. Alternativ lässt es sich manuell in der Datei /boot/config.txt aktivieren, was verständlicherweise einen reboot erfordert. raspi-config ändert nicht nur die Datei, sondern startet die Module zusätzlich über modprobe.

# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on

Permanent werden diese Module in /etc/modules oder in /etc/modules-load.d/i2c.conf geladen. Wobei der Eintrag i2c-dev mit raspi-config erfolgt, der Eintrag für i2c-bcm2708 muss manuell erfolgen.

# Konfiguration RTC in /etc/modules-load.d/i2c.conf
ic2-bcm2708
i2c-dev

i2c-bcm2708 ist in älteren Beschreibungen enthalten, aber wohl nicht mehr erforderlich um die RTC DS3231 anzusprechen. Dies wird mit dem folgenden Befehl in der erledigt.

On-the-fly lässt sich die Uhr mit folgendem Befehl aktivieren:

pi@gateway:~ $ sudo dtoverlay i2c-rtc ds3231

Permanent wird dies in der Datei /boot/config.txt aktiviert. Hier für gibt es keinen vordefinierten Eintrag, der nur entkommentiert werden muss.

[all]
dtoverlay=i2c-rtc,ds3231

Eine Alternative aus älteren Beschreibungen dazu ist der folgende Befehl:

pi@gateway:~ $ echo ds3231 0x68 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device"

Hier habe ich auch Empfehlungen gefunden diesen Befehl im Startprozess einzubauen. Dies erübrigt sich aber mit dem Eintrag in /boot/config.txt.

Auch Änderungen in Servies des systemd sind nicht erforderlich.

In einem Fall, bei dem ich I2C nicht mittels raspi-config und ohne dtparam i2c_arm=on aktiviert habe, dann scheitert dieser Befehl bei mir mit der Meldung:

pi@gateway:~ $ echo ds3231 0x68 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
tee: /sys/class/i2c-adapter/i2c-1/new_device: No such file or directory
ds3231 0x68

i2cdetect

Nach der Aktivierung I2C mittels raspi-config sollte der Befehl i2cdetect folgende Ausgabe liefern. Wichtig ist dabei die ’68‘ in der Zelle ’68‘. Anstelle der ’68‘ kann ‚UU‘ stehen, dann die Prüfung der Adresse wurde der Scan der Adresse übersprungen, weil die Adresse von einem Treiber belegt ist. Was wir am Ende ja wollen.

pi@gateway:~ $ sudo i2cdetect -y 1
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --  
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --  
70: -- -- -- -- -- -- -- --

Anschließend war auch der obige Befehl echo ds3231 0x68 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device erfolgreich.

Fast fertig

Jetzt sollte der Befehl hwclock funktionieren und die Uhrzeit der RTC anzeigen.

pi@gateway:~ $ sudo hwclock 
2000-02-21 10:54:57.169540+01:00

Bei einer neuen RTC wird die Uhr eine Zeit im Jahr 2000 anzeigen. Wir müssen die Uhr erst auf die aktuelle Zeit setzen. Dies geschieht am einfachsten mit ntpd. Normalerweise läuft NTP auf jedem Raspberry Pi. Der Service muss allerdings erst beendet werden, bevor ntpd mit dem Parametern -gq getartet wird, um die Uhrzeit zu setzen.

sudo systemctl stop ntp
sudo ntpd -gq
sudo systemctl start ntp

Die Ausgabe von ntpd -gq ist etwas länger, deshalb habe ich sie hier weggelassen.

Alternativ lässt sich die Uhrzeit per Hand setzen, was allerdings zu einer weniger genauen Zeit führt. Und läuft:

pi@gateway:~ $ sudo hwclock  
2022-04-09 14:35:25.726381+02:00

Es kann sein, dass die Hardwareuhr etwas verzögert die neue Zeit anzeigt. Die in einer Zeile eingegebene Befehlsfolge:

pi@gateway:~ $ sudo systemctl stop ntp;sudo ntpd -gq;sudo systemctl start ntp;sudo hwclock 

zeigte die alte Zeit an. Erst der einige Sekunden später abgesetzte Befehl sudo hwclock, zeigte die richtige Zeit.

Alles auf Github

Unter github.com gibt es das ganze Verfahren als Rolle realtimeclock in ansible-RaspberryPi.

Anmerkung:

In manchen Beschreibungen wird /lib/udev/hwclock-set geändert. Der Grund ist mir nicht einsichtig, denn auf Rechnern mit CMOS Uhr läuft das Script ohne diese Änderungen.

Quellen:

  1. Pi MyLife Up: Adding a Real Time Clock (RTC) to the Raspberry Pi
  2. Raspberry Pi Geek 03/2015: Echtzeituhr-Modul DS3231 sorgt für genaue Zeitangaben
  3. S 3: Einrichten einer RealTimeClock (RTC) auf dem Raspberry Pi