Raspberry Pi に DS1307 を導入した
【RaspberryPi】RTC DS1307 導入方法まとめ
を読みながら作業したら問題なかったんだけど、上記の記事との差異や、追加情報を。
ハードウェアとOS
ラズパイは:
- Raspberry Pi 3 Model B+
- Linux raspberrypi 4.19.50-v7+ #896 SMP Thu Jun 20 16:11:44 BST 2019 armv7l GNU/Linux
で。RTC は 「Raspberry Pi RTC Expansion Module v1.1Maxim DS1307チップ」というのを入手した。1000円前後。
別途ボタン電池 CR1220 必要。こちらは 150円前後。
起動
ハードウェアをつなげないと設定できないので、電池を入れてラズパイにさしてから起動する。
さし方は
DS1307 RTC Module with BAT for Raspberry Pi SKU: EP-0059 ― How to Connect:
の写真が参考になる。
ちなみに、RTC をラズパイにさした状態だと手元のケースだとふたが閉まらなくなる。どうしたものか。
I2C の有効化
$ sudo raspi-config
として、
5 Interfacing Options
→ P5 I2C
を選ぶと
Would you like the ARM I2C interface to be enabled?
と聞かれるので <はい>
を選ぶ。
必要なツールのインストール
上記の記事だと i2c-tools
も入れるようになっていたが、私の手元だとインストール済みだった。
というわけで、
$ sudo apt-get install ntpdate
と、ntpdate
を入れる。これはあとで、起動スクリプトで使う。
RTCモジュールを起動時に読み込むようにする
/etc/modules
というファイルがあり、そこにモジュール名を書いておくと起動時に読み込んでくれるらしい。
上記の記事だと i2c-dev
も書き込むようになっていたが、手元の環境ではすでに i2c-dev
は /etc/modules
に書いてあったので、 rtc-ds1307
だけを書き込むことにした。
$ sudo echo rtc-ds1307 >> /etc/modules
-bash: /etc/modules: 許可がありません
が、失敗。仕方ないので root で実行。
$ su
# echo rtc-ds1307 >> /etc/modules
# exit
RTC の I2C のアドレス番号を確認する
こんな感じ:
$ 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: -- -- -- -- -- -- -- --
私の場合は 0x68 だった。
ちなみに -y
は「Disable interactive mode.」。1
はi2c bus の番号らしい。
デバイスアダプタ(?)の登録
続いて、 /sys/class/i2c-adapter/i2c-1/new_device
に RTC を登録する。この、 new_device
というファイルは、 ls -l
すると
--w------- 1 root root 4096 8月 15 11:53 new_device
となっていて、普通のファイルではないことがわかる。このファイルにデバイス名とアドレス番号を
$ su
# modprobe rtc-ds1307
# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
という具合に書き込む。
modprobe
は、Linux カーネルにモジュールを追加するらしい。
modprobe
にわたす引数と new_device
に書き込むデバイス名が合っていないので不安になるけどこれでいいらしい。
うまくできると、 i2cdetect
の出力が 68
から UU
に変わる。UU
は「ここはドライバが使っているよ」という意味。
$ 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: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
RTC 以外の時計を無効にする
RTC 以外の時計があると競合して(というより、RTC が負けて)RTCが機能しないので止める必要がある。
特に fake-hwclock
は バッテリバックアップされた RTC がない環境専用なので全く必要ない。
ntp はあとで電源 on 時に参照するようになっているのでここは一旦 off にする。
こんな具合。ここは前掲の記事と全く同じ。
$ sudo apt-get install chkconfig
$ sudo chkconfig ntp off
$ sudo apt-get remove fake-hwclock
$ sudo dpkg --purge fake-hwclock
起動時に RTC の内容をシステムクロックに取り込む
起動スクリプト rc.local
で、以下の変更を加える:
- npt サーバー
ntp.nict.jp
から時刻を読み取ろうとしてみる - 読み取れたら、その結果を RTC に書き込む
- 読み取れなかったら、RTC の時刻をシステム時間とする
というわけで、vim
などを使って rc.local
を以下のように書き換える
変更前:
# !/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
exit 0
変更後:
# !/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
ntpdate -v ntp.nict.jp
if [ $? = 0 ]; then
hwclock -w # システムクロック => RTC
else
hwclock -s # システムクロック <= RTC
fi
exit 0
起動時にネットワーク接続を待たないようにする
このままだと、起動時にネットワーク接続を待ってしまうんだと思う。
そこで、
$ sudo raspi-config
として、起動オプションを変更する。
3 Boot Options
→ B2 Wait for Network at Boot
を選ぶと
「Would you like boot to wait until a network connection is established?
」と聞かれるので「<いいえ>
」を選ぶ。
RTC を正しい時刻にする
ntp が使える環境で再起動すると、先程の rc.local
にあるスクリプトのおかげで時刻が正しくなる。というわけで、再起動。
そして
$ sudo hwclock --get
2019-08-15 13:58:39.252902+09:00
とすると、RTC が正しい時刻になっていることがわかる。
ネットワークのない環境での動作確認
まだやっていない。