何番煎じネタかというぐらい、RaspberryPiにGPSレシーバをつけてNTPdにするというネタではありますが、今回はRTCも(そこまで意味はないけど)つけてしまおうという話です。
別にGPSが受信できてればRTCは必要ないですが、たまたま停電とかで再起動直後とかビルの法定点検で1日停電とかの後を想定しつつ、気持ちRTC積んどくかぐらいのお話です。
正直RTCはおまけです。
なので、RTC部分を読み飛ばしてGPSレシーバでのNTPサーバ構築として読んでも大丈夫です。
1.用意するもの
- RaspberyPi (なんでもよし。今回は余っていたRaspberryPi 4B)
- 秋月の GNSS(GPS・GLONASS・QZSS)受信機キット 1PPS出力 みちびき3機対応 アンテナセット付キット [AE-GNSS-EXTANT+ANT_SET]
- DS3231 AT24C32 高精度時計モジュール
- コネクタ付ケーブル 20cm 40P メスメス
GPSモジュールが入手不可の場合、秋月で販売してる下記のものが代替できます。
-
GPS受信機キット 1PPS出力付き 「みちびき」2機受信対応 [AE-GYSFDMAXB]
-
https://akizukidenshi.com/catalog/g/gK-09991/
こちらでも代替可能ですが、GPSアンテナが内臓のため、ラズパイの設置場所を窓際などにする必要があります。
また、GPS側の基盤パターンがRXDとTXDが本説明で使ってるAE-GNSS-EXTANTと逆になるため、注意が必要です。(むしろ2ピンから12ピンまで入れ子にせずストレート配線できるのでわかりやすい。)
-
https://akizukidenshi.com/catalog/g/gK-09991/
-
GPS/GLONASS受信機(Galileo/BeiDou可)u‐blox M8搭載 みちびき3機受信対応 [GT-902PMGG]
-
https://akizukidenshi.com/catalog/g/gM-12905/
こちらの場合、GPSアンテナが外付けですので非常におすすめです。
配線が剥き出しのため、ピンヘッダに刺すために - ケーブル用コネクタ (10個入) https://akizukidenshi.com/catalog/g/gC-12160/
- コネクタ用ハウジング 5P https://akizukidenshi.com/catalog/g/gC-12154/
あたりも入手しておくと良いです。
さらに、このユニットの1PPS信号はアクティブHighなので、本説明での設定を行う際に注意が必要です。
(pps設定時のdtoverlay=pps-gpio,gpiopin=18 のみになり assert_falling_edge=true は不要です。)
-
https://akizukidenshi.com/catalog/g/gM-12905/
2.GPS受信キットの配線
pi@gps:~ $ pinout
Description : Raspberry Pi 4B rev 1.5
Revision : b03115
SoC : BCM2711
RAM : 2GB
Storage : MicroSD
USB ports : 4 (of which 2 USB3)
Ethernet ports : 1 (1000Mbps max. speed)
Wi-fi : True
Bluetooth : True
Camera ports (CSI) : 1
Display ports (DSI): 1
,--------------------------------.
| oooooooooooooooooooo J8 +======
| 1ooooooooooooooooooo J14 | Net
| Wi 12 +======
| Fi Pi Model 4B V1.5 oo |
| |D ,---. +---+ +====
| |S |SoC| |RAM| |USB3
| |I `---' +---+ +====
| |0 C| |
| oo1 J2 S| +====
| I| |A| |USB2
| pwr |hd| |hd| 0| |u| +====
`-| |---|m0|---|m1|----|x|-------'
J8:
3V3 (1) (2) 5V
GPIO2 (3) (4) 5V
GPIO3 (5) (6) GND
GPIO4 (7) (8) GPIO14
GND (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND
GPIO22 (15) (16) GPIO23
3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND
GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8
GND (25) (26) GPIO7
GPIO0 (27) (28) GPIO1
GPIO5 (29) (30) GND
GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
GND (39) (40) GPIO21
J2:
GLOBAL ENABLE (1)
GND (2)
RUN (3)
J14:
TR01 TAP (1) (2) TR00 TAP
TR03 TAP (3) (4) TR02 TAP
For further information, please refer to https://pinout.xyz/
pi@gps:~ $
pinoutコマンドを叩くとピン配列が出てきます。
秋月のAE-GNSS-EXTANTには
動作用の
- VDD5V
- GND
通信用の
- UART TXD
- UART RXD
1PPS信号(3.3V 100ms アクティブLow)の
- 1PPS
というピンが出ていますので、ラズパイの対応するピンと配線する必要があります。
ラズパイでUARTが使えるのは
GPIO14,GPIO15となっている8番(UART TX)、10番(UART RX)
この辺りで電源として使える 5vPowerの4番、Groundの6番
ちょうど1直線に配線できそうなので、PPSはGPIO18の12番ピンに入れると良いでしょう。
なので
- VDD5Vを4番ピン
- GNDを6番ピン
- TXDを10番ピン
- RXDを8番ピン
- 1PPSを12番ピン
に配線します。
3.Raspberry Pi OSインストール
今回は Raspberry Pi OS Lite 32-bitで用意
(執筆時点では)
https://www.raspberrypi.com/software/
Raspberry Pi Imagerを使ってサクッと作ります。
イメージを燒く際に、詳細な設定からSSHを有効にしたりしていると、初手よりSSH接続できるようになるので良いかと。
パスワードやロケールも変えておくと良いです。
4.Raspberry Pi OSでGPSを使うためのの設定変更
執筆時点でのリリースバージョンであるbullseyeベースで記載する
pi@gps:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 12 (bookworm)
Release: 12
Codename: bookworm
pi@gps:~ $
pi@gps:~ $ uname -a
Linux gps 6.6.47+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.47-1+rpt1 (2024-09-02) aarch64 GNU/Linux
pi@gps:~ $
また、タイムゾーンは Asia/Tikyoにセットしてある
sudo timedatectl set-timezone Asia/Tokyo
4.1.UART有効にする
ラズパイのドキュメントにUARTの有効方法が書かれている
/boot/firmware/config.txt に enable_uart=1
を追記する
これを読む限り、UARTはデフォルトで115200bpsで通信するようになっているようだ。
AE-GNSS-EXTANTはデフォルト9600bpsなので9600bpsになるよう
/boot/firmware/config.txt に init_uart_baud=9600
を追記する
ここまでの2つを実行し、 /boot/firmware/config.txt に追記を行う
echo enable_uart=1 | sudo tee -a /boot/firmware/config.txt
echo init_uart_baud=9600 | sudo tee -a /boot/firmware/config.txt
4.1.ex Bluetooth内蔵RaspberryPiの場合 (非搭載の場合は読み飛ばしてOK)
RaspberryPiには、PL011とminiUARTという2つの回路が存在します。
https://www.raspberrypi.com/documentation/computers/configuration.html#configuring-uarts
Bluetoothを内蔵していないRaspberryPiの場合UART0がPL011に接続されており、miniUARTは無効になっています。
Bluetoothを内蔵しているRaspberryPi 3や ZeroWなどの場合PL011がBluetoothに接続されており、そのまま
/boot/firmware/config.txt に enable_uart=1
を追記した場合、miniUART側にGPIOのUARTが接続されます。
このminiUARTというのはminiとついているように、機能が限定されています。
一番問題なのはGPUのクロックに依存してしまうため、ボーレートが変化する可能性が出るのですが、それを回避するためにGPUのコアクロックが250MHzへ固定し、性能を落として利用する必要があります。
https://datasheets.raspberrypi.com/bcm2835/bcm2835-peripherals.pdf
そのため、GPSモジュールを繋ぐ際は下記のいずれかの方法が必要になります。
A. Bluetoothを無効にする(無効化することで、PL011がUART0になる)
B. BluetoothをminiUART接続に変えてUART0にPL011を使う
4.1.ex A. Bluetoothを無効にする
/boot/firmware/config.txt に dtoverlay=disable-bt
を追記することでBluetoothを無効にします。
echo dtoverlay=disable-bt | sudo tee -a /boot/firmware/config.txt
4.1.ex B. BluetoothをminiUART接続に変えてUART0にPL011を使う
/boot/firmware/config.txt に dtoverlay=miniuart-bt
を追記することでBluetoothをminiUART接続に変えてUART0にPL011を使うようになります。
また、/boot/firmware/config.txt に core_freq=250
を追記し、miniUARTのクロックが変動しないようにします。
echo dtoverlay=miniuart-bt | sudo tee -a /boot/firmware/config.txt
echo core_freq=250 | sudo tee -a /boot/firmware/config.txt
4.2.シリアルコンソールを無効にする
Raspberry Pi OSではデフォルトでシリアルコンソールが有効になっています。
そのため、せっかくUARTを有効にしてもシリアルコンソールの出力先として使われてしまいます。
/boot/cmdline.txt の console=serial0,115200
を削除し、シリアルコンソールを無効化します。
また serial-getty@ttyS0.service
も停止、無効化する必要があります。
sudo sed -i 's/console=serial0,115200 //g' /boot/firmware/cmdline.txt
sudo systemctl stop serial-getty@ttyS0.service
sudo systemctl disable serial-getty@ttyS0.service
4.3.PPSを有効にする
GPIO18(ピン番号12番)にPPSを配線しましたが、設定を入れなければ有効になりません。
Linux Kernelにある PPS Signal on GPIO を有効にします。
/etc/modules に pps-gpio
を追加し、
/boot/firmware/config.txt に dtoverlay=pps-gpio,gpiopin=18
を追加します。
GPSモジュールのPPSシグナルがアクティブLowな場合 assert_falling_edge=true
が必要です。
そのため
echo dtoverlay=pps-gpio,gpiopin=18,assert_falling_edge=true | sudo tee -a /boot/firmware/config.txt
と置き換えてください
ここまで設定できたら一度リブートします。
echo pps-gpio | sudo tee -a /etc/modules
echo dtoverlay=pps-gpio,gpiopin=18 | sudo tee -a /boot/firmware/config.txt
sudo shutdown -r now
5.gpsdのインストールと設定
5.1.必要パッケージのインストール
上記まででGPSを利用するためのOS側設定が終わっているので、gpsdをインストールし設定します。
必要なパッケージ gpsd
gpsd-tools
pps-tools
をaptで入れましょう
sudo apt update && sudo apt -y install gpsd gpsd-tools pps-tools
5.2.gpsmonを使ってGPS受信確認
gpsmon
を使い、GPS信号の受信ができるかを確認します。
その前に ls /dev/ttyAMA0
でデバイスが認識しているかを確認します。
ls /dev/ttyAMA0
実行例
pi@raspberrypi:~ $ ls /dev/ttyAMA0
/dev/ttyAMA0
pi@raspberrypi:~ $
ここで ls: cannot access '/dev/ttyAMA0': No such file or directory
となった場合はOSでの設定ができていないので、 4.1.UART有効にする
から設定を確認しましょう。
問題なければ gpsmon -n /dev/ttyAMA0
を実行します。
sudo gpsmon -n /dev/ttyAMA0
実行例
raspberrypi:/dev/ttyAMA0 9600 NMEA0183>
┌──────────────────────────────────────────────────────────────────────────────┐
│Time: 2022-09-19T17:45:43.000Z Lat: xx xx.xxxxxx' N Lon: xxx xx.xxxxxx' E │
└───────────────────────────────── Cooked TPV ─────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ GLGSV GNRMC GPVTG GPZDA GPGGA GNGLL GNGSA GPGSV │
└───────────────────────────────── Sentences ──────────────────────────────────┘
┌───────────────────────┌─────────────────────────┌────────────────────────────┐
│ SVID PRN Az El SN HU│Time: 174543.000 │Time: 174544.000 │
│GP 1 1 209 35 19 Y│Latitude: xxxx.xxxx N │Latitude: xxxx.xxxx │
│GP 8 8 13 73 26 Y│Longitude: xxxxx.xxxx E │Longitude: xxxxx.xxxx │
│GP 14 14 308 9 17 Y│Speed: 0.21 │Altitude: xx.x │
│GP 16 16 126 25 18 Y│Course: 124.33 │Quality: 1 Sats: 10 │
│GP 21 21 202 66 23 Y│Status: A FAA:A │HDOP: x.xx │
│GP 23 23 38 11 28 Y│MagVar: │Geoid: xx.x │
│GP 27 27 67 42 36 Y└───────── RMC ───────────└─────────── GGA ────────────┘
│GP 30 30 301 28 18 Y┌─────────────────────────┌────────────────────────────┐
│GL 12 76 168 51 24 Y│Mode: A3 Sats: 1 8 14 + │UTC: RMS: │
│GL 14 78 328 14 22 Y│DOP H=0.85 V=0.81 P=1.17 │MAJ: MIN: │
│GP 7 7 264 41 0 N│TOFF: 0.327112748 │ORI: LAT: │
│GP 10 10 66 25 11 N│PPS: N/A │LON: ALT: │
└───v──── GSV ──────────└────── GSA + PPS ────────└─────────── GST ────────────┘
実際には LatやLonには自分の場所の緯度経度が表示されます。
表示がない場合、TXやRXが逆転している可能性がありますので、配線などを確認しましょう。
現時点で PPS: N/A
は正常です。
quit
と入力しエンターで閉じるか、 Ctrl+c
で閉じることができます。
5.3.ppstestを使ってPPS受信確認
ppstest
を使い、PPS信号の受信ができるかを確認します。
その前に ls /dev/pps0
でデバイスが認識しているかを確認します。
ls /dev/pps0
実行例
pi@raspberrypi:~ $ ls /dev/pps0
/dev/pps0
pi@raspberrypi:~ $
ここで ls: cannot access '/dev/pps0': No such file or directory
となった場合はOSでの設定ができていないので、 4.3.PPSを有効にする
から設定を確認しましょう。
問題なければ ppstest /dev/pps0
を実行します。
sudo ppstest /dev/pps0
実行例
trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1663610127.994295210, sequence: 4636 - clear 0.000000000, sequence: 0
source 0 - assert 1663610128.994297397, sequence: 4637 - clear 0.000000000, sequence: 0
source 0 - assert 1663610129.994291099, sequence: 4638 - clear 0.000000000, sequence: 0
source 0 - assert 1663610130.994289180, sequence: 4639 - clear 0.000000000, sequence: 0
source 0 - assert 1663610131.994286639, sequence: 4640 - clear 0.000000000, sequence: 0
上記のように source 0 - assert 1663610127.994295210, sequence: 4636 - clear 0.000000000, sequence: 0
と一定間隔で出てこれば問題ないです。
表示されない場合、sudo
つけて実行しているかや、配線確認をしてみてください。
5.4 gpsdの設定
ここまで問題なければ、gpsdの設定を行います。
設定ファイルは /etc/default/gpsd
にありますので、これを書き換えます。
DEVICES=""
には /dev/ttyAMA0
と /dev/pps0
を
GPSD_OPTIONS=""
には -n
を入れてクライアントからのアクセスがなくても更新するようにします。
https://gpsd.gitlab.io/gpsd/gpsd-time-service-howto.html
また、設定後にgpsdを再起動します。
sudo sed -i 's@DEVICES=""@DEVICES="/dev/ttyAMA0 /dev/pps0"@g' /etc/default/gpsd
sudo sed -i 's@GPSD_OPTIONS=""@GPSD_OPTIONS="-n"@g' /etc/default/gpsd
sudo systemctl restart gpsd.service
sudo systemctl restart gpsd.socket
ここまで設定完了したら、再度gpsmonを起動して動作確認をします。
設定ファイルで/dev/ttyAMA0
/dev/pps0
を指定しているため、 gpsmon
を叩くだけでステータス表示がされます。
gpsmon -n
実行例
pi@raspberrypi:~ $ gpsmon -n
tcp://localhost:2947 NMEA0183>
┌──────────────────────────────────────────────────────────────────────────────┐or":14}
│Time: 2022-09-19T18:48:14.000Z Lat: xx xx.xxxxxx' N Lon: xxx xx.xxxxxx' E │ver":"MTK-3301","subtype":"AXN_5.1.2_3333_17113000-0013","activated":"2022-09-19T18:48:0
└───────────────────────────────── Cooked TPV ─────────────────────────────────┘mincycle":0.10},{"class":"DEVICE","path":"/dev/pps0","driver":"PPS","activated":"2022-09
┌──────────────────────────────────────────────────────────────────────────────┐
│ GLGSV GNRMC GPZDA GPGRS GPGST GPGGA GNGSA GPGSV │false,"timing":false,"split24":false,"pps":true}
└───────────────────────────────── Sentences ──────────────────────────────────┘
┌───────────────────────┌─────────────────────────┌────────────────────────────┐
│ SVID PRN Az El SN HU│Time: 184814.000 │Time: 184815.000 │
│GP 1 1 228 65 30 Y│Latitude: xxxx.xxxx N │Latitude: xxxx.xxxx │
│GP 8 8 72 57 23 Y│Longitude: xxxxx.xxxx E │Longitude: xxxxx.xxxx │
│GP 10 10 40 16 18 Y│Speed: 0.56 │Altitude: xx.x │
│GP 14 14 310 33 18 Y│Course: 338.30 │Quality: 1 Sats: 8 │
│GP 21 21 44 83 20 Y│Status: A FAA:A │HDOP: x.xx │
│GP 27 27 88 21 19 Y│MagVar: │Geoid: xx.x │
│GP 30 30 270 28 21 Y└───────── RMC ───────────└─────────── GGA ────────────┘
│GL 14 78 314 42 25 Y┌─────────────────────────┌────────────────────────────┐
│GP 3 3 170 15 18 N│Mode: A3 Sats: 1 8 10 + │UTC: 184814.000RMS: 5.7 │
│GP 7 7 234 25 0 N│DOP H=1.29 V=0.86 P=1.55 │MAJ: 15 MIN: 8.4 │
│GP 16 16 139 2 0 N│TOFF: 0.264741719 │ORI: 170.5 LAT: 15 │
│GP 17 17 279 10 0 N│PPS: -0.006733994 │LON: 8.6 ALT: 18 │
└───v──── GSV ──────────└────── GSA + PPS ────────└─────────── GST ────────────┘
GSA + PPS
のところの PPS:に数字が入るようになりました。
ここまで表示されていれば問題はないです。
quit
もしくは Ctrl+c
で抜けます
6.Chronyのインストールと設定
NTPサーバとしてChronyを使います。一般的なntpdという選択肢もありますが、この後RTCを搭載した際にハードウェアクロックとの同期がサポートされてたりと、機能的にChronyが良いため、Chronyをデーモンとして使用します。
6.1.Chronyのインストール
Chronyをインストールし設定します。
必要なパッケージ chrony
をaptで入れましょう
sudo apt update && sudo apt -y install chrony
6.2.Chronyの設定
/etc/chrony/chrony.conf
を編集し、PPSを使ったNTPサーバになるよう設定する。
デフォルトの pool 2.debian.pool.ntp.org iburst
については
pool ntp.nict.jp iburst minpoll 6 maxpoll 8
に変更し、PPSとの誤差を計測する
sourcedir /run/chrony-dhcp
についてもコメントアウトする
refclock PPS /dev/pps0 lock NMEA refid GPS
を追加する
leapsecmode slew
を追加し、うるう秒においてslewモードで合わせる
maxslewrate 1000
を追加し、1秒のずれを17時間34分かけて同期する。
smoothtime 400 0.001 leaponly
を追加し閏秒の時でもスムーズに時刻同期する。
ここまで設定したら、 systemctl restart chrony.service
でサービス再起動する
sudo sed -i 's@pool 2.debian.pool.ntp.org iburst@pool ntp.nict.jp iburst minpoll 6 maxpoll 8@g' /etc/chrony/chrony.conf
sudo sed -i 's@sourcedir /run/chrony-dhcp@#sourcedir /run/chrony-dhcp@g' /etc/chrony/chrony.conf
echo refclock PPS /dev/pps0 lock NMEA refid GPS | sudo tee -a /etc/chrony/chrony.conf
echo leapsecmode slew | sudo tee -a /etc/chrony/chrony.conf
echo maxslewrate 1000 | sudo tee -a /etc/chrony/chrony.conf
echo smoothtime 400 0.001 leaponly | sudo tee -a /etc/chrony/chrony.conf
sudo systemctl restart chrony.service
ここまで実行したら、chronyc sources -v
にて同期状態をチェックしましょう
chronyc sources -v
実行例1
pi@raspberrypi:~ $ chronyc sources -v
.-- Source mode '^' = server, '=' = peer, '#' = local clock.
/ .- Source state '*' = current best, '+' = combined, '-' = not combined,
| / 'x' = may be in error, '~' = too variable, '?' = unusable.
|| .- xxxx [ yyyy ] +/- zzzz
|| Reachability register (octal) -. | xxxx = adjusted offset,
|| Log2(Polling interval) --. | | yyyy = measured offset,
|| \ | | zzzz = estimated error.
|| | | \
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
#? GPS 0 4 0 - +0ns[ +0ns] +/- 0ns
^+ ntp-b3.nict.go.jp 1 6 7 1 -155us[ -487us] +/- 12ms
^* ntp-b2.nict.go.jp 1 6 7 1 +80us[ -252us] +/- 13ms
^+ ntp-a2.nict.go.jp 1 6 7 2 +96us[ -236us] +/- 13ms
^- ntp-a3.nict.go.jp 1 6 7 2 -119us[ -452us] +/- 13ms
pi@raspberrypi:~ $
ntp-b2.nict.go.jp
の左に *
が付き、このソースをもとに同期を始める動作になるのですが、3分ぐらい経つと下記のようになります。
実行例2
pi@raspberrypi:~ $ chronyc sources -v
.-- Source mode '^' = server, '=' = peer, '#' = local clock.
/ .- Source state '*' = current best, '+' = combined, '-' = not combined,
| / 'x' = may be in error, '~' = too variable, '?' = unusable.
|| .- xxxx [ yyyy ] +/- zzzz
|| Reachability register (octal) -. | xxxx = adjusted offset,
|| Log2(Polling interval) --. | | yyyy = measured offset,
|| \ | | zzzz = estimated error.
|| | | \
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
#* GPS 0 4 37 9 +1105ns[ -303ns] +/- 317ns
^- ntp-b3.nict.go.jp 1 6 37 11 -381us[ -382us] +/- 12ms
^- ntp-b2.nict.go.jp 1 6 37 11 -11us[ -13us] +/- 12ms
^- ntp-a2.nict.go.jp 1 6 37 11 -198us[ -199us] +/- 13ms
^- ntp-a3.nict.go.jp 1 6 37 11 -136us[ -137us] +/- 12ms
pi@raspberrypi:~ $
今度はGPSの隣に *
が付きましたので、無事GPSの1PPS信号をもとに同期しています。
外部のNTPサーバとの補正や比較が必要なければ
pool ntp.nict.jp iburst minpoll 6 maxpoll 8
をコメントアウトしてしまっても良いですが、この後紹介するRTCクロックを搭載後に行うのが良いかと思います。
ここまででGPSを使ったNTPサーバの構築は終わりです。
7.RTCモジュールの取り付け
pi@gps:~ $ pinout
Description : Raspberry Pi 4B rev 1.5
Revision : b03115
SoC : BCM2711
RAM : 2GB
Storage : MicroSD
USB ports : 4 (of which 2 USB3)
Ethernet ports : 1 (1000Mbps max. speed)
Wi-fi : True
Bluetooth : True
Camera ports (CSI) : 1
Display ports (DSI): 1
,--------------------------------.
| oooooooooooooooooooo J8 +======
| 1ooooooooooooooooooo J14 | Net
| Wi 12 +======
| Fi Pi Model 4B V1.5 oo |
| |D ,---. +---+ +====
| |S |SoC| |RAM| |USB3
| |I `---' +---+ +====
| |0 C| |
| oo1 J2 S| +====
| I| |A| |USB2
| pwr |hd| |hd| 0| |u| +====
`-| |---|m0|---|m1|----|x|-------'
J8:
3V3 (1) (2) 5V
GPIO2 (3) (4) 5V
GPIO3 (5) (6) GND
GPIO4 (7) (8) GPIO14
GND (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND
GPIO22 (15) (16) GPIO23
3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND
GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8
GND (25) (26) GPIO7
GPIO0 (27) (28) GPIO1
GPIO5 (29) (30) GND
GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
GND (39) (40) GPIO21
J2:
GLOBAL ENABLE (1)
GND (2)
RUN (3)
J14:
TR01 TAP (1) (2) TR00 TAP
TR03 TAP (3) (4) TR02 TAP
For further information, please refer to https://pinout.xyz/
pi@gps:~ $
pinoutコマンドを叩くとピン配列が出てきます。
今回のRTCモジュールには
水晶発信機の32.768kHzをそのまま出力する
- 32K
水晶発信機の32.768kHzを矩形波に直した
- SQW
I2C通信の
- SCL
- SDA
動作用の
- VCC (3.3V入力)
- GND
の6ピンがありますが、 32KとSQWは使わなくて良いため、
- SCL
- SDA
- VCC
- GND
という4つのピンを、ラズパイの対応するピンと配線する必要があります。
ラズパイでI2Cが使えるのは
GPIO02,GPIO03となっている3番(I2C SDA)、5番(I2C SCL)
この辺りで電源として使える 3.3vPowerの1番、Groundの9番
ちょうど1直線に配線できそうです。
なので
- SCLを5番ピン
- SDAを3番ピン
- VCCを1番ピン
- GNDを9番ピン
に配線します。
shutdown -h now
で電源を落とし、電源USBも抜いた上で、RTCモジュールとRaspberryPiを配線します。
8.Raspberry Pi OSでRTCを使うためのの設定変更
8.1.I2C有効にし、RTCを使えるようにする
I2Cを有効にするには /etc/modules
に i2c-dev
を追記する必要がある。
また、今回のRTCはDS3231を使っているため、これを有効にするために /boot/firmware/config.txt
に dtoverlay=i2c-rtc,ds3231
を追記する必要がある。
ここまで終えたら再起動をする。
echo i2c-dev| sudo tee -a /etc/modules
echo dtoverlay=i2c-rtc,ds3231 | sudo tee -a /boot/firmware/config.txt
sudo shutdown -r now
再起動後、問題なくI2Cのモジュールがロードされてるかを確認するため
ls /dev/i2c*
を実行し、表示が出るか確認する。
実行例
pi@raspberrypi:~ $ ls /dev/i2c*
/dev/i2c-1
pi@raspberrypi:~ $
このように何かが表示されていれば問題ない。
8.2.i2c-toolsをインストール
/dev/i2c-1
が表示されていても、これが何のデバイスかがこのままでは確認できないため、きちんとRTCが認識しているかを確認するため
apt install i2c-tools
を行い、 i2cdetect -y 1
でデバイス確認をします。
sudo apt update && sudo apt -y install i2c-tools
i2cdetect -y 1
実行例
pi@raspberrypi:~ $ 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: -- -- -- -- -- -- -- --
pi@raspberrypi:~ $
57については、このRTCボードについているAT24C02 EEPROMのものなので、問題なし。
68がUUになっていればRTCが利用可能である。
万が一ここがUUではなく、数字で68となっている場合、ロードされていないため、8.1.I2C有効にし、RTCを使えるようにする
の内容を確認する必要がある。
9.RTCを利用する
ここまででRTCが利用できる状態になりましたので、実際に確認や設定をします。
まず hwclock -r
で読み出せるか確認します。
sudo hwclock -r
実行例
pi@raspberrypi:~ $ sudo hwclock -r
2022-09-20 12:15:26.475239+09:00
pi@raspberrypi:~ $
現在の時刻もしくは、2000年1月1日ぐらいの適当な時間のどちらかが表示されているかと思います。
本来この状態ではRTCには何も時刻が書き込まれていないはずなので、初期データの2000年1月1日ぐらいの適当な時刻が出るのですが、
GPS時刻の配信にChronyをインストールした際 /etc/chrony/chrony.conf
に rtcsync
が記載されているため、11分ごとにhwclockに現在時刻を書き込み同期させています。
なので、現在時刻が表示されてても問題ないです。
そこで簡単な実験をします。
hwclock --set --date '-54min'
を行いRTCの時刻を適当な時刻へ変更後、 while true; do echo; hwclock; date; sleep 1m; done
を実行し、様子を見ます。11分おきに ChronyはRTCと同期をとるので、どこかのタイミングでRTCが書き変わるはずです。
sudo hwclock --set --date "-54min"
while true; do echo; sudo hwclock; date; sleep 1m; done
実行例
pi@raspberrypi:~ $ sudo hwclock --set --date "-54min"
pi@raspberrypi:~ $ while true; do echo; sudo hwclock; date; sleep 1m; done
2022-09-20 11:34:48.878274+09:00
Tue 20 Sep 12:28:49 JST 2022
2022-09-20 11:35:49.100144+09:00
Tue 20 Sep 12:29:50 JST 2022
2022-09-20 12:30:50.930984+09:00
Tue 20 Sep 12:30:51 JST 2022
^C
pi@raspberrypi:~ $
今回は3分ほどで同期されましたが、あくまで11分間隔で行なっているため、12分経っても同期されない場合、chronyの動作や設定に問題があります。
最後に timedatectl
を実行し System clock synchronized: yes
や NTP service: active
を確認する
timedatectl
実行例
pi@raspberrypi:~ $ timedatectl
Local time: Tue 2022-09-20 12:37:11 JST
Universal time: Tue 2022-09-20 03:37:11 UTC
RTC time: Tue 2022-09-20 03:37:11
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
pi@raspberrypi:~ $
問題なくRTCタイムが表示されていたり、System clock synchronized: yes
NTP service: active
が確認できればOKです。
10.おわりに
非常に長い文章となりましたが、RaspberryPi でのGPS NTPやRTC利用の参考になればと。
参考資料