はじめに
2016年11月、Raspberry Pi2にRTCモジュールを接続しました。
Raspberry Piには、RTC(Real Time Clock)というハードウェア・クロックが搭載されていません。そのため、ブート直後は前回シャットダウン時の日時になります。インターネットに接続状態の場合は、NTPサーバーと同期して日時を補正してくれます。しかし、インターネットに接続できない場合やNTPサーバーにアクセスできない場合は正確な日時が設定されません。
そこで、バッテリーバックアップ付きのRTCモジュールを接続することにより、インターネットに接続していない状態でブートした場合でも日時を保持できるようにしました。
「Raspberry Pi RTC 拡張モジュール DS1307」を購入して接続しました。この拡張モジュールは、MAXIM社の「DS1307」チップを使用しています。サイズは23mm×26mmの小型のボードで、10ピンのコネクタで接続します。時計はCR1220電池でバッテリーバックアップされています。
Raspberry Pi2のRaspbian jessie OSで動作確認しました。
pi@pi2note:~ $ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 8.0 (jessie) Release: 8.0 Codename: jessie
リアルタイムクロック RTC DS1307 とは
maxim社のホームページに DS1307 の説明がありました。
DS1307は、I2Cインターフェースでマイクロプロセッサと接続するRTCデバイスです。
[説明]
シリアルリアルタイムクロック(RTC)のDS1307は低電力、56バイトNV SRAM内蔵の完全なバイナリコードの10進(BCD)クロック・カレンダです。アドレスおよびデータはI2C、双方向バスによりシリアル転送されます。クロック・カレンダは、秒、分、時間、曜日、日、月、年の各情報を提供します。月の最後の日付は、うるう年の修正を含めて、31日より少ない月について自動的に調整されます。クロックは、24時間形式もしくはAM/PM表示付き12時間形式のいずれかで動作します。DS1307は、電源障害を検出して自動的にバックアップ電源に切り換える電源検出回路を内蔵しています。デバイスがバックアップ電源によって動作する際にもタイムキーピング動作は維持されます。
[主な特長]
- 全計時機能を完全に管理
- リアルタイムクロックは秒、分、時間、日、月、曜日、および年をカウント(2100年までうるう年を補正)
- 56バイト、バッテリーバックアップ、汎用RAMは書き込み回数が無制限
- 簡素なシリアルポートによってほとんどのマイクロコントローラと接続可能 (I2Cシリアルインターフェース)
データシートにアドレスマップの記述がありました。7バイトの領域に「年/月/日/曜日/時/分/秒」の情報をBCD形式で記録しており、リアルタイムにクロックを刻んでいます。
I2Cとは
I2C(Inter-Integrated Circuit)とは、周辺デバイスとのシリアル通信の方式です。1台のマスターに複数のスレーブデバイスを接続することが可能で、スレーブデバイスはアドレスで区別します。マスターとスレーブは、シリアルデータ (SDA) とシリアルクロック (SCL) の2本の信号線で接続します。
Raspberry Pi2のGPIOポートコネクタ(40ピン)にI2Cの信号線が接続されています。
ピン | GPIO | 用途 |
---|---|---|
1 | 3.3V | |
2 | 5V | |
3 | GPIO 02 | I2C SDA |
4 | 5V | |
5 | GPIO 03 | I2C SCL |
6 | GND | |
7 | GPIO 04 | |
8 | GPIO 14 | UART TXD |
9 | GND | |
10 | GPIO 15 | UART RXD |
RTCボードはRaspberryPiのGPIOポートの1番~10番ピンの10本のコネクタで接続するようになっています。
Raspberry PiとRTC DS1307の間は、SDA(3番ピン)とSCL(5番ピン)の信号線と電源系(Vcc / GND)を接続します。そして、RTCボードの上部から5本の信号線のピンが出ていて、UARTの信号線を接続できるようになっています。
Linuxシステムの時計について
Linuxシステムには主要な時計が2つ存在します。
- ハードウェア・クロック : CPUから独立している時計で、システムが停止している間も動作している時計です
- システム・クロック : Linuxカーネルの内部に存在している時計で、すべての基準となる時計です
ハードウェア・クロックはRTCと呼ばれ、バッテリーバックアップすることでマシンの電源がOFFの場合にも動作しています。
インターネット接続している場合は、NTPプロトコルでネットワーク上の時刻サーバーに問い合わせてシステム・クロックを時間同期させることができます。
システム・クロック
dateコマンドでシステム・クロックにアクセスします。
コマンド | 説明 |
---|---|
date | システム・クロックを標準出力に表示します |
date -s ‘日時’ | システム・クロックに指定した日時を設定します |
ハードウェア・クロック
hwclockコマンドでハードウェア・クロックにアクセスします。
コマンド | 説明 |
---|---|
hwclock -r | ハードウェア・クロックを読んで標準出力に表示します |
hwclock -w | ハードウェア・クロックにシステム・クロックを書き込みます |
hwclock -s | ハードウェア・クロックをシステム・クロックに設定します |
RTC DS1307デバイスを接続
I2C有効化とソフトの設定
最初に、Raspberry PiのI2Cを有効化します。
sudo raspi-config
「7 Advanced Options」→「A7 I2C」→「はい」→「了解」で、I2Cを有効化して <Finish> で終了します。
次に、ユーティリティをインストールします。
sudo apt-get install i2c-tools
モジュールをロードするために、/etc/modulesに「i2c-dev」と「rtc-ds1307」を追加します。
pi@pi2note:~ $ sudo cat /etc/modules # /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. i2c-dev rtc-ds1307
RTCデバイスの登録
最初に、「i2cdetect」コマンドでI2Cデバイスのアドレスを調べます。
pi@pi2note:~ $ 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: -- -- -- -- -- -- -- --
DS1307は、アドレス0x68に接続されていました。
RTCデバイスを登録します。「sudo su」で管理者モードで操作します。デバイス名とアドレス「ds1307 0x68」をI2Cデバイスに書き込みます。
もう一度、「i2cdetect」コマンドでI2Cデバイスのアドレスを調べると、68→UUに変化してシステム管理下になったことがわかります。
pi@pi2note:~ $ sudo su root@pi2note:/home/pi# modprobe rtc-ds1307 root@pi2note:/home/pi# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device root@pi2note:/home/pi# 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: -- -- -- -- -- -- -- --
- 「date」コマンドでシステム・クロックを参照します
- 「hwclock -w」コマンドで、システム・クロックをハードウェア・クロックに書き込みます
- 「hwclock -r」コマンドで、ハードウェア・クロックを読み込んで正しく設定されたことを確認します
root@pi2note:/home/pi# date 2016年 11月 8日 火曜日 10:58:59 JST root@pi2note:/home/pi# hwclock -w root@pi2note:/home/pi# hwclock -r 2016年11月08日 10時59分11秒 -0.518151 seconds root@pi2note:/home/pi#
RTC DS1307のテスト
シャットダウンして電源OFFにします。しばらく時間を空けて、ネットワーク切断状態で電源を入れます。
「date」コマンドで、日時を確認するとシャットダウンした日時となっています。「i2cdump」コマンドで、DS1307内の日時を確認します。
pi@pi2note:~ $ date 2016年 11月 8日 火曜日 11:07:53 JST pi@pi2note:~ $ sudo i2cdump -y 1 0x68 b 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: 44 28 02 03 08 11 16 93 f7 9f 9b a5 d3 ff ff 9f
Address 0 : 44 秒
Address 1 : 28 分
Address 2 : 02 時 (02+09=11時)
Address 3 : 03 曜日 (火曜日)
Address 4 : 08 日
Address 5 : 11 月
Address 6 : 16 年 (2016)
Linux内部のシステム・クロックは停止していましたが、RTCのハードウェア・クロックは現在の時刻となっていますので、正常に動作しています。
ブート時にRTC時刻を設定する
ブート時に、RTCのハードウェア・クロックをシステム・クロックに設定すれば、ネットワークに接続していなくてもブート時に正しく時刻が設定されることになります。
/etc/default/hwclock の最後の行 HCTOSYS_DEVICE のコメントアウトを外します。
pi@pi2note:~ $ sudo cat /etc/default/hwclock|grep HCTOSYS_DEVICE # probably match the CONFIG_RTC_HCTOSYS_DEVICE kernel config option. HCTOSYS_DEVICE=rtc0
起動スクリプト /etc/rc.local の exitの手前でハードウェア・クロックをシステム・クロックに設定します。/etc/rc.local は、管理者モードで実行しますので、sudoは入れる必要はありません。
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device sleep 1 hwclock -s
さて、テストしてみます。ネットワーク切断状態で電源を入れます。ブート時に正しく時刻が設定されるはずです。
「date」コマンドでシステム・クロックを確認すると、現在の時刻ではありませんでした。
「hwclock -r」コマンドでハードウェア・クロックを参照すると、システム・クロックと同じです。
pi@pi2note:~ $ date 2016年 11月 8日 火曜日 12:33:34 JST pi@pi2note:~ $ sudo hwclock -r 2016年11月08日 12時34分15秒 -0.276407 seconds
ブート時に正しく時刻が設定されていません。何かミスしているようです。
ネットワークに接続して、NTPサービスを再起動します。そして、「date」コマンドでシステム・クロックを確認すると、当然ながら現在の時刻が表示されます。
「hwclock -r」コマンドでハードウェア・クロックを参照すると、システム・クロックと同じになっています。NTPサービスにより、ハードウェア・クロックが再設定されてしまったようです。
pi@pi2note:~ $ sudo /etc/init.d/ntp restart [ ok ] Restarting ntp (via systemctl): ntp.service. pi@pi2note:~ $ date 2016年 11月 8日 火曜日 13:28:49 JST pi@pi2note:~ $ sudo hwclock -r 2016年11月08日 13時28分52秒 -0.252129 seconds
このことから、ネットワーク切断状態でブートした場合は、NTPサーバーからの時刻取得に失敗していますが、ハードウェア・クロックを再設定していると想像できます。
これでは、RTCを接続した意味がありません!
続きは、「Raspberry PiにRTC(DS1307)を接続 【解決編】」を参照して下さい。無事解決しました。