GPSを使ったNTPサーバの構築 その3 評価とGPSレシーバーの設定

# 1.GPSレシーバーをデフォルト設定で使った場合の結果
下図はインターネットタイムサーバとの同期が落ち着いて2日目から5日間のoffsetをグラフにしたもの。縦軸はoffset(単位ms)。
![ntp_peers-pinpoint1648998000,1649430000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611482/05e229e7-fbc4-9ad5-45a6-9305a8c2e11c.png)

## 1.1.測定条件
- GPSレシーバーの設定はデフォルトのまま。
- GPSレシーバーは3つとも南向きの窓に吸盤で貼り付けている。
- ntpdはGPSではなくインターネットタイムサーバを基準に合わせるようにしている。
- 自宅の回線はJ:COMの120M。

## 1.2.グラフの説明
- 0ms付近に固まっているのがNICT、INTERNET MFEED、Google。
- -40～-60msの紫の線がCloudflare。
- -80ms近辺の緑の線がVFAN UG-353。
- -100～-160msのオレンジの線がLOCOSYS LS23030-V2。
- 重なって見えにくいが-100ms近辺の黄色の線がLS23030-V2のPPS。
- -200～-300ms辺りで大きく揺らいでいる青の線がGLOBALSAT BU-353S4。

# 2.評価
インターネットに接続できる環境なら、あえてGPSレシーバー使ってタイムサーバ構築しなくとも十分高い精度の時刻が得られている。GPS使ったタイムサーバはPPS無しならインターネットタイムサーバよりも精度は悪い(分かっていたことだが)。

## 2.1.インターネットタイムサーバ
Cloudflareを除いたインターネットタイムサーバはほぼ同時刻を報告しており、offsetの変動もPPS(黄色の線)のそれと同期している。PPSの秒刻みは正確なはずなので、インターネットタイムサーバから得られる時刻が高い精度を持っていることがわかる。

GoogleとCloudflareは最近知ったので試しに加えてみたのだが、GoogleはNICTやMFEEDと遜色の無い精度が出ている。delayがNICTやMFEEDの15ms程度に対し40～50msとネットワーク的に若干遠いがjitterは±3ms程度で安定していた。Strtum 1だし十分メインのタイムサーバにできる。

Cloudflareは他のインターネットタイムサーバに比べるとイマイチ。Strtum 3であることを考慮しても、時刻の遅れがあるしoffsetの変動も大きい。あえて採用する必要は無い。ただCloudflareはNTPSecに対応しているので、信憑性が必要なら使うの有りか。

## 2.2.GPSレシーバー
いずれもインターネットタイムサーバよりoffsetの変動が大きく、GPSレシーバー同士だと、UG-353、LS23030-V2、BU-353S4の順で変動が大きくなる。

LS23030-V2はグラフにけっこうなスパイクが出ている。転送速度が115200bpsと一番速く、PPS有で、お値段も高かったのでもっと精度が良いと思っていた。
BU-353S4は時々大きな変動が起きている。昔構築した時もこんな感じだった。時刻の遅れについては、転送速度が4800bpsと遅いことが原因と推察。

# 3.GPSレシーバーの最適化について
どのGPSレシーバーのoffset変動は100ms以下なので、PPSによる秒刻みとインターネットタイムサーバを使っての時刻補正を行えば、このままでも十分なタイムサーバを構築できると思う。が、それはそれとしてもう少しGPSから得られる時刻の精度を上げたい。
ntpdのNMEAドライバのリファレンスを見ると以下のように書かれている。
> Caveat: Using higher line speeds does not necessarily increase the precision of the timing device. Higher line speeds are not necessarily helpful for the NMEA driver, either. They can be used to accomodate for an amount of data that does not fit into a 1-second cycle at 4800 bps, but high-speed high-volume NMEA data is likely to cause trouble with the serial line driver since NMEA supports no protocol handshake. Any device that is exclusively used for time synchronisation purposes should be configured to transmit the relevant data only, e.g. one \\$GPRMC or \\$GPZDA per second, at a linespeed of 4800 bps or 9600 bps.

- 転送速度を上げても精度が上がるとは限らない
- NMEAドライバにとって、転送速度を上げることが必ずしも有益では無い。
- 高速で大量のNMEAデータはシリアルラインドライバとの間でトラブルを起こす可能性が高くなる。
- 4800bpsまたは9600bpsの回線速度で、1秒間に1回の\\$GPRMCや\\$GPZDAなど、1種類のセンテンスのみ送信するよう設定する。

転送速度が速いとトラブる可能性有とあるが、このリファレンスが書かれたのがずいぶんと前のようなので、現在のマシンスペックにそのまま当てはまるかは微妙。
ただ転送速度が遅く、ntpdに不要なセンテンスを送信させてると精度が悪くなるというのは道理。
転送速度とセンテンスの限定をまとめてやっても良いのだが、センテンスの限定がどのくらい精度に影響を与えるのか知りたいのでまずはセンテンスの限定を行い、後で転送速度を上げることにする。

## 3.1.ntpdのNMEAプロトコル処理について
設定の前にntpdのNMEAドライバのソースを覗いてみた。
受信したセンテンス毎にnmea_procrec()関数が呼ばれて、センテンスから時刻を取り出す処理が行われる。処理できるセンテンスは GPRMC、GPGGA、GPGLL、GPZDA or GPZDG、PGRMF、PUBX で、GPSレシーバーから1サイクルで送信した中にこれらが複数含まれていれば、それらすべて処理するようになっている。
同じ時刻を持つセンテンスを何回も処理する必要は無いので、GPSモジュール側で送信センテンスの設定が出来なくともmodeフラグで処理するセンテンスを限定すれば精度が改善する可能性がある(今回は検証しないが)。

## 3.2.GPSレシーバーが送信するセンテンスの順序
と、ここでもう一点気になることが。
GPSレシーバーから送られてくる時刻は秒単位なので、1サイクルで送られてくるセンテンス群の後ろよりも、前の方に送られてくるセンテンスを処理した方が時刻の遅れが少ないのではないか。また位置情報センテンスの数は捉えている衛星数により変動するはずなので、位置情報より前のセンテンスを処理した方がoffsetの変動は小さくなると推察。
ということで調べてみたのが下表。GPSレシーバーから送信するセンテンスを限定できない場合、始めの方に受信するセンテンスのみ処理するようntpdを設定した方がよさそう。

| 順番 | UG-353 | BU-353S4 | LS23030-V2 |
|:-:|:-:|:-:|:-:|
| 1 | GPRMC◎ | GPGGA◎ | GNGGA◎ |
| 2 | GPVTG | GPGSA☆ | GNGLL |
| 3 | GPGGA◎ | GPGSV☆ | GNGSA☆ |
| 4 | GPGSA☆ | GPRMC◎ | GPGSV☆ |
| 5 | GPGSV☆ | - | GLGSV☆ |
| 6 | GPGLL◎ | - | GNRMC◎ |
| 7 | - | - | GNVTG |
| 8 | - | - | GNGST |

◎...ntpdの処理対象、☆...複数行

# 4.GPSレシーバーの送信センテンス設定
データシート([その2](https://qiita.com/R800/items/7e34a374257bdced34a8)参照)に記載されているコマンドを使って、各GPSレシーバーから送信するセンテンスを1種類に限定する。GPSモジュールの内部処理がどうなっているまでは分からなかったので、デフォルトで現在送信されているセンテンス群の1番目を残し、その他のセンテンスの送信を停止ことにする。
これでしばらく動かして、結果を確認する。

~~~sh:UG-353のGPVTG、GPGGA、GPGSA、GPGSV、GPGLL送信をOff
#/bin/sh
export UBXOPTS="-P 14 -s 9600 -f /dev/gps0"
ubxtool -p CFG-MSG,0xF0,0x05,0
ubxtool -p CFG-MSG,0xF0,0x00,0
ubxtool -p CFG-MSG,0xF0,0x02,0
ubxtool -p CFG-MSG,0xF0,0x03,0
ubxtool -p CFG-MSG,0xF0,0x01,0
~~~
~~~sh:BU-353S4のGPGSA、GPGSV、GPRMC送信をOff
#!/bin/sh
(
  printf '$PSRF103,2,0,0,1*26\r\n'
  printf '$PSRF103,3,0,0,1*27\r\n'
  printf '$PSRF103,4,0,0,1*20\r\n'
) > /dev/gps1
~~~

~~~sh:LS23030-V2のGNGLL、GNGSA、GPGSV&GLGSV、GNRMC、GNVTG、GNGST送信をOff
#!/bin/sh
(
  printf '$PAIR062,1,0*3F\r\n'
  printf '$PAIR062,2,0*3C\r\n'
  printf '$PAIR062,3,0*3D\r\n'
  printf '$PAIR062,4,0*3A\r\n'
  printf '$PAIR062,5,0*3B\r\n'
  printf '$PAIR062,8,0*36\r\n'
) > /dev/gps2
~~~

# おまけ.BU-353S4(u-blox 7)のセンテンス送信設定
ubxtoolでセンテンス送信設定を行う場合はCFG-MSGプリセットを使用する。

~~~sh:センテンス送信状態の取得と設定
ubxtool -p CFG-MSG,<Class>,<Id>[,<rate>]
~~~
ClassとIdは下表の通り。rateには送信間隔を10進数で指定する。デフォルトは1で、0を指定すると送信しなくなる。rateを指定しなければ現在の設定が取得できる。

u-blox 7 Receiver Description Including Protocol Specification V14のP.51「23 NMEA Messages Overview」より抜粋。

| Mnemonic | Class | Id | Description |
|:-:|:-:|:-:|:-|
| DTM | 0xF0 | 0x0A | Datum Reference |
| GBS | 0xF0 | 0x09 | GNSS Satellite Fault Detection |
| GGA | 0xF0 | 0x00 | Global positioning system fix data |
| GLL | 0xF0 | 0x01 | Latitude and longitude, with time of position fix and status |
| GLQ | 0xF0 | 0x43 | Poll a standard message (if the current Talker ID is GL) |
| GNQ | 0xF0 | 0x42 | Poll a standard message (if the current Talker ID is GN) |
| GNS | 0xF0 | 0x0D | GNSS fix data |
| GPQ | 0xF0 | 0x40 | Poll a standard message (if the current Talker ID is GP) |
| GRS | 0xF0 | 0x06 | GNSS Range Residuals |
| GSA | 0xF0 | 0x02 | GNSS DOP and Active Satellites |
| GST | 0xF0 | 0x07 | GNSS Pseudo Range Error Statistics |
| GSV | 0xF0 | 0x03 | GNSS Satellites in View |
| RMC | 0xF0 | 0x04 | Recommended Minimum data |
| TXT | 0xF0 | 0x41 | Text Transmission |
| VTG | 0xF0 | 0x05 | Course over ground and Ground speed |
| ZDA | 0xF1 | 0x08 | Time and Date |