Setup Stratum-1 Time Server

พรบ.คอมฯ 50 กำหนดไว้ว่าผู้ให้บริการต้องเก็บข้อมูลจราจรคอมพิวเตอร์ โดยมีความคลาดเคลื่อนของเวลาไม่เกิน 10 msec. จากเวลาอ้างอิง (stratum-0) ซึ่งเป็นเวลาที่ได้จากนาฬิกาอะตอม .. time source ที่เป็นนาฬิกาอะตอมไม่ได้หายากอย่างที่คิด สัญญาณจากดาวเทียม GPS ก็เป็นเวลาที่ได้จากนาฬิกาอะตอมเหมือนกัน ดังนั้นเซ็ต stratum-1 time server ก็แค่ใช้ time source จาก GPS เท่านั้นเอง

เพิ่งได้ USB GPS receiver แบบไม่มียี่ห้อ มาเมื่อหลายวันก่อน ใช้ชิปของ U-Blox ANTARIS LEA-4S ซึ่ง output เป็น NMEA messages ออกมาทาง USB ได้เลย และส่ง 1-Pulse-Per-Second (1PPS) ได้ด้วย เสียบ USB GPS Receiver เข้าคอมพิวเตอร์ (ติดตั้ง เดเบียน ลินุกซ์) ลอง cat /var/log/syslog หรือ dmesg ก็เห็นข้อความประมาณนี้

...
cdc_acm 1-1:1.0: ttyACM0: USB ACM device
usbcore: registered new driver cdc_acm
drivers/usb/class/cdc-acm.c: v0.25:USB Abstract Control Model driver for USB modems and ISDN adapters
...

แปลได้ว่าลินุกซ์เห็น USB GPS receiver เชื่อมกับ USB แล้ว และกำหนด device เป็น /dev/ttyACM0 ลอง

$ lsusb
...
Bus 001 Device 002: ID 1546:01a4 U-Blox AG
...

จะเห็นว่าลินุกซ์รู้จัก U-Blox AG. ด้วย ..ว่าแล้วก็ cat /dev/ttyACM0 ดูเลย

$ cat /dev/ttyACM0
...
$GPRMC,180032.00,A,1628.32246,N,10249.53339,E,0.362,287.84,261208,,,A*62
$GPVTG,287.84,T,,M,0.362,N,0.671,K,A*3B
$GPGGA,180032.00,1628.32246,N,10249.53339,E,1,04,3.23,226.6,M,-27.1,M,,*76
$GPGSA,A,3,22,32,16,06,,,,,,,,,3.98,3.23,2.31*02
$GPGSV,3,1,11,18,04,149,,14,46,058,,22,37,158,42,30,16,038,*71
$GPGSV,3,2,11,32,31,319,20,31,45,353,,29,11,081,,20,08,321,*7C
$GPGSV,3,3,11,16,55,199,44,03,03,197,33,06,10,185,27*4E
$GPGLL,1628.32246,N,10249.53339,E,180032.00,A,A*6C
$GPZDA,180032.00,26,12,2008,00,00*63
$GPRMC,180033.00,A,1628.32249,N,10249.53329,E,0.191,285.38,261208,,,A*66
$GPVTG,285.38,T,,M,0.191,N,0.354,K,A*32
$GPGGA,180033.00,1628.32249,N,10249.53329,E,1,04,3.24,226.6,M,-27.1,M,,*7E
...

จะเห็นเป็น NMEA messages ขึ้นมา .. ข่าวดีคือ NTP อ่าน NMEA message มาเป็น time source ได้เลย .. ก่อนอื่นลง package ntp ก่อน

$ sudo aptitude install ntp

แก้ไฟล์ /etc/ntp.conf เพิ่ม server ที่ใช้ Generic NMEA driver

server 127.127.20.0
fudge 127.127.20.0 time1 0.0 refid GPS

Restart ntp รอสัก 1-2 นาที แล้ว query ดู

$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*GPS_NMEA(0)     .GPS.            0 l   13   64  377    0.000   -2.154   3.517

แปลว่า ntp มัน sync กับ stratum-0 time source ได้ และขึ้นมาเป็น stratum-1 NTP server เรียบร้อย :D

อย่างไรก็ตาม หลังรันเซิร์ฟเวอร์และเก็บสถิติไปสักพักก็พบว่า นาฬิกามันไม่ได้แม่นยำอย่างที่คิด เวลาที่ได้มีความคลาดเคลื่อนแกว่งไปมาในช่วง +/- 4 msec บางจังหวะ peak ไปถึง +/- 20 msec ซึ่งถือว่าเป็น stratum-1 server ที่ performance ไม่ได้เรื่องเท่าไหร่ และยังไม่ได้ตามข้อกำหนดตามกฎหมายด้วย .. สาเหตุความคลาดเคลื่อนคงเพราะ NMEA message ไม่ใช่ time source ที่แม่นยำ .. ถ้าจะให้แม่นยำกว่านี้ ต้องใช้ 1PPS

USB GPS receiver ที่ได้มามันไม่ได้ต่อ 1PPS ออกมาให้ใช้งาน จะใช้ก็ต้องต่อเอง .. สิ่งที่ต้องใช้ก็มี DB-9 connector ตัวเมีย สายไฟ หัวแร้งบัดกรี ตะกั่วบัดกรีนิดหน่อย คู่มือของ U-Blox ANTARIS LEA-4S บอกว่าขา 1-PPS (i.e., TIMEPULSE) อยู่ที่ขา 28 จอเข้ากับขา 1 ของ DB-9 (ขา Data Carrier Detect ของ RS-232) และต่อ ground ของ receiver ไปยังขา 5 (GND) ของ DB-9 connector ก่อนเอาไปต่อก็เอา scope วัดสัญญาณดู สัญญาณ 1PPS จะเป็น pulse low-to-high amplitude 3.3 V ใช้ rising edge บอกวินาที

เมื่อต่อเข้ากับ RS-232 ของเครื่อง แล้วทีนี้จะอ่านสัญญาณ 1PPS ยังไงดี ? .. มีอยู่สามทางเลือก LinuxPPS, GPSD, และ SHMPPS

  • LinuxPPS เป็น PPSAPI implementation ตาม RFC2783 มีผลพลอยได้คือ precision ของนาฬิกาจะเป็น nanosecond แต่ต้อง patch / recompile kernel และอาจจะต้อง patch ntpd อีกด้วย (- -‘)
  • GPSD เป็นอีกทางเลือก ลองแล้วไม่สำเร็จ ทั้งที่ GPSD อ่านสัญญาณ 1PPS จาก /dev/ttyS0 แล้ว แต่มันไม่ signal ไปยัง ntpd .. GPS receiver แบบที่ป้อน 1PPS + NMEA ผ่าน RS-232 เพียวๆ อาจจะใช้กับ GPSD ได้
  • SHMPPS เป็นโปรแกรมอ่าน signal จาก serial/parallel port เลือก signal ได้หลายขา แล้วส่งไปยัง ntpd ผ่านทาง SHM (SHare Memory) .. อันนี้ง่ายสุดแล้ว

ก่อนอื่น แก้/เพิ่ม config ใน /etc/ntp.conf ให้ใช้ SHM driver

server 127.127.28.0 minpoll 4 maxpoll 4 prefer
fudge 127.127.28.0 refid PPS

ดาวน์โหลด shmpps extract / make จะได้ shm_splc2 เป็น binary และมี wrapper scripts อีก 2 ตัว ไม่ต้องสนใจ wrapper script ก็ได้ .. ลองสั่งให้ shm_splc2 อ่านสัญญาณ Data Carrier Detect จาก /dev/ttyS0 กันเลย

$ /usr/local/sbin/shm_splc2 -d /dev/ttyS0 -s -l DCD -u 0 -D &

รอสักพัก

$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*SHM(0)          .PPS.            0 l    3   16  377    0.000    0.047   0.003
+GPS_NMEA(0)     .GPS.            0 l   13   64  377    0.000   -2.154   3.517

ทิ้งไว้สักพักใหญ่ๆ .. offset และ jitter จะค่อยๆ ลู่เข้าสู่ 0.000

$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*SHM(0)          .PPS.            0 l    3   16  377    0.000    0.000   0.001
 GPS_NMEA(0)     .GPS.            0 l   33   64  377    0.000   -5.702  5.288

ปิดท้าย ดูจากกราฟก็จะเห็นว่ามันไม่ได้ 0.000000 s เสียทีเดียว แต่มีจังหวะแกว่งมากบ้างน้อยบ้าง จะเห็นว่านาฬิกามันไม่เที่ยงก็ต้องดู scale usec ซึ่งเทียบกับ stratum-1 servers ของหลายๆ แห่งก็จะได้ precision ประมาณเดียวกัน และน่าจะเกินพอสำหรับ พรบ. ..

เทียบ Offset ของ NMEA กับ 1PPS (scale: msec)

เทียบ Jitter ของ NMEA กับ 1PPS (scale: msec)

Offset ของ 1PPS (scale: usec)

Jitter ของ 1PPS (scale: usec)

GPS and Linux

ได้ USB GPS receiver มา (ของ ยี่ห้อนี้) ไม่ต้องคิดมาก เสียบ แล้ว dmesg ดู

$ dmesg
[157930.448089] usb 2-1: new full speed USB device using uhci_hcd and address 3
[157930.612998] usb 2-1: configuration #1 chosen from 1 choice
[157930.718842] cdc_acm 2-1:1.0: ttyACM0: USB ACM device
[157930.726652] usbcore: registered new interface driver cdc_acm
[157930.727462] cdc_acm: v0.26:USB Abstract Control Model driver for USB modems and ISDN adapters

อ่อ มี ttyACM0 … cat ดูโลด

$ cat /dev/ttyACM0
$GPRMC,115258.00,A,1628.33537,N,10249.54838,E,0.155,223.32,081208...
$GPVTG,223.32,T,,M,0.155,N,0.288,K,A*3C
$GPGGA,115258.00,1628.33537,N,10249.54838,E,1,08,1.68,185.0,M,-27.1....
$GPGSA,A,3,26,24,15,12,05,29,10,30,,,,,2.29,1.68,1.56*0F
$GPGSV,3,1,12,26,60,037,19,24,49,356,18,15,80,028,22,02,29,105,*7F
$GPGSV,3,2,12,12,08,193,22,05,08,205,33,18,20,278,17,29,59,280,22*7C
$GPGSV,3,3,12,10,22,041,13,21,15,320,19,30,09,228,21,09,21,169,20*75
$GPGLL,1628.33537,N,10249.54838,E,115258.00,A,A*63
...

อืมมม NMEA message มาเลย :) .. งั้น GPSd เลยดีกว่า

$ sudo aptitude install gpsd gpsd-clients

ลอง man แล้ว run แล้วไม่ work แฮะ .. ถาม อ.กู้เห็นบางคนเขาจะ set speed ก่อน

$ stty -F /dev/ttyACM0 ispeed 9600
$ gpsd /dev/ttyACM0

ทีนี้ก็

$ cgps

ได้ผลเป็นแบบนี้

หรือจะ

$ xgps

หรือจะลอง tangoGPS

More tangoGPS screenshot: Street Map | Arial | Topo