GPS センサを使って位置情報取得と時刻補正をする


Raspberry Pi に GPS センサを接続し、 gpsd と chrony の サービス を有効にして位置情報取得と時刻補正をする

動作環境

配線接続

用意した GPS センサは UART 接続用だが、Raspberry Pi 以外の機器にも適用するため変換器を使用して USB 接続する

接続確認

USB 変換器が認識されると/dev/ttyUSB0が作成される
通信内容を読み取り GPS センサが接続されていることを確認する

cat /dev/ttyUSB0

コマンド実行すると、下記のような NMEA 形式の応答がある
(注) 既に gpsd を設定・起動しているとDevice or resource busyと表示される

GNGLL,3422.1331,N,13518.0431,E,141613.000,A,A*48
GNGSA,A,3,17,28,04,14,09,03,19,06,22,,,,1.19,0.86,0.82*18
...

gpsd を有効にして位置情報を取得する

位置情報を受け取る仕組み

GPS センサから NMEA 形式の信号を受け取った gpsd は、gpsd_json 形式に変換した位置情報レポートを TCP/IP 通信(ポート2947)で配信する。レポートの内容は cgps などの gpsd クライアントを使用して簡単に表示できる

gpsd、gpsd クライアントのインストール

sudo apt install gpsd gpsd-clients

gpsd 設定

/etc/default/gpsdを編集する

/etc/default/gpsd
# Default settings for the gpsd init script and the hotplug wrapper.

# Start the gpsd daemon automatically at boot time
START_DAEMON="true"

# Use USB hotplugging to add new USB devices automatically to the daemon
USBAUTO="true"

# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="/dev/ttyUSB0"

# Other options you want to pass to gpsd
GPSD_OPTIONS="-F /var/run/gpsd.sock -b -n -r"

オプションの意味はman gpsdで確認できる

-F ソケットのファイルパス
-b デバイス保護モード(GPS センサへの設定書き込み禁止)
-n リクエストがくるまでセンサ接続待機する機能を無効にする。
-r 補正完了前でも GPS の時刻を使用する。RTC 内蔵センサなら補正完了前でも有効な時刻が取得できる

gpsd を再起動する

sudo systemctl restart gpsd.service

位置情報を取得する

cgps や gpsmon などの gpsd クライアントを使用して位置情報を取得する

cgps -s

こちらのライブラリを使用すると python で位置情報を取得することもできる

chrony を有効にして位置情報を取得する

chrony とは

ntpd とは異なる NTP 実装。ホストマシンが頻繁にシャットダウンやネットワーク切断状態となるケースで安定して動作することが特徴[公式]。CentOS や Red Hat では ntpd に変わりデフォルトとなっていることから信頼性も高い

chorny は gpsd が shared memory に書き込んだ情報を読み取って時刻補正する

chrnoy 設定

Raspberry Pi OS ではデフォルトでsystemd-timesyncdが起動しているので無効化する

sudo systemctl stop systemd-timesyncd
sudo systemctl disable systemd-timesyncd

chrony をインストールする

sudo apt install chrony

/etc/chrony/chrony.confを編集する

/etc/chrony/chrony.conf
# ネットワーク上の時刻サーバとの同期させない場合はコメントアウト
# pool 2.debian.pool.ntp.org iburst

# shared memoryから読み取る設定を追加
refclock SHM 0 refid GPS precision 1e-1

chrony を再起動する

sudo systemctl restart chrony.service

chrony sourcesコマンドで状況を確認できる
暫く放置して GPS の左側に*が表示されたら時刻同期完了している

210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#* GPS                           0   4   377    20    +18ms[  +32ms] +/-  100ms

参考

http://manpages.ubuntu.com/manpages/focal/man8/gpsd.8.html
https://manpages.ubuntu.com/manpages/precise/man5/gpsd_json.5.html
https://gpsd.gitlab.io/gpsd/gpsd-time-service-howto.html#_feeding_chrony_from_gpsd
https://gpsd.gitlab.io/gpsd/client-howto.html#_introduction