使用支持 1PPS (one pulse-per-second) 的 GPS 设备,搭建低成本高质量的 NTP 时间服务器。这里使用的 GPS 设备是 Garmin 18x LVC 。
拿到手的 Garmin 18x LVC 内建有5米长的电缆,但是上面没有接头。线缆接头需要自己焊接。参考规格说明书,接上一个 DB-9 RS-232 母头;再接上一个 USB Type-A 接口。这是为了从 USB 接口偷 5V 100mA 电力,驱动 GPS 运作。
GPS 输出的 1PPS 信号,需要连接到 RS-232 串口的 DCD。这将产生每秒一次的硬件中断。通过 Linux Kernel PPS 支持,可以让 Linux kernel 的系统时钟保持 ±1 微秒的走时精度。
Pin 1: DCD 1 Yellow: Measurement Pulse Output
+-------------------------------o----------------------------+.
| 2 Red: Vin
| +-----o----------------------------+.
| | 3 Black: GND +---.
| | +---o----------------------------+. '-===|###<
| Pin 2: RxD | | 4 White: TxD >=====|###<
| +-----------------------------o----------------------------+' ,-===|###<
| | Pin 5: GND | | 5 Black: GND (Drain Wire) / / +---'
| | +-----------------|-+---o----------------------------+' / GPS 18x
| | Pin 3: TxD | | 6 Green: RxD / LVC
| | +---------------------------o----------------------------+'
| | | | | |
1| | | |5 | | 1 Red: 5V
-v-v-v---v- +-----o----------------------------+.
( o o o o o ) | 2 Green: D+ +---.
o o o o / | ----------------------------+. '----|###<
'-------' | 3 White: D- >=====|###<
6 9 | ----------------------------+' ,----|###<
DB-9 Serial Connector | 4 Black: GND / +---'
Female Pin Contacts +---o----------------------------+' USB Type-A
Connector
GPS 需要至少看到 1/3 的天空才能持续追踪到 4 颗星,维持 3D 定位,正常运作。
这里使用的 Linux 发行版是 Debian GNU/Linux 10 "buster"。
$ sudo apt-get install gpsd gpsd-clients
安装 gpsd。配置 gpsd。注意对应的串行接口设备的名字,这里是 /dev/ttyS0。
$ 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="false"
# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="/dev/ttyS0"
# Other options you want to pass to gpsd
GPSD_OPTIONS="-b -n"
启动 gpsd 服务。
$ sudo systemctl start gpsd
运行 gpsmon,确认 gpsd 正常工作。注意包含 PPS offset 的输出。
$ sudo apt-get install ntp
安装 ntp。配置 ntp。
$ cat /etc/ntp.conf
driftfile /var/lib/ntp/ntp.drift
leapfile /usr/share/zoneinfo/leap-seconds.list
statsdir /var/log/ntpstats/
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable
restrict -4 default kod notrap nomodify nopeer noquery limited
restrict -6 default kod notrap nomodify nopeer noquery limited
restrict 127.0.0.1
restrict ::1
server 127.127.28.0 minpoll 4 maxpoll 4
fudge 127.127.28.0 time1 0.40444156 refid GPS flag4 1
server 127.127.28.1 minpoll 4 maxpoll 4 prefer
fudge 127.127.28.1 refid PPS
启动 ntp 服务。
$ sudo systemctl start ntp
运行 ntpq 确认 ntpd 正常运作。
$ ntpq -nc rv
associd=0 status=0415 leap_none, sync_uhf_radio, 1 event, clock_sync,
version="ntpd 4.2.8p12@1.3728-o (1)", processor="x86_64",
system="Linux/4.19.0-6-amd64", leap=00, stratum=1, precision=-23,
rootdelay=0.000, rootdisp=1.030, refid=PPS,
reftime=e1ad8615.568639d0 Wed, Dec 25 2019 14:54:13.337,
clock=e1ad8617.c43c03ed Wed, Dec 25 2019 14:54:15.766, peer=51432, tc=4,
mintc=3, offset=-0.013099, frequency=25.370, sys_jitter=0.163206,
clk_jitter=19.012, clk_wander=0.043, tai=37, leapsec=201701010000,
expire=202006280000
$ ntpq -np
remote refid st t when poll reach delay offset jitter
==============================================================================
+127.127.28.0 .GPS. 0 l 2 16 377 0.000 -3.871 5.281
*127.127.28.1 .PPS. 0 l 16 16 377 0.000 0.001 0.001
这样就有毫秒级精度的 NTP 服务器了。
参考资料
- GPSD Time Service HOWTO
- Compatible GPSes
- Garmin GPS 18x Technical Specfications