Raspberry Pi: RTC の接続
概要
Raspberry Pi は RTC1 (real-time clock) を搭載しておらず、シャットダウン時に時刻を記録して次の起動時にはその時刻から開始するように動作する。ネットワークに接続していれば起動後すぐに NTP サーバと時刻同期を行って概ね正しい時刻で動作するが、オフライン環境や NTPd をオフにしている状態ではシステム時刻が実際の時刻よりどんどん遅れることになる。
Raspberry Pi に RTC モジュールを追加することで電源のオン/オフを行っても正しいシステム時刻を示すようにすることができる。この記事では実際に RTC モジュールを取り付けてシステムが RTC の時刻を使用するように設定する。
- 1コンピュータ内蔵の時計や回路。電池などのバックアップによりコンピュータの電源を落とした状態でも時間を刻み続けることができる。ハードウェアクロック、CMOS に時刻を記録し続けるため CMOS クロックなどとも呼ばれる。
Table of Contents
ここでは SEEED の DS1307 クロックの RTC を使用している。RTC 単体であれば 500 円程度で購入することができる。それ以外には電源制御モジュールのように RTC とセットになっている物を選んでも良い。
この RTC モジュールはバックアップ電池に 3V CR1225 を使用する。CR1225 は国内の家電店では取り扱いがないため、ネットで購入するか BR1225 で代用するしかない点に注意 (応急処置的に高さが 0.5mm 低い 3V CR1220 も使えないことはない)。
RTC による時刻合わせ
先に raspi-config
を使って RTC を取り付ける I²C インターフェースを有効化する。
まずは RTC 取り付け前の状態を確認してみよう。timedatectl
を実行すると RTC time が n/a になっていて時刻制御に使用できる RTC が存在しないことが分かる。また i2cdetect -y 1
の実行結果は I²C インターフェース上で何のデバイスも検出していないことを示している。
pi@pirite:~ $ timedatectl
Local time: Sun 2022-02-06 16:18:40 JST
Universal time: Sun 2022-02-06 07:18:40 UTC
RTC time: n/a
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: no
NTP service: n/a
RTC in local TZ: no
pi@pirite:~ $ 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: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
RTC の接続
次に Raspberry Pi に RTC を設置しよう。取り付けで特に難しいことはなく、本体の電源を落として Fig 3 に示すように I²C インターフェースに差し込むだけで良い。
RTC の有効化
RTC モジュールの取り付けが完了したら次は Raspberry Pi を起動して RTC を有効にする。まずはシステムが対応している RTC のクロックを確認しよう。
pi@pirite:~ $ dtoverlay -h i2c-rtc
Name: i2c-rtc
Info: Adds support for a number of I2C Real Time Clock devices
Usage: dtoverlay=i2c-rtc,<param>=<val>
Params: abx80x Select one of the ABx80x family:
AB0801, AB0803, AB0804, AB0805,
AB1801, AB1803, AB1804, AB1805
bq32000 Select the TI BQ32000 device
ds1307 Select the DS1307 device ← 今回設置した RTC に搭載されているクロック
ds1339 Select the DS1339 device
ds1340 Select the DS1340 device
ds3231 Select the DS3231 device
...
取り付けた RTC のクロックに対応していることを確認したら、/boot/config.txt
を開いてそのクロックを指定する。
pi@pirite:~ $ sudo vim /boot/config.txt
# Enable RTC
dtoverlay=i2c-rtc,ds1307
Raspberry Pi を再起動して RTC が認識されていることを確認する。次の例は RTC time から時刻を参照できており、I²C バス上のアドレス 0x68 がシステムによって使用されていることを示している。
pi@pirite:~ $ timedatectl
Local time: Tue 2022-02-08 22:19:44 JST
Universal time: Tue 2022-02-08 13:19:44 UTC
RTC time: Tue 2022-02-08 13:19:42
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: no
NTP service: n/a
RTC in local TZ: no
pi@pirite:~ $ 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: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
システム時刻で RTC 時刻を更新
OS の管理するシステム時刻と、RTC のハードウェアクロックは別々に時刻を管理している。
有効化したばかりの RTC は間違った時刻を示していることがある。時刻はコマンドライン上で指定もできるが、システム時刻が正確ならシステム時刻で更新するのが確実なので、まずシステム時刻を NTP サーバと同期しよう。
以下のコマンドで ntpd
が active (running)
状態になっていれば問い合わせ時刻を確認する。以下の例では 16:06 (現在 16:18 なので 12 分前) にプールに設定されている NTP サーバに要請していることがわかる。
pi@pirite02:~ $ sudo systemctl status ntp
● ntp.service - Network Time Service
Loaded: loaded (/lib/systemd/system/ntp.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2022-02-11 16:06:47 JST; 1min 34s ago
Docs: man:ntpd(8)
Process: 4807 ExecStart=/usr/lib/ntp/ntp-systemd-wrapper (code=exited, status=0/SUCCESS)
Main PID: 4813 (ntpd)
Tasks: 2 (limit: 780)
CPU: 181ms
CGroup: /system.slice/ntp.service
└─4813 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 115:124
Feb 11 16:06:51 pirite ntpd[4813]: Soliciting pool server 2001:9a8:0:e:1337:0:123:1
Feb 11 16:06:51 pirite ntpd[4813]: Soliciting pool server 160.16.113.133
...
Feb 11 16:06:54 pirite ntpd[4813]: Soliciting pool server 194.0.5.123
あるいは意図的に ntpd
を停止しているのであれば ntpdate
を使って同期する。
pi@pirite:~ $ sudo apt install -y ntpdate
pi@pirite:~ $ ntpdate ntp.nict.jp
システム時刻が正しいことを確認したら、次のコマンドで RTC 時刻をシステム時刻で更新する。
pi@pirite:~ $ sudo hwclock --systohc
起動時にシステム時刻を RTC 時刻で更新
/etc/udev/rules.d/85-hwclock.rules
に以下のようなファイルを作成する。
pi@pirite:~ $ sudo vim /etc/udev/rules.d/85-hwclock.rules
# On the Raspberry Pi the RTC isn't available when systemd tries,
# set the time from RTC now when it is available.
KERNEL=="rtc0", RUN+="/sbin/hwclock --rtc=$root/$name --hctosys"
この設定後に WiFi をオフにして Ethernet ケーブルと電源ケーブルを抜いた状態で暫く放置し、起動した後に確認すると、システム時刻、RTC 時刻、電波時計 (G-SHOCK) がすべて同じ時刻を示していた。
fake-hwclock の削除
RTC を構成した後も Raspberry Pi がデフォルトで使用している fake-hwclock
を残しておくことができる。しかしこれを削除しておくことで (電池切れなどにより) RTC が機能していないときに 2016-11-03 のような明らかにおかしい時間となって気づきやすい。残しても削除してもどちらでも良いが、削除する場合は apt
から行うことができる。
pi@pirite:~ $ sudo apt purge fake-hwclock