NanoPi NEOとGPSモジュールでNTPサーバ PPS解決編

GPSモジュールと接続
写真は使い回し

NanoPi NEOをPPSなNTPサーバにしたのだが、どうしてもPPSとNMEAに同期しない、同期してもすぐに切れる、でも他のNTPサーバは同期するということで思いっきり迷走することになってしまったが、結局のところ、目が節穴だったのが主原因だった。

最終的なNTPの設定ファイルは以下のような感じになった。(「がとらぼ」の中の人のネットワークでは実際にはIPv6を有効にしている)

/etc/ntp.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
driftfile /var/lib/ntp/ntp.drift
#statsdir  /var/log/ntpstats/

server ntp1.jst.mfeed.ad.jp #210.173.160.27
server ntp2.jst.mfeed.ad.jp #210.173.160.57
server ntp3.jst.mfeed.ad.jp #210.173.160.87
#server ntp1.v6.mfeed.ad.jp #2001:3a0:0:2001::27:123
#server ntp2.v6.mfeed.ad.jp #2001:3a0:0:2005::57:123
#server ntp3.v6.mfeed.ad.jp #2001:3a0:0:2006::87:123

restrict -4 default ignore
#restrict -6 default ignore

restrict -4 127.0.0.1
#restrict -6 ::1

restrict 192.168.0.0 mask 255.255.255.248 nomodify notrap
#restrict abcd:1234:abcd:1234:: mask ffff:ffff:ffff:ffff:: nomodify notrap

restrict -4 210.173.160.27 mask 255.255.255.255 nomodify notrap noquery
restrict -4 210.173.160.57 mask 255.255.255.255 nomodify notrap noquery
restrict -4 210.173.160.87 mask 255.255.255.255 nomodify notrap noquery
restrict -6 2001:3a0:0:2001::27:123 nomodify notrap noquery
restrict -6 2001:3a0:0:2005::57:123 nomodify notrap noquery
restrict -6 2001:3a0:0:2006::87:123 nomodify notrap noquery

server 127.127.20.0 mode 17 minpoll 4 prefer
fudge  127.127.20.0 time2 0.175 refid NMEA

server 127.127.22.0 minpoll 4 true
fudge  127.127.22.0 flag3 1 refid PPS

MNEAを使わずにPPSの動作試験を繰り返していたという前提があって、PPSを同期させるにはPPS以外のどれかのserverにpreferを付けなければならないのでserver ntp1.jst.mfeed.ad.jpの後にpreferを付けたつもりだった。
しかし、上の設定例のようにserver行の末尾にコメントでIPアドレスを書いているんだけど、その末尾にpreferを書いてしまっていた。つまり書いたつもりがコメントの一部になってた。
上の例では他所のNTPサーバではなく、MNEAを有効にしてそれにpreferを付けている。(27行目)

28行目、MNEAの遅延補正にtime1を使ってた。これはTypo。リファレンスクロックドライバが127.127.20.*ならtime2だわね。上の例ではPPSとの時刻差0.175秒を補正している。

30行目、PPSの同期が切れないようにtrueを追加した。←強引だけどこれが効いてると思う。

$ ntptime
ntp_gettime() returns code 0 (OK)
  time dc906a84.a546f588  Thu, Apr  6 2017 16:19:32.645, (.645614050),
  maximum error 3000 us, estimated error 17 us, TAI offset 0
ntp_adjtime() returns code 0 (OK)
  modes 0x0 (),
  offset 0.000 us, frequency -30.816 ppm, interval 256 s,
  maximum error 3000 us, estimated error 17 us,
  status 0x2107 (PLL,PPSFREQ,PPSTIME,PPSSIGNAL,NANO),
  time constant 4, precision 0.001 us, tolerance 500 ppm,
  pps frequency -30.815 ppm, stability 5.914 ppm, jitter 10.656 us,
  intervals 106, jitter exceeded 8, stability exceeded 0, errors 0.
$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*GPS_NMEA(0)     .NMEA.           0 l   14   16  377    0.000    1.050  17.884
oPPS(0)          .PPS.            0 l   13   16  377    0.000    0.002   0.006
+ntp1.jst.mfeed. 133.243.236.17   2 u   27   64  377   19.929    1.864   0.205
+ntp2.jst.mfeed. 133.243.236.17   2 u   31   64  377   19.896    0.758   0.121
-ntp3.jst.mfeed. 133.243.236.17   2 u   27   64  377   17.214    1.781   0.071

内蔵時計がバカでシステム時計がみるみるズレるのでRTCモジュールでも付けないとダメなのかと思ったけどなんとかなった。
っていうか、見直すって大事。
ただ、UART(シリアルポート)が良くないのかジッターが大きいのが気になる。

setserialを使うと良いというページがあったので試してみた。

# apt install setserial
# setserial /dev/ttyS1 low_latency

ttyS1に対してlow_latencyをセットした。

$ cat /var/lib/setserial/autoserial.conf
###PORT STATE GENERATED USING AUTOSAVE-ONCE###
###AUTOSAVE-ONCE###
#KERNEL
/dev/ttyS0 uart undefined port 0x0000 irq 33 baud_base 1500000 spd_normal
/dev/ttyS1 uart undefined port 0x0000 irq 34 baud_base 1500000 spd_normal
/dev/ttyS3 uart undefined port 0x0000 irq 35 baud_base 1500000 spd_normal

自動認識されたIRQは正しそう。UARTの種類は認識されていない。おそらくNanoPi NEOのUARTの種類がU6_16550Aという亜種?だからかな。

$ setserial /dev/ttyS1 -a
/dev/ttyS1, Line 1, UART: undefined, Port: 0x0000, IRQ: 34
        Baud_base: 1500000, close_delay: 50, divisor: 0
        closing_wait: 3000
        Flags: spd_normal low_latency

一応、最後の行にlow_latencyというのが入ったので動いてる気な様子。
なので、setserial /dev/ttyS1 low_latency を/etc/rc.localに書き込む。其のときにntpが停まってるタイミングで実行される方が良いかも。

ただし、setserialでlow_latencyをセットした効果は全く無いように見える(ダメじゃん)。何か間違ってる?

2020年7月3日追記:
意味があるかどうかは不明だが、動いているのが気に入らないのでシリアルポート用のgettyを停めたいと思った。
シリアルポート用のgettyはserial-gettyというサービスで、 /lib/systemd/system/serial-getty@.service にある。
@付きのサービスは特殊なので普通にサービス名指定では停止できない。

$ sudo systemctl stop serial-getty@ttyS0.service        #停止
$ sudo systemctl disable serial-getty@ttyS0.service     #無効化

こんな感じで、@の後に停止したいポート名(上の例ではttyS0)を付ける。

と、いうことで、OS側のGPIO対応の遅れとしょーもないミス&勘違いがあってかなり日数がかかったものの、PPSを使ったNTPサーバも一応できた。
NanoPi NEO(無印)+ヒートシンク+送料、GPSモジュール+GPSアンテナ(こちらは送料無料)で合計約3,000円でPPS対応NTPサーバができるということになる。良い時代になったもんだなぁ。

関連記事: