ありふれた題材と思いますが、勉強を兼ねて実施したので、備忘
使用機器およびソフトウェア
本体: RaspberryPI Zero W
GPSモジュール: 秋月電子通商製 AE-GYSFDMAXB
OS/ディストリビューション: raspbian lite(stretch)
(* 使ったのがたまたまZero Wだっただけで、2,3,Zeroでもほぼ同じで動くはず。)
前提条件
とりあえずラズパイ自体は動作していて、インターネットに接続できていることが前提です。
パッケージ導入と周辺ソフトウェア設定
ntp, ntpdate,fake-hwclockパッケージを導入
fake-hwclockはntpの設定変更後、起動時に時計がリセットされてしまうため、対策として追加
$ sudo apt install ntp ntpdate fake-hwclock
知らぬ間に時計を修正されると気持ちがわるいので、systemdの時刻同期処理を停止
$ sudo timedatectl set-ntp false
DHCP配布されたIPアドレスを使用している場合,dhcpcdが用意した設定ファイルでntpdが起動するため
dhcpcd.confを変更して、この挙動を阻止
#/etc/dhcpcd.conf
option ntp_servers
↓
# option ntp_servers (コメントアウト)
GPSモジュールの設定
ラズパイ側の設定
UART(シリアルポート)とPPSドライバの有効化
/boot/config.txt に以下を追記
enable_uart=1
dtoverlay=pps-gpio,gpiopin=18,assert_falling_edge=true
enable_uart=1でUARTを有効化
dtoverlayほにゃららでpps信号をGPIO18で扱えるようにします.
また、このGPSモジュールはPPS信号を立ち下がりエッジで送信するため、assert_falling_edgeオプションを指定しています.
(デフォは立ち上がりエッジで検出)
また、bluetoothを使用しないのであれば,以下を追加することで、
ラズパイに搭載されている2つのUARTのうち、機能の良い方を使用することができます.
dtoverlay=pi3-diable-bt
このまま接続すると、シリアルポートからとんでもない値が入力されてOSが悲しいことになるので
/boot/cmdline.txtを変更してシリアルコンソールを無効化します。
具体的には
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 ....
となっているところの console=serial0,115200 を削除します。
ntpがGPSおよびPPS信号を読み込む際に指定するデバイスファイル名が/dev/gpsX, /dev/gpsppsXなため、
udevにルールを追加して、OS起動時に自動的に該当ファイルが生成されるようにします.
/etc/udev/rules.d に以下の内容でファイルを追加
/etc/udev/rules.d/99-pps.rules
KERNEL=="ttyS0",SYMLINK+="gps0"
KERNEL=="pps0",OWNER="root",GROUP="dialout",MODE="0660",SYMLINK+="gpspps0"
bluetoothを無効にした場合は,ttyS0の部分をttyAMA0に変更してください.
追加したデバイスファイルをntpが読めるようにグループdialoutにユーザntpを追加
$ sudo usermod -aG dialout ntp
ここまで設定が終わったら,ラズパイの電源を落として、GPSモジュールとラズパイを配線する
電源ブチ切りするとお亡くなりになる可能性があるので注意
GPSモジュール,ラズパイ間の配線は
モジュール - ラズパイ
5V - P4(5V)
GND - P6(GND)
TXD - P10(GPIO15 UART_RXD)
RXD - P8(GPIO14 UART_TXD)
1PPS - P12(GPIO18)
ラズパイの5VはP2からも出てますが、P4から取ると隙間なく5ピン揃って良いんじゃないでしょか。
配線が終わったらラズパイの電源を入れる.
GPSのPPS信号に同期したNTPDの設定
参考にしたサイトにはPPS信号を扱えるようにntp自体をソースファイルからビルドするとありましたが、
今はパッケージのままで大丈夫そうです。
/etc/ntp.conf に以下を追記
server 127.127.20.0 mode 16 minpoll 4 manpoll 4
fudge 127.127.20.0 flag1 1 flag3 0 flag4 0 time1 0.0 time2 0.488 refid GPS
server 127.127.20.0 … : Generic NMEA GPS Receiver を使用
mode 16 : シリアルポートのボーレート指定 9600bps
fudge 127.127.20.0 … : Generic NMEA GPS Receiver の設定
flag1 1 : PPS信号を扱う
flag3 0 : ntpモード/カーネルモード 0でntpモード, 1にするにはlinuxカーネルのビルドが必要なので、今は0
time1 0.0 : PPS信号の遅延時間(ミリ秒)を指定, とりあえず0.0
time2 0.488 : シリアルポートで受信される電文の遅延時間(ミリ秒)を指定, 0.0だと頻繁に時間飛びが発生したのでとりあえずこのぐらい。要チューニング箇所
設定の詳細はntpの公式を参照のこと.
ntpを一旦停止し,ドリフトファイルを削除,時計合わせを行なって,ntpを起動する.
$ sudo systemctl stop ntp
$ sudo rm -f /var/lib/ntp/ntp.drift
$ sudo ntpdate ntp.nict.jp
$ sudo systemctl start ntp
以上で、問題がなければ、ntpqコマンドで以下のような出力が出てくると思います。
(下記はカーネルモードを有効にしてるので、若干違いますが。)
GPSモジュールから受信した電文で直近採用されたものがtimecode=の箇所にでてくるので、
動作が怪しい時はこの辺り見るとよいかと。
$ watch -n 16 ntpq -crv -ccv -pn
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
version="ntpd 4.2.8p10@1.3728-o Sat Oct 7 14:29:08 UTC 2017 (1)",
processor="armv6l", system="Linux/4.9.59-pps+", leap=00, stratum=1,
precision=-19, rootdelay=0.000, rootdisp=62.729, refid=GPS,
reftime=dda64fc0.471cca3c Fri, Nov 3 2017 11:15:28.277,
clock=dda64fc0.d335cd8a Fri, Nov 3 2017 11:15:28.825, peer=38248, tc=4,
mintc=3, offset=0.000019, frequency=-10.019, sys_jitter=0.001907,
clk_jitter=0.003, clk_wander=0.000
associd=0 status=0000 no events, clk_unspec,
device="NMEA GPS Clock",
timecode="$GPGGA,021528.000,3442.5578,N,13527.6561,E,1,7,1.20,15.5,M,34.2,M,,*68",
poll=7, noreply=0, badformat=0, baddata=0, fudgetime2=488.000, stratum=0,
refid=GPS, flags=5
remote refid st t when poll reach delay offset jitter
==============================================================================
o127.127.20.0 .GPS. 0 l - 16 177 0.000 0.000 0.002
カーネルpps対応
TODO:
電源ブチ切り対策(リードオンリーなrootfs)
TODO: