15
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RaspberryPiのRTC構築(DS1307とsystemd)

Last updated at Posted at 2019-02-16

はじめに

RaspberryPiに外付けのRTC(Real Time Clock)を載せて、更に起動時に時刻合わせする手順です。

ここでは、systemdを使って、Raspbianの起動時に自動的に時刻合わせの処理をします。

構成と概要

ハードウェア

I2C通信対応の、DS1307を使用したRTCを使います。I2Cアドレスは0x68番になります。(他のRTCでも、I2C周りの書き方が変わるだけで、基本は同じです)

####(例)

#事前確認

###raspi-config
I2C通信を有効にします。

$ sudo raspi-config

設定は、こちらを参考にしてください。

###必要なパッケージのインストール
以下のパッケージを入れます。

$ sudo apt install i2c-tools -y
$ sudo apt install ntpdate -y

###modulesの追記
/etc/modulesに設定を追記します。

$ cd /etc
$ sudo cp -p modules modules.org
$ sudo nano modules

rtc-ds1307を追記します。

/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

###DS1307の認識状況

DS1307のRTCモジュールを、RaspberryPiのI2C回路に繋いでおくと、0x68にRTCが見えます。

注意:DS1307にはバックアップの電池を繋いでおいてください。繋いでないと下記の一覧に出てきません・・・

$ 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: -- -- -- -- -- -- -- --

この時点で、RTCの現在時刻を確認すると、まだRaspbianの管理下になっていないので、下記のエラーメッセージが出ます。

$ sudo /sbin/hwclock
hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --debug option to see the details of our search for an access method.

#RTCに現在の時刻を書き込む

Raspbianのシステムクロックの値を、RTCに書き込みます。
※システムクロックntpときちんと同期して、正しい時刻にしておいてください。

###RTCをRaspbianの管理下に置く
sudo echo コマンドではPermission deniedになるので、一旦rootになってから操作します。

$ sudo su
# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
# 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: -- -- -- -- -- -- -- --
# exit
$

この時点で、RTCの現在時刻を確認すると、まだ時刻を書き込んでいないので、下記のように2000年1月1日の日付になっています。

$ sudo /sbin/hwclock
2000-01-01 09:00:18.046319+0900

RaspberryPi4の場合は、下記のようにread the time failedというメッセージになります。

$ sudo /sbin/hwclock
hwclock: ioctl(RTC_RD_TIME) to /dev/rtc0 to read the time failed: Invalid argument

$ uname -a
Linux few-kin05 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux

###システムクロックの時刻をRTCに書き込む

$ date
Fri Feb 15 18:17:53 JST 2019
$ sudo /sbin/hwclock -w
$ sudo /sbin/hwclock
2019-02-15 18:17:57.070420+0900

起動時に時刻合わせをする

時計あわせのスクリプトを準備して、Raspbianの起動時にsystemdから一回だけ起動するようにします。

###時刻合わせのスクリプト

setSystimeRTC.sh
#!/bin/sh
#--------------------------------------------------------------------
# 時刻合わせのスクリプト
# 2019-02 myasu
#--------------------------------------------------------------------

#----------------------------------
#定数
#----------------------------------

#NTPサーバ
NTPSERVER="ntp.nict.jp"

#----------------------------------
#メイン処理
#----------------------------------

#実行中ユーザをチェック
if [ `/usr/bin/id -u` != "0" ]; then
    #rootでなければ異常終了
    echo " ! Please run as root."
    exit 1
fi

#主要コマンドの存在をチェック
if [ ! -x /usr/sbin/i2cdetect ]; then
    #見つからなければ異常終了
    echo " ! No 'i2cdetect' Command."
    exit 1
fi
if [ ! -x /usr/sbin/ntpdate ]; then
    #見つからなければ異常終了
    echo " ! No 'ntpdate' Command."
    exit 1
fi
if [ ! -x /sbin/hwclock ]; then
    #見つからなければ異常終了
    echo " ! No 'hwclock' Command."
    exit 1
fi

#現在時刻を表示
NOW=`date`
echo " now (before sync) > "$NOW

#RTCデバイスがあるかチェック
#(強引ですがgrepを使って、該当アドレス68番かUUの文字があるか確認)
#(複数のデバイスがあって、UUが複数表示されるようなら、ココの記述は要改良)
/usr/sbin/i2cdetect -y 1 | grep "68\|UU" > /dev/null
if  [ $? != 0 ]; then
    #見つからなければ異常終了
    echo " ! No RTC Device."
    exit 1
fi

#RTCデバイスがraspbianの管理下にあるかチェック
#(強引ですがgrepを使って、該当アドレス68番があるか確認)
/usr/sbin/i2cdetect -y 1 | grep "68" > /dev/null
if  [ $? = 0 ]; then
    #未登録なら登録する
    echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
fi

#まずはNTPに対して時刻合わせする
/usr/sbin/ntpdate -v $NTPSERVER
if  [ $? = 0 ]; then
  #NTPで正常に時計合わせできたら、RTCの時刻を書き換え
  /sbin/hwclock -w    # system time --> rtc
  echo " Synchronize clock with NTP"
else
  #RTCの時刻を読み出してシステムクロックを書き換え
  /sbin/hwclock -s    # system time <-- rtc
  echo " Synchronize clock with RTC"
fi

#現在のシステムクロック時刻を表示
NOW=`date`
echo " now (after sync)  > "$NOW

#正常終了
exit 0

systemdの設定

起動時にワンショットだけ動く様にしています。
スクリプトの中の[INSTALL DIR] は、スクリプトファイルやserviceファイルを置いたフォルダに合わせて修正してください。

###serviceファイル

setSystimeRTC.service
[Unit]
Description=Synchronize clock with NTP or RTC
After=network.target local-fs.target
ConditionPathExists=/home/pi/[INSTALL DIR]

[Service]
ExecStart=/home/pi/[INSTALL DIR]/setSystimeRTC.sh
Restart=no
KillMode=mixed
Type=oneshot
User=root
Group=root

[Install]
WantedBy=multi-user.target

####簡単に解説

指定 設定値 説明
After network.target local-fs.target networkとファイルシステムが有効になってから起動します
Restart no 一発なので再起動無し
Type oneshot 一発だけ起動

systemdへ登録

systemdに登録して、サービスを起動します。

$ sudo ln -s /home/pi/[INSTALL DIR]/setSystimeRTC.service /etc/systemd/system
$ sudo systemctl enable setSystimeRTC.service
$ sudo systemctl start setSystimeRTC.service

####serviceファイルを修正した時
下記のように都度、リロードします。

$ sudo systemctl daemon-reload

起動状態を確認

systemctl statusコマンドで、状態を確認します。
起動したあと、ntpに問い合わせして時刻を合わせた後、RTCにシステムクロックを書き込んで終了しています。

$ systemctl status setSystimeRTC.service
● setSystimeRTC.service - Synchronize clock with NTP or RTC
   Loaded: loaded (/home/pi/gitwork/python/rtc/setSystimeRTC.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Wed 2019-01-30 05:59:43 JST; 3h 51min ago
 Main PID: 373 (code=exited, status=0/SUCCESS)

Jan 29 20:17:28 raspibp systemd[1]: Starting Synchronize clock with NTP or RTC...
Jan 29 20:17:28 raspibp setSystimeRTC.sh[373]:  now (before sync) > Tue Jan 29 20:17:28 JST 2019
Jan 29 20:17:29 raspibp setSystimeRTC.sh[373]: 29 Jan 20:17:29 ntpdate[391]: ntpdate 4.2.8p10@1.3728-o Sat Mar 10 18:03:
Jan 30 05:59:41 raspibp setSystimeRTC.sh[373]: 30 Jan 05:59:41 ntpdate[391]: step time server 133.243.238.243 offset 349
Jan 30 05:59:43 raspibp setSystimeRTC.sh[373]:  Synchronize clock with NTP
Jan 30 05:59:43 raspibp setSystimeRTC.sh[373]:  now (after sync)  > Wed Jan 30 05:59:43 JST 2019
Jan 30 05:59:43 raspibp systemd[1]: Started Synchronize clock with NTP or RTC.

逆に、ntpの問い合わせが失敗した場合は、RTCから時刻を合わせます。
下記の例では、わざとNTPサーバのホスト名を間違えています。

$ systemctl status setSystimeRTC.service
● setSystimeRTC.service - Synchronize clock with NTP or RTC
   Loaded: loaded (/home/pi/gitwork/python/rtc/setSystimeRTC.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Sat 2019-02-16 10:18:56 JST; 2s ago
  Process: 995 ExecStart=/home/pi/gitwork/python/rtc/setSystimeRTC.sh (code=exited, status=0/SUCCESS)
 Main PID: 995 (code=exited, status=0/SUCCESS)

Feb 16 10:18:51 raspiap systemd[1]: Starting Synchronize clock with NTP or RTC...
Feb 16 10:18:51 raspiap setSystimeRTC.sh[995]:  now (before sync) > Sat Feb 16 10:18:51 JST 2019
Feb 16 10:18:51 raspiap setSystimeRTC.sh[995]: 16 Feb 10:18:51 ntpdate[1002]: ntpdate 4.2.8p10@1.3728-o Sat Mar 10 18:03
Feb 16 10:18:55 raspiap setSystimeRTC.sh[995]: Error resolving ntp.nict1.jp: Name or service not known (-2)
Feb 16 10:18:55 raspiap setSystimeRTC.sh[995]: 16 Feb 10:18:55 ntpdate[1002]: Cant find host ntp.nict1.jp: Name or serv
Feb 16 10:18:55 raspiap setSystimeRTC.sh[995]: 16 Feb 10:18:55 ntpdate[1002]: no servers can be used, exiting
Feb 16 10:18:56 raspiap setSystimeRTC.sh[995]:  Synchronize clock with RTC
Feb 16 10:18:56 raspiap setSystimeRTC.sh[995]:  now (after sync)  > Sat Feb 16 10:18:56 JST 2019
Feb 16 10:18:56 raspiap systemd[1]: Started Synchronize clock with NTP or RTC.

参考

15
18
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?