3
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RaspberryPi に GPSレシーバー と RTC をつけてGPS 1PPS対応NTPサーバにする。

Last updated at Posted at 2022-09-20

何番煎じネタかというぐらい、RaspberryPiにGPSレシーバをつけてNTPdにするというネタではありますが、今回はRTCも(そこまで意味はないけど)つけてしまおうという話です。
別にGPSが受信できてればRTCは必要ないですが、たまたま停電とかで再起動直後とかビルの法定点検で1日停電とかの後を想定しつつ、気持ちRTC積んどくかぐらいのお話です。
正直RTCはおまけです。
なので、RTC部分を読み飛ばしてGPSレシーバでのNTPサーバ構築として読んでも大丈夫です。

1.用意するもの

GPSモジュールが入手不可の場合、秋月で販売してる下記のものが代替できます。

  • GPS受信機キット 1PPS出力付き 「みちびき」2機受信対応 [AE-GYSFDMAXB]

    • https://akizukidenshi.com/catalog/g/gK-09991/
      こちらでも代替可能ですが、GPSアンテナが内臓のため、ラズパイの設置場所を窓際などにする必要があります。
      また、GPS側の基盤パターンがRXDとTXDが本説明で使ってるAE-GNSS-EXTANTと逆になるため、注意が必要です。(むしろ2ピンから12ピンまで入れ子にせずストレート配線できるのでわかりやすい。)
  • 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 は不要です。)

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番ピン

に配線します。

GPS配線.png

3.Raspberry Pi OSインストール

今回は Raspberry Pi OS Lite 32-bitで用意
(執筆時点では)
https://www.raspberrypi.com/software/
Raspberry Pi Imagerを使ってサクッと作ります。

スクリーンショット 2022-09-15 22.01.46.png

イメージを燒く際に、詳細な設定からSSHを有効にしたりしていると、初手よりSSH接続できるようになるので良いかと。
パスワードやロケールも変えておくと良いです。
スクリーンショット 2022-09-15 22.01.26.png
スクリーンショット 2022-09-15 22.01.32.png
スクリーンショット 2022-09-15 22.01.40.png

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を配線します。

RTC配線.png

8.Raspberry Pi OSでRTCを使うためのの設定変更

8.1.I2C有効にし、RTCを使えるようにする

I2Cを有効にするには /etc/modulesi2c-devを追記する必要がある。
また、今回のRTCはDS3231を使っているため、これを有効にするために /boot/firmware/config.txtdtoverlay=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.confrtcsync が記載されているため、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利用の参考になればと。

参考資料

3
7
0

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
3
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?