syncing time via VGA

The title is slightly misleading :-) What it really is, and this is a TL;DR too:
PPS via Arduino into the I2C pins of a VGA connector of a Linux-running-PC which then gets interfaced to NTPd.

how

As described above, there's an Arduino to which I connected a PPS source. This PPS source ("Pulse Per Second") gives a pulse every second. For my experiment I used a simple TCXO (temperature compensated crystal oscillator, a 10MHz TCXO with a PicDiv to make that into a PPS signal) but a GPS with a PPS pin is preferred.

On the Arduino runs a custom script. This script waits for an I2C request to which it should respond in a short time (else the requester times out). The Arduino then waits for 50us (50 microseconds) in a loop until the PPS signal comes in (e.g. the GPS pulls the pin high). If the signal is received, a '!' is sent back, else some other character.

The Linux PC tries to find a baseline for the PPS offset by frequently polling the Arduino. When the first signal was received, then that is used and a sleep of 990ms to minimize the polling. Every time a PPS comes in, the timestamp is send to NTP via a "shared memory segment".

On this website there's a picture of how to connect the Arduino to the VGA connector: .
Connect pin 15 ("SCL", lower left hole) to A5 and pin 12 ("SDA", next the pin on the right) to pin A4 and pin 5 ("GND") to one of the GND pins of the Arduino. You might need to add pull-up resistors between A4 and VCC, and A5 and VCC (4.7k Ohm) - with the videocard I used (Radeon HD 8370D) it also worked without.

Refer to the website I mentioned for how to determine how to find which I2C bus the Arduino is connected to. You can also probe them manually by first connecting the Arduino to the port (don't forget to upload the script first) and then run i2cdetect -y -a on each bus - if it detects something on address 8, then that may be the Arduino:

root@brain:~# i2cdetect -y -a 11
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- 08 -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

In this example, the Arduino sits on bus 11. You can now and retrieve the code from GitHub. Before "make"-ing, you might need to replace the "11" in i2cppsl.cpp to the bus you found:

if ((fd = open("/dev/i2c-11", O_RDWR)) < 0) {

Add the following line to /etc/ntp.conf:

server 127.127.28.0 minpoll 4 maxpoll 4 prefer
and run the 'il' program you build in the previous step (after restarting ntpd).

results

After 8 hours it looked like this on my system:

     remote            refid      st t when poll reach   delay   offset   jitter
================================================================================
*SHM(0)           .SHM.            0 l    4    8  377   0.0000   0.2660   0.2562
+192.168.65.211   .PPS.            1 u   43   64  377   0.7995 3491.294   3.4860
+192.168.64.79    .PPS.            1 u   36   64  377   0.3217 3493.653   1.9202
+192.168.64.1     192.168.64.79    2 u   24   64  377   0.2613 3496.491   3.3935
You're looking for the 'SHM(0)' line. A jitter of 0.2562 is not too bad I would say. The output of ntpq is explained on this website.

Allen deviation plot

picture






Other projects: here and here.


feedback