BN-880 で時刻を取得できるのか？ Raspberry Pi で NTP サーバ


GPS を使って時刻を取得しようと 2018/4 に [LEA-M8T GPS breakout board with Precision Timing](https://www.csgshop.com/product.php?id_product=244) ([コア](https://www.u-blox.com/ja/product/neolea-m8t-series))を $98.99 で買ったのですが、外付け回路が面倒で放置していました。

そしたらこないだ、[Beitian BN-880](http://www.sz-beitian.com/ProductsDetailEng?product_id=163) を [bangood](https://www.banggood.com/ja/UBLOX-NEO-M8N-BN-880-Flight-Control-GPS-Module-Dual-Module-Compass-p-971082.html) で 1,812円 と書いているのを見つけてしまい、アンテナ内蔵だし外付け回路も不要そうだし安いしでついつい買ってしまいました。
![PSX_20190408_013147.jpg](https://qiita-image-store.s3.amazonaws.com/0/306041/0b96e14e-0515-3eda-f579-a1cce40b6632.jpeg)

検索してみるとフォーラムに[マニュアル](https://www.rcgroups.com/forums/showthread.php?2370082-Bn-880-gps-setup)が上がってますねぇ。コアに [u-blox M8030-KT](https://www.u-blox.com/ja/product/ubx-m8030-series) を使っているとのこと。なるほど、結局 u-blox なんですね。![PSX_20190408_013515.jpg](https://qiita-image-store.s3.amazonaws.com/0/306041/ee859e97-c18b-8485-7253-35f6f235b7bd.jpeg)
![PSX_20190408_013938.jpg](https://qiita-image-store.s3.amazonaws.com/0/306041/8b210efc-7f2f-865d-f564-8d737875b568.jpeg)
BN-880 のピンアサイン

|PIN番号|名前|I/O|内容|ケーブルの色|
|----:|:--:|:--:|:---|:--------|
| 1|SDA|O|I2C|黄|
| 2|GND|G|接地|黒|
| 3|TX|O|UART Tx, TTLレベル|白|
| 4|RX|I|UART Rx, TTLレベル|緑|
| 5|Vcc|I|電源 DC 2.8～6.0V|赤|
| 6|SCL|I|I2C|灰|

ぐらいの情報があればあとは M8030-KT のマニュアル見れば良いということですね。
[質問コーナー](https://portal.u-blox.com/s/question/0D52p00008HKDtfCAH/how-to-use-i2c-to-get-the-nmea-frames) を見ると I2C 接続はコマンドを送った後に、1秒程度待ってから読み込みしないといけないようです。
先ずは UART として繋いで設定するのが楽かな。

Raspberry Pi の [GPIO の配置](https://www.raspberrypi.org/documentation/usage/gpio/README.md) (pinio コマンド, [フォーラムの記事](https://www.raspberrypi.org/forums/viewtopic.php?t=51788)) と見比べるとこんな感じで繋げたら良さそう。

|BN-880|Raspberry Pi GPIO|名前|色|
|--:|:-:|:--------|:-:|
| 5|4, 2|5V|赤|
| 2|6, 9, 14, 20, 25, 30, 34, 39|GND|黒|
| 4(Rx)| 8 Tx (GPIO14)|UART|緑|
| 3(Tx)|10 Rx (GPIO15)|UART|白|
![PSX_20190408_014127.jpg](https://qiita-image-store.s3.amazonaws.com/0/306041/44f9e91f-1005-062c-a41a-3e54a19bf482.jpeg)
GPIO の4,6,8,10 と縦並びで刺さるようなのでソケットを付け替えて...あら、色まで書いておきながら接続間違えてるわ。ということで、赤⇔黒、緑⇔白を入れ替えて付け直し (写真省略)。 2ピンのほうは I2C 用みたいなので放置。

コンソール用の serial をログインに使わないようにする。
sudo vi /boot/cmdline.txt
で、console=serial0,115200 という部分を消去、getty を停止。

```text:/boot/cmdline.txt
> sudo vi /boot/cmdline.txt
#dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=0001a5c2-07 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
dwc_otg.lpm_enable=0 console=tty1 root=PARTUUID=0001a5c2-07 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
> ps -ax | grep getty
  509 tty1     Ss+    0:00 /sbin/agetty --noclear tty1 linux
  512 ttyS0    Ss+    0:00 /sbin/agetty --keep-baud 115200,38400,9600 ttyS0 vt220
 1515 pts/1    S+     0:00 grep tty
> sudo systemctl stop serial-getty@ttyS0.service
> sudo systemctl disable serial-getty@ttyS0.service
> ps -ax | grep getty
  509 tty1     Ss+    0:00 /sbin/agetty --noclear tty1 linux
 1901 pts/1    S+     0:00 grep getty
```
GPS モジュールからの出力を確認。9600bps にして cat してみる。

```tcsh:
> sudo stty -F /dev/ttyS0 9600
> sudo cat /dev/ttyS0
$GPGSV,2,1,07,07,01,316,,08,32,229,19,16,61,347,29,21,30,065,23*7E

$GPGSV,2,2,07,23,,,25,26,55,049,27,27,,,28*4B

$GLGSV,1,1,01,75,,,29*6D

...snip...
```
正しく出力されていました。
GPS関連のコマンドをインストールする。インストールすると何故か gpsd が起動したので止める。

```tcsh:
> sudo bash
# apt install gpsd gpsd-clients pps-tools
# ps -ax | grep gps
 2578 ?        S<s    0:00 /usr/sbin/gpsd -N
 3553 pts/1    S+     0:00 grep gps
# systemctl stop gpsd.socket
# ps -ax | grep gps
 3567 pts/1    S+     0:00 grep gps
```

```tcsh:
> sudo gpsmon /dev/ttyS0
/dev/ttyS0 9600 8N1           NMEA0183>
┌──────────────────────────────────────────────────────────────────────────────┐
│Time: 2019-04-07T05:13:04.000Z Lat:  34 39' xx.xxx" N Lon: 135 28' xx.xxx" E  │
└───────────────────────────────── Cooked TPV ─────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ GNTXT GNRMC GNVTG GNGGA GNGSA GPGSV GLGSV GNGLL                              │
└───────────────────────────────── Sentences ──────────────────────────────────┘
┌──────────────────┐┌────────────────────────────┐┌────────────────────────────┐
│Ch PRN  Az El S/N ││Time:      051304.00        ││Time:      051304.00        │
│ 0   7 317  4   0 ││Latitude:    3439.xxxxx N   ││Latitude:  3439.xxxxx       │
│ 1   8 232 35  27 ││Longitude:  13528.xxxxx E   ││Longitude: 13528.xxxxx      │
│ 2   9 302 19  26 ││Speed:     0.101            ││Altitude:  14.6             │
│ 3  16 356 62  29 ││Course:                     ││Quality:   1   Sats: 06     │
│ 4  21  60 29  24 ││Status:    A       FAA: A   ││HDOP:      1.65             │
│ 5  23 268 31  18 ││MagVar:                     ││Geoid:     34.1             │
│ 6  26  55 52  25 │└─────────── RMC ────────────┘└─────────── GGA ────────────┘
│ 7  27   0  0  28 │┌────────────────────────────┐┌────────────────────────────┐
│ 8  65 263  5   0 ││Mode: A3 Sats: 75           ││UTC:           RMS:         │
│ 9  66 318  5   0 ││DOP: H=1.65  V=3.12  P=3.52 ││MAJ:           MIN:         │
│10  75 336 43  30 ││TOFF:  0.105370828          ││ORI:           LAT:         │
│11  76 314  6   0 ││PPS:                        ││LON:           ALT:         │
└────── GSV ───────┘└──────── GSA + PPS ─────────┘└─────────── GST ────────────┘
(68) $GNRMC,051304.00,A,3439.12115,N,13528.00466,E,0.101,,070419,,,A*64
...snip
```
gpsd 経由での動作確認

```tcsh:gpsdで動作確認
> sudo systemctl start gpsd.socket
> sudo cgps -s
┌───────────────────────────────────────────┐┌─────────────────────────────────┐
│    Time:       n/a                        ││PRN:   Elev:  Azim:  SNR:  Used: │
│    Latitude:   n/a                        ││                                 │
│    Longitude:  n/a                        ││                                 │
│    Altitude:   n/a                        ││                                 │
│    Speed:      n/a                        ││                                 │
│    Heading:    n/a                        ││                                 │
│    Climb:      n/a                        ││                                 │
│    Status:     NO FIX (0 secs)            ││                                 │
│    Longitude Err:   n/a                   ││                                 │
│    Latitude Err:    n/a                   ││                                 │
│    Altitude Err:    n/a                   ││                                 │
│    Course Err:      n/a                   ││                                 │
│    Speed Err:       n/a                   ││                                 │
│    Time offset:     n/a                   ││                                 │
│    Grid Square:     n/a                   ││                                 │
└───────────────────────────────────────────┘└─────────────────────────────────┘

```
ありゃ？ダメですねぇ？あ、gpsd の設定をしてませんでした。
DEVICES="/dev/ttyS0"
GPSD_OPTIONS="-n -P /var/run/gpsd.pid -F /var/run/gpsd.sock"

```tcsh:
> sudo vi /etc/default/gpsd
> cat /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=""
DEVICES="/dev/ttyS0"

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

> sudo systemctl restart gpsd.socket
> sudo cgps -s
┌───────────────────────────────────────────┐┌─────────────────────────────────┐
│    Time:       2019-04-07T05:44:47.000Z   ││PRN:   Elev:  Azim:  SNR:  Used: │
│    Latitude:    34.xxxxxx N               ││   7    15    318    23      N   │
│    Longitude:  135.xxxxxx E               ││   8    47    245    22      Y   │
│    Altitude:   111.3 ft                   ││   9    20    288    30      N   │
│    Speed:      2.0 mph                    ││  16    61    027    26      Y   │
│    Heading:    147.1 deg (true)           ││  21    23    049    22      Y   │
│    Climb:      -18.3 ft/min               ││  23    25    252    25      Y   │
│    Status:     3D FIX (76 secs)           ││  26    45    074    12      Y   │
│    Longitude Err:   +/- 55 ft             ││  27    78    296    16      Y   │
│    Latitude Err:    +/- 99 ft             ││  74    48    102    23      N   │
│    Altitude Err:    +/- 138 ft            ││  75    58    351    29      Y   │
│    Course Err:      n/a                   ││  85    86    144    23      N   │
│    Speed Err:       +/- 3 mph             ││                                 │
│    Time offset:     0.107                 ││                                 │
│    Grid Square:     PM74rp                ││                                 │
└───────────────────────────────────────────┘└─────────────────────────────────┘
```
おー、いった。
とりあえず 1PPS 無しで ntpd に入れる。

```tcsh:
> cat /etc/ntp.conf
> sudo systemctl restart ntp
driftfile /var/lib/ntp/ntp.drift

statsdir /var/log/ntpstats/
statistics loopstats peerstats clockstats sysstats
filegen loopstats file loopstats type month link enable
filegen peerstats file peerstats type month link enable
filegen clockstats file clockstats type month link enable
filegen sysstats file clockstats type month link enable
filegen rawstats file clockstats type month link enable

server ntp-a3.nict.go.jp iburst
server ntp-b2.nict.go.jp iburst
server ntp-b3.nict.go.jp iburst
server ntp-a2.nict.go.jp iburst
server ntp1.jst.mfeed.ad.jp iburst
server ntp2.jst.mfeed.ad.jp iburst
server ntp3.jst.mfeed.ad.jp iburst
pool time.google.com iburst
server ats1.e-timing.ne.jp iburst
server cwa225.bai.ne.jp iburst
server cwa201.bai.ne.jp iburst
server baidb6a8fb9.bai.ne.jp iburst

server 127.127.28.0 minpoll 4 maxpoll 4
fudge 127.127.28.0 refid GPS stratum 8
```
12時間ほど経過し

```tcsh:ntpq&nbsp;-p
> ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 time.google.com .POOL.          16 p    -   64    0    0.000    0.000   0.000
xSHM(0)          .GPS.            8 l   16   16  377    0.000  -99.654   1.786
+ntp-a3.nict.go. .NICT.           1 u  631 1024  377   11.646    0.589   0.718
*ntp-b2.nict.go. .NICT.           1 u  937 1024  377    9.187   -0.678   2.339
+ntp-b3.nict.go. .NICT.           1 u  612 1024  377    9.226   -0.488   1.628
+ntp-a2.nict.go. .NICT.           1 u 1004 1024  377   11.113    0.195  12.755
+ntp1.jst.mfeed. 133.243.236.17   2 u 1015 1024  377    9.046   -0.417  12.725
+ntp2.jst.mfeed. 133.243.236.17   2 u  792 1024  377    9.848    0.332   1.076
+ntp3.jst.mfeed. 133.243.236.17   2 u 1001 1024  377   10.793   -0.109   1.164
+61.114.187.55 ( .PPS.            1 u  861 1024  377   11.211   -0.092   1.158
+cwa225.bai.ne.j 210.171.0.34     4 u  861 1024  377    4.276   -0.238   4.224
-cwa201.bai.ne.j 210.171.0.34     4 u  567 1024  377    1.731    3.214   2.522
 baidb6a8fb9.bai .INIT.          16 u    - 1024    0    0.000    0.000   0.000
>
```
google は delay が多いので外して、100ms ぐらいずれているので time1 ntp.conf を

```tcsh:ntp.conf
> vi ntp.conf
...
pool ntp.nict.jp iburst
server ntp1.jst.mfeed.ad.jp iburst
server ntp2.jst.mfeed.ad.jp iburst
server ntp3.jst.mfeed.ad.jp iburst
# pool time.google.com iburst
server ats1.e-timing.ne.jp iburst
server cwa225.bai.ne.jp iburst
server cwa201.bai.ne.jp iburst
# server ntp0.lordynet.org iburst
# server ntp1.lordynet.org iburst

server 127.127.28.0 minpoll 4 maxpoll 4 burst
fudge 127.127.28.0 time1 0.1004 refid BN880 stratum 8
...
> sudo systemctl restart ntp
```
という感じにしてみました。12時間ほど経過

```tcsh:
~> ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 ntp.nict.jp     .POOL.          16 p    -   64    0    0.000    0.000   0.000
 SHM(0)          .BN88.           8 l 300m   16    0    0.000  -650.71   0.000
-ntp1.jst.mfeed. 133.243.236.17   2 u  868 1024  377   10.987    1.030   1.448
-ntp2.jst.mfeed. 133.243.236.17   2 u  625 1024  377   11.679    1.728   0.732
-ntp3.jst.mfeed. 133.243.236.17   2 u    6 1024  377   11.211   -0.168   0.923
-61.114.187.55 ( .PPS.            1 u  949 1024  375   14.688    1.849   0.785
-cwa225.bai.ne.j 210.171.0.34     4 u  863 1024  377    5.764    1.095   1.607
-cwa201.bai.ne.j 210.171.0.34     4 u 1015 1024  377    3.292    9.403   2.229
+ntp-b3.nict.go. .NICT.           1 u  756 1024  377   10.491    0.631   0.821
-ntp-a2.nict.go. .NICT.           1 u 1006 1024  377    9.664   -0.620   2.238
+ntp-a3.nict.go. .NICT.           1 u 1065 1024  377   10.804    0.587   0.944
*ntp-b2.nict.go. .NICT.           1 u   22 1024  377   13.126    1.234   0.747
```
えー、GPS に 300分間時刻合わせてくれてないー。どういうこと？と見てみると

```shell:
> gpspipe -r
{"class":"VERSION","release":"3.16","rev":"3.16-4","proto_major":3,"proto_minor":11}
{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyS0","driver":"u-blox","subtype":"SW ROM CORE 3.01 (107888),HW 00080000,FWVER=SPG 3.01,PROTVER=18","activated":"2019-04-08T10:04:56.299Z","flags":1,"native":0,"bps":9600,"parity":"N","stopbits":2,"cycle":1.00,"mincycle":0.25}]}
{"class":"WATCH","enable":true,"json":false,"nmea":true,"raw":0,"scaled":false,"timing":false,"split24":false,"pps":false}
$GNTXT,01,01,02,u-blox AG - www.u-blox.com*4E
$GNTXT,01,01,02,HW UBX-M8030 00080000*60
$GNTXT,01,01,02,ROM CORE 3.01 (107888)*2B
$GNTXT,01,01,02,FWVER=SPG 3.01*46
$GNTXT,01,01,02,PROTVER=18.00*11
$GNTXT,01,01,02,GPS;GLO;GAL;BDS*77
$GNTXT,01,01,02,SBAS;IMES;QZSS*49
$GNTXT,01,01,02,u-blox AG - www.u-blox.com*4E
$GNTXT,01,01,02,HW UBX-M8030 00080000*60
$GNTXT,01,01,02,ROM CORE 3.01 (107888)*2B
$GNTXT,01,01,02,u-blox AG - www.u-blox.com*4E
$GNTXT,01,01,02,HW UBX-M8030 00080000*60
$GNTXT,01,01,02,ROM CORE 3.01 (107888)*2B
$GNTXT,01,01,02,u-blox AG - www.u-blox.com*4E
$GNTXT,01,01,02,HW UBX-M8030 00080000*60
$GNTXT,01,01,02,ROM CORE 3.01 (107888)*2B
```
なんですかこれ？機器情報しか見えないんですけども。1pps は点滅してるけど 1秒間隔じゃない？何か設定が変わってしまった？
u-center でちょっと見てみますか。u-center で捕まえる衛星の設定とか通信速度の変更とかすると変わるのかな？
→[BN-880 を設定する](https://qiita.com/jp_yen/items/a4a6adb812c8ff944348)


以下、メモ書き。以降の参考用。

参考 [GPS,GPS+PPSを使うNTPサーバの調整](http://k-hiura.cocolog-nifty.com/blog/2017/11/gpsgpsppsntp-7b.html) 前後の記事
[Raspberry Pi 3 で NTP Stratum-1 Server を作る(Raspbian stretch)](https://www.netfort.gr.jp/~tosihisa/notebook/doku.php/raspberrypi/log20171231_rpi3_ntp_stratum_1#dokuwiki__top)
[GPSのPPS信号を使った Stratum-1 NTPサーバの作り方](https://nyanchew.com/?q=jp/gps%E3%81%AEpps%E4%BF%A1%E5%8F%B7%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F-stratum-1-ntp%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9)
[ntpd – PPS discipline まずは普通に較正 編](https://kana.me/entry/ntpd-pps-discipline) 「興味のないところは手を抜きまくります。」と書いている割には fft とかして補正かけてたり。

[[ntp:questions] Ignore one server except in extreme conditions?](http://lists.ntp.org/pipermail/questions/2011-November/030972.html)
これによると、PPS と NEMA は同じドライバに読ませるのが良いみたいですね。
fudge 127.127.20.0 flag11

1PPS だけだと秒のタイミングは分かるけど時刻は分からない (秒針の音を聞いているようなもの)、NEMA は電文なので PPS ほど正確な時刻を伝えられない (人が時間を読み上げているようなもの)。

起動時に時刻を修正できるように ntpd -qgx (≒ntpdate)してから ntpd を起動するか、gpsd から日付を抽出して合わせるスクリプトが必要ですねぇ。

M8 がまだ使えてないのに M9 が広まってますね [SparkFun GPS-RTK2 Board - ZED-F9P](https://www.sparkfun.com/products/15136) 
[RCB-F9Tタイミング・ボード](https://www.u-blox.com/ja/product/rcb-f9t-timing-board)


ntpq -p の行頭に表示される記号は以下の意味があります。
　空白 Stratum 値が高い（精度が悪い）ため、または、到達不能などにより同期候補から外された
　x　同期候補から外された (アルゴリズムにより正確な時計でないと判断された)
　.　同期候補から外された (candidate(候補) list の末尾から外された)
　-　同期候補から外された (clustering algorithm により)
　+　同期候補にあがっている
　#　現在同期しているサーバだが、距離が遠い
　*　現在同期中のサーバ
　o　同期(pps signal in use)

ntpq -pw とするとホスト名が切れないらしい。

ntptrace で表示されるもの。左から
1. ホスト名
2. その stratum 値
3. 自マシンのシステム時刻との ntpd 内部時刻との時刻差 (秒)
4. 同期距離
5. リファレンスクロック ID (stratum1 のみ)

filegen peerstats file peerstats type month link enable と指定した peerstats ファイルの中身
1. ユリウス日 (日付)
2. UTC での時刻（単位：秒）
3. 相手 IP アドレス(注:127.127.1.0 はローカルクロック)
4. 16 進での peerstatus
5. 秒単位でのオフセット（→リファレンスサーバとの時刻差）
6. 秒単位での遅延
7. 秒単位での分散

ntp.conf calibrate

NTP Release version
http://support.ntp.org/rss/releases.xml

[gpsd](http://www.catb.org/gpsd/gpsd-time-service-howto.html)