On my PC I want to feed chrony from GPS. For this, I installed gpsd
and pps-tools
. I have a GPS connected to the serial port /dev/ttyS0
and the PPS is connected to the DCD input. Apparently, the PPS pulses are received correctly:
$ sudo ppscheck /dev/ttyS0
# Seconds nanoSecs Signals
1646915383.000347816 TIOCM_CD
1646915383.100323649
1646915384.000213974 TIOCM_CD
1646915384.100172453
...
so far so good. Also, the data from the GPS module seems to be received correctly. I verify this using sudo gpsmon /dev/ttyS0
. It appears as the $GPRMC
sentence is successfully received and that the data was valid. A time could be extracted and the PPS was detected also:
┌──────────────────────────────────────────────────────────────────────────────┐
│Time: 2022-03-10T12:31:10.000Z Lat: 46 xx.xxxxxx' N Lon: 7 xx.xxxxxx' E │
└───────────────────────────────── Cooked TPV ─────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ GPRMC │
└───────────────────────────────── Sentences ──────────────────────────────────┘
┌───────────────────────┌─────────────────────────┌────────────────────────────┐
│ SVID PRN Az El SN HU│Time: 123110 │Time: │
│ │Latitude: 46xx.xxxxx N │Latitude: │
│ │Longitude: 7xx.xxxxx E │Longitude: │
│ │Speed: 000.0 │Altitude: │
│ │Course: 000.0 │Quality: Sats: │
│ │Status: A FAA: │HDOP: │
│ │MagVar: 000.0E │Geoid: │
│ └───────── RMC ───────────└─────────── GGA ────────────┘
│ ┌─────────────────────────┌────────────────────────────┐
│ │Mode: Sats: │UTC: RMS: │
│ │DOP H= V= P= │MAJ: MIN: │
│ │TOFF: 0.132531938 │ORI: LAT: │
│ │PPS: 0.000246686 │LON: ALT: │
└──────── GSV ──────────└────── GSA + PPS ────────└─────────── GST ────────────┘
so far, so good. I would like to run gpsd
now such that chrony
can get the time from it. Here the trouble begins. I test gpsd
as follows `
gpsd:INFO: launching (Version 3.23.1, revision 3.23.1)
gpsd:IO: opening IPv4 socket
gpsd:SPIN: passivesock_af() -> 3
gpsd:IO: opening IPv6 socket
gpsd:SPIN: passivesock_af() -> 4
gpsd:INFO: listening on port gpsd
gpsd:PROG: NTP: shmat(0,0,0) succeeded, segment 0
gpsd:PROG: NTP: shmat(1,0,0) succeeded, segment 1
gpsd:PROG: NTP: shmat(2,0,0) succeeded, segment 2
gpsd:PROG: NTP: shmat(3,0,0) succeeded, segment 3
gpsd:PROG: NTP: shmat(4,0,0) succeeded, segment 4
gpsd:PROG: NTP: shmat(5,0,0) succeeded, segment 5
gpsd:PROG: NTP: shmat(6,0,0) succeeded, segment 6
gpsd:PROG: NTP: shmat(7,0,0) succeeded, segment 7
gpsd:PROG: successfully connected to the DBUS system bus
gpsd:PROG: shmget(0x47505344, 26712, 0666) for SHM export succeeded
gpsd:PROG: shmat() for SHM export succeeded, segment 8
gpsd:INFO: stashing device /dev/ttyS0 at slot 0
gpsd:PROG: no /etc/gpsd/device-hook present, skipped running ACTIVATE hook. No such file or directory
gpsd:INFO: SER: opening read-only GPS data source type 2 at '/dev/ttyS0'
gpsd:IO: SER: fusercount: path /dev/ttyS0 fullpath /dev/ttyS0 cnt 1
gpsd:IO: SER: fd 6 set speed 115200(4098)
gpsd:INFO: SER: fd 6 current speed 115200, 8N1
gpsd:IO: SER: open(/dev/ttyS0) -> 6 in gpsd_serial_open()
gpsd:PROG: Probing "Garmin USB binary" driver...
gpsd:PROG: Probe not found "Garmin USB binary" driver...
gpsd:PROG: Probing "GeoStar" driver...
gpsd:PROG: Sent GeoStar packet id 0xc1
gpsd:PROG: Probe not found "GeoStar" driver...
gpsd:PROG: Probing "Trimble TSIP" driver...
gpsd:IO: SER: fd 6 set speed 9600(13)
gpsd:INFO: SER: fd 6 current speed 9600, 8O1
gpsd:IO: SER: fd 6 set speed 115200(4098)
gpsd:INFO: SER: fd 6 current speed 115200, 8N1
gpsd:PROG: Probe not found "Trimble TSIP" driver...
gpsd:PROG: Probing "iSync" driver...
gpsd:IO: SER: fd 6 set speed 9600(13)
gpsd:INFO: SER: fd 6 current speed 9600, 8N1
gpsd:IO: SER: fd 6 set speed 115200(4098)
gpsd:INFO: SER: fd 6 current speed 115200, 8N1
gpsd:PROG: Probe not found "iSync" driver...
gpsd:PROG: no probe matched...
gpsd:INFO: gpsd_activate(2): activated GPS (fd 6)
gpsd:PROG: NTP:PPS: using SHM(0)
gpsd:PROG: NTP:PPS: using SHM(1)
gpsd:PROG: PPS:/dev/ttyS0 connect chrony socket failed: /run/chrony.ttyS0.sock, error: -2, errno: 111/Connection refused
gpsd:PROG: KPPS:/dev/ttyS0 checking /sys/devices/virtual/pps/pps1/path, /dev/ttyS0
gpsd:INFO: KPPS:/dev/ttyS0 RFC2783 path:/dev/pps1, fd is 7
gpsd:INFO: KPPS:/dev/ttyS0 pps_caps 0x1133
gpsd:INFO: KPPS:/dev/ttyS0 have PPS_CANWAIT
gpsd:INFO: KPPS:/dev/ttyS0 kernel PPS will be used
gpsd:PROG: PPS:/dev/ttyS0 thread launched
gpsd:INFO: PPS: activated /dev/ttyS0 ntpshm_link_activate(): Clock
gpsd:INFO: stashing device /dev/pps0 at slot 1
gpsd:PROG: no /etc/gpsd/device-hook present, skipped running ACTIVATE hook. No such file or directory
gpsd:ERROR: SER: stat(/dev/pps0) failed: No such file or directory(2)
gpsd:ERROR: initial GPS device /dev/pps0 open failed
gpsd:INFO: KPPS:/dev/ttyS0 kernel PPS timeout 4:unknown error
gpsd:INFO: KPPS:/dev/ttyS0 kernel PPS timeout 4:unknown error
gpsd:INFO: KPPS:/dev/ttyS0 kernel PPS timeout 4:unknown error
gpsd:INFO: running with effective group ID 18
gpsd:INFO: running with effective user ID 65534
gpsd:INFO: startup at 2022-03-10T12:35:52.000Z (1646915752)
gpsd:PROG: KPPS:/dev/ttyS0 assert 1646915753.000208807, sequence: 1, clear 0.000000000, sequence: 0 - using: assert
gpsd:PROG: KPPS:/dev/ttyS0 Assert cycle: 1646915753000208, duration: 0 @ 1646915753.000208807
gpsd:RAW: PPS:/dev/ttyS0 Assert pps-detect changed to 1
gpsd:PROG: PPS:/dev/ttyS0 Assert cycle: 1646915753000208, duration: 0 @ 1646915753.000208807
gpsd:PROG: PPS:/dev/ttyS0 Assert ignored missing last_fixtime
gpsd:PROG: KPPS:/dev/ttyS0 assert 1646915753.000208807, sequence: 1, clear 1646915753.100149920, sequence: 1 - using: clear
gpsd:PROG: KPPS:/dev/ttyS0 Clear cycle: 99941, duration: 99941 @ 1646915753.100149920
gpsd:RAW: PPS:/dev/ttyS0 Clear pps-detect changed to 0
gpsd:PROG: PPS:/dev/ttyS0 Clear cycle: 99941, duration: 99941 @ 1646915753.100149920
gpsd:PROG: PPS:/dev/ttyS0 Clear ignored missing last_fixtime
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.130428717 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type -1
gpsd:INFO: reconnection attempt on device 1
gpsd:PROG: no /etc/gpsd/device-hook present, skipped running ACTIVATE hook. No such file or directory
gpsd:ERROR: SER: stat(/dev/pps0) failed: No such file or directory(2)
gpsd:ERROR: /dev/pps0: device activation failed, freeing device.
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.131202895 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type -1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.132038783 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type -1
gpsd:IO: SER: gpsd_next_hunt_setting(6) retries 0 diff 0
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.132776939 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type -1
gpsd:IO: SER: gpsd_next_hunt_setting(6) retries 1 diff 0
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.133566515 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type -1
gpsd:IO: SER: gpsd_next_hunt_setting(6) retries 2 diff 0
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.134296808 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type -1
gpsd:IO: SER: gpsd_next_hunt_setting(6) retries 3 diff 0
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.135119824 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type -1
gpsd:IO: SER: gpsd_next_hunt_setting(6) retries 4 diff 0
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915753.135905236 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:PROG: switching to match packet type 1: $GPRMC,123553,A,46xx.xxxxx,N,7xx.xxxxx,E,000.0,000.0,100322,000.0,E*70\x0d\x0a
gpsd:PROG: switch_driver(NMEA0183) called...
gpsd:PROG: selecting NMEA0183 driver...
gpsd:INFO: /dev/ttyS0 identified as type NMEA0183, 1 sec @ 115200bps
gpsd:RAW: raw packet of type 1, 72:$GPRMC,123553,A,46xx.xxxxx,N,7xx.xxxxx,E,000.0,000.0,100322,000.0,E*70\x0d\x0a
gpsd:IO: <= GPS: $GPRMC,123553,A,46xx.xxxxx,N,7xx.xxxxx,E,000.0,000.0,100322,000.0,E*70
gpsd:DATA: NMEA0183: merge_ddmmyy(100322) sets year 2022
gpsd:RAW: NMEA0183: merge_ddmmyy(100322) 2 10 122
gpsd:DATA: NMEA0183: GPRMC: registers fractional time 123553.000000000
gpsd:DATA: NMEA0183: RMC: ddmmyy=100322 hhmmss=123553 lat=46.95 lon=7.44 speed=0.00 track=0.00 mode=2 var=nan status=0
gpsd:DATA: NMEA0183: GPRMC newtime is 1646915753.000000000 = 2022-03-10T12:35:53.000Z
gpsd:DATA: NMEA0183: GPRMC time 123553.000000000 last 0.000000000 latch 1 cont 0
gpsd:PROG: NMEA0183: GPRMC starts a reporting cycle. lasttag 0
gpsd:SPIN: parse_packet() = {ONLINE|TIME|LATLON|SPEED|TRACK|STATUS|MODE|PACKET|DRIVER|CLEAR|NTPTIME}
gpsd:DATA: packet type 1 from /dev/ttyS0 with {ONLINE|TIME|LATLON|SPEED|TRACK|STATUS|MODE|PACKET|DRIVER|CLEAR|NTPTIME}
gpsd:DATA: all_reports(): changed {ONLINE|TIME|LATLON|SPEED|TRACK|STATUS|MODE|PACKET|DRIVER|CLEAR|NTPTIME}
gpsd:SPIN: packet_get() fd 6 -> 0 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:PROG: KPPS:/dev/ttyS0 assert 1646915754.000142962, sequence: 2, clear 1646915753.100149920, sequence: 1 - using: assert
gpsd:PROG: KPPS:/dev/ttyS0 Assert cycle: 999934, duration: 899993 @ 1646915754.000142962
gpsd:RAW: PPS:/dev/ttyS0 Assert pps-detect changed to 1
gpsd:PROG: PPS:/dev/ttyS0 Assert cycle: 999934, duration: 899993 @ 1646915754.000142962
gpsd:PROG: PPS:/dev/ttyS0 Assert ignored missing last_fixtime
gpsd:PROG: KPPS:/dev/ttyS0 assert 1646915754.000142962, sequence: 2, clear 1646915754.100056948, sequence: 2 - using: clear
gpsd:PROG: KPPS:/dev/ttyS0 Clear cycle: 999907, duration: 99913 @ 1646915754.100056948
gpsd:RAW: PPS:/dev/ttyS0 Clear pps-detect changed to 0
gpsd:PROG: PPS:/dev/ttyS0 Clear cycle: 999907, duration: 99913 @ 1646915754.100056948
gpsd:PROG: PPS:/dev/ttyS0 Clear ignored missing last_fixtime
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.139262196 (Success)
gpsd:SPIN: packet_get() fd 6 -> 12 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.140017104 (Success)
gpsd:PROG: transmission pause. gap 1.004081 quiet_time 0.250000
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.140906731 (Success)
gpsd:SPIN: packet_get() fd 6 -> 10 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.141784777 (Success)
gpsd:SPIN: packet_get() fd 6 -> 10 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.142634744 (Success)
gpsd:SPIN: packet_get() fd 6 -> 10 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.143412923 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.144186955 (Success)
gpsd:SPIN: packet_get() fd 6 -> 9 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:SPIN: pselect() {3 4 6} -> { 6 } at 1646915754.144838131 (Success)
gpsd:SPIN: packet_get() fd 6 -> 3 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
gpsd:RAW: packet sniff on /dev/ttyS0 finds type 1
gpsd:RAW: raw packet of type 1, 72:$GPRMC,123554,A,46xx.xxxxx,N,7xx.xxxxx,E,000.0,000.0,100322,000.0,E*7B\x0d\x0a
gpsd:IO: <= GPS: $GPRMC,123554,A,46xx.xxxxx,N,7xx.xxxxx,E,000.0,000.0,100322,000.0,E*7B
gpsd:DATA: NMEA0183: merge_ddmmyy(100322) sets year 2022
gpsd:RAW: NMEA0183: merge_ddmmyy(100322) 2 10 122
gpsd:DATA: NMEA0183: GPRMC: registers fractional time 123554.000000000
gpsd:DATA: NMEA0183: RMC: ddmmyy=100322 hhmmss=123554 lat=46.95 lon=7.44 speed=0.00 track=0.00 mode=2 var=nan status=0
gpsd:DATA: NMEA0183: GPRMC newtime is 1646915754.000000000 = 2022-03-10T12:35:54.000Z
gpsd:DATA: NMEA0183: GPRMC time 123554.000000000 last 123553.000000000 latch 1 cont 0
gpsd:PROG: NMEA0183: GPRMC starts a reporting cycle. lasttag 61
gpsd:PROG: NMEA0183: tagged RMC as a cycle ender. 61
gpsd:PROG: NMEA0183: GPRMC ends a reporting cycle.
gpsd:SPIN: parse_packet() = {ONLINE|TIME|LATLON|SPEED|TRACK|STATUS|MODE|PACKET|CLEAR|REPORT|NTPTIME}
gpsd:DATA: packet type 1 from /dev/ttyS0 with {ONLINE|TIME|LATLON|SPEED|TRACK|STATUS|MODE|PACKET|CLEAR|REPORT|NTPTIME}
gpsd:DATA: all_reports(): changed {ONLINE|TIME|LATLON|SPEED|TRACK|STATUS|MODE|PACKET|CLEAR|REPORT|NTPTIME}
gpsd:SPIN: packet_get() fd 6 -> 0 (0)
gpsd:RAW: /dev/ttyS0 is known to be NMEA0183
...
Apparently, it successfully sets up the shared memory. It can also read the NMEA data, extracts date and time, and the PPS pulses are also detected! while this runs, it creates a device /dev/pps0
and with sudo ppstest /dev/pps0
I can confirm that the PPS pulses are still there. Now, in my chrony.conf
, I have these two lines
refclock SHM 0 offset 0.5 delay 0.2 refid NMEA noselect
refclock SHM 1 offset 0.0 delay 0.1 refid PPS
so chrony should be able to read the time. However, even after a couple minutes, there is nothing:
$ chronyc sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
#? NMEA 0 4 0 - +0ns[ +0ns] +/- 0ns
#? PPS 0 4 0 - +0ns[ +0ns] +/- 0ns
However I can confirm the shared memory segments are there:
$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x4e545030 0 root 600 96 2
0x4e545031 1 root 600 96 2
0x4e545032 2 root 666 96 1
0x4e545033 3 root 666 96 1
0x4e545034 4 root 666 96 1
...
so what is going on here? I notice that gpsd
changes its own user to nobody
$ ps aux | grep gpsd
root 12667 0.0 0.0 235424 8736 pts/0 S+ 13:41 0:00 sudo gpsd -D 8 -N -b -n /dev/ttyS0 /dev/pps0
nobody 12668 0.3 0.0 17172 4816 pts/0 S<l+ 13:41 0:01 gpsd -D 8 -N -b -n /dev/ttyS0 /dev/pps0
while chronyd
runs as user chrony
:
$ ps aux | grep chrony
chrony 12917 0.0 0.0 10600 2972 ? S 13:45 0:00 /usr/sbin/chronyd -F 2
I believe this could be the culprit, since the shared memories belong to root
. But I am not sure. Why can't get chrony the time from gpsd? I also tried the other variants, i.e. the sockets, but with the same result.
As /dev/pps0 gives plausible output, these refclock lines in chrony.conf might be what you need:
My system (Raspberry pi3B+ with Adafruit Ultimate GPS HAT version 2) has these non-comment lines in chrony.conf in addition to the default contents:
As I understand it, the PPS system knows very accurately where the second boundaries are but it doesn't know which second the boundaries belong to. The NMEA entry is accurate enough to know which second is being timed and passes this to PPS. The 'magic' is realising that the 'noselect' entry can be assist the line that references it without itself being used directly.
Chronyc sources shows