はじめに
Raspberry Pi は電源を切ると時刻を保持する機能がないため時間が狂ってしまいます。
なので時刻を保持できるという RTC モジュールの DS3231SN を購入。2週間足らずで到着しました。
デバイスの認識を確認
繋いだ後に i2cdetect で接続されていることを確認。これは DS3231 は $ I^2C $ の68番。
> /usr/sbin/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: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
見えました。
ドライバの読み込み
ドライバ (カーネルモジュール) を確認。
> sudo modprobe -c | grep ds3231
alias i2c:ds3231 rtc_ds1307
alias of:N*T*Cmaxim,ds3231 rtc_ds1307
alias of:N*T*Cmaxim,ds3231C* rtc_ds1307
ドライバはあるけどロードされていない模様。
i2c:ds3231 のドライバは rtc_ds1307 で良いらしい。
ds1307 のドライバをロード。
> sudo modprobe rtc_ds1307
> sudo lsmod | grep ds1307
rtc_ds1307 24576 0
hwmon 16384 1 rtc_ds1307
> echo ds3231 0x68 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
ds3231 0x68
> /usr/sbin/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: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
認識されました?認識されなかったら一度、モジュールをアンロードしてからロードしなおしてみて下さい。
> sudo modprobe -r -v rtc_ds1307
> sudo modprobe -v rtc_ds1307
-v は verbose (饒舌) モードです。
RTCへの時刻の書き込みと読み出し
とりあえず電池なしで引っこ抜き、挿し直して RTC の時刻を確認する。
> sudo hwclock -r && date
2000-01-01 09:00:12.413597+0900
Fri May 3 04:09:39 JST 2019
バックアップ電池が無いと 2000年 1月 1日になるのか。
時刻を書き込み、再度読み出してみる。
> sudo hwclock -w
> sudo hwclock -r && date +%F_%T.%N
2019-05-03 04:19:00.644180+0900
2019-05-03_04:19:00.538989379
お、時間が読めた!
ntpd が起動しているからか暫く待っていると自動的に書き込まれるようです。RTC へセットする値が 1秒単位なので 1秒ぐらいはずれても仕方ないですね。
ntpd が起動していると勝手に時刻を書き込むということは、起動時に時刻を読めれば良い訳ですね。
まず、ドライバーが読まれるように sudo vi /boot/config.txt して最後に追加。
dtoverlay=i2c-rtc,ds3231
起動時にドライバを読み込み、時間を合わせるように
あとは、本物があるので fake-hwclock は解除。
> sudo systemctl stop fake-hwclock
> sudo systemctl disable fake-hwclock
> sudo apt remove fake-hwclock
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
これを削除するには 'sudo apt autoremove' を利用してください。
以下のパッケージは「削除」されます:
fake-hwclock
アップグレード: 0 個、新規インストール: 0 個、削除: 1 個、保留: 0 個。
この操作後に 32.8 kB のディスク容量が解放されます。
続行しますか? [Y/n]
(データベースを読み込んでいます ... 現在 181085 個のファイルとディレクトリがインストールされています。)
fake-hwclock (0.11+rpt1) を削除しています ...
man-db (2.7.6.1-2) のトリガを処理しています ...
>
起動時に実行されるようにスクリプトを書く
以下、うまくいっていません
/etc/init.d/rtc_i2c に起動スクリプトを書く
#!/bin/sh
### BEGIN INIT INFO
# Provides: RTC clock
# Required-Start: mountdevsubfs
# Required-Stop: mountdevsubfs
# Should-Stop: umountfs
# X-Start-Before: checkroot
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Sync RTC clock and system clock time.
# Description: Load the RTC driver and set to system clock.
### END INIT INFO
HWCLOCK=/sbin/hwclock
MODPROBE=/sbin/modprobe
RTC_MODULE=rtc_ds1307
set -e
# Include core init functions if needed
. /lib/lsb/init-functions
case "${1:-}" in
stop)
$HWCLOCK -w
$MODPROBE -r -v $RTC_MODULE
log_end_msg $? || true
;;
start|reload|force-reload)
$MODPROBE $RTC_MODULE
echo ds3231 0x68 | /sys/class/i2c-adapter/i2c-1/new_device
$HWCLOCK -s
log_end_msg $? || true
;;
restart)
$0 stop ; sleep 2 ; $0 start
;;
show-time)
echo "hwclock: `$HWCLOCK -r`"
date +"OS time: %F %T.%N"
;;
*)
log_action_msg "Usage: ${0:-} {start|stop|status|restart|reload|force-reload|show-time}" || true
exit 1
;;
esac
変更内容を systemd に認識させる
> systemctl daemon-reload
> systemctl list-unit-files
> systemctl list-dependencies