Electronics > Open Source Hardware

"Laureline" embedded GPS NTP server

(1/10) > >>

gxti:
A simple but effective project for your perusal. Laureline is an embedded SNTP server that receives time from a GPS receiver in the form of a pulse-per-second (PPS) input as well as the usual serial data in whatever format it comes (NMEA, Oncore, TSIP, etc.). I call it SNTP and not NTP because time is served from GPS alone and no other NTP servers are consulted. However, laureline is perfectly suitable as a Stratum 1 reference for NTP and SNTP clients alike.

The processor is a STM32F107 which includes a built-in 100Mbit Ethernet MAC, which I have paired with an inexpensive transceiver to get a good Ethernet solution with predictable and minimal latency unlike the USB-based MACs found in e.g. Raspberry Pi. Also onboard is a small VCXO which is disciplined by the microcontroller to precisely 10MHz using the GPS pulses, in effect making laureline a low-grade GPSDO. The board is powered by a buck converter that accepts 8-40VDC, allowing for direct power from a 12V or 24V lead acid battery. Other than that, the rest of the magic is in software: observing the frequency of the local oscillator by way of incoming GPS pulses, calculating NTP time from the 70MHz timer when queried  and handling network administrivia.

Because almost all STM32 IOs are 5V-tolerant, the serial interface works with both 3.3V and 5V GPS receivers. I've designed but not yet fabricated some tiny adapters to connect two types of receivers to the 6-pin header on laureline, one being Oncore GT+/UT+ and probably other Motorola receivers as well, and the other being Trimble's Resolution T and Resolution SMT carrier boards. Both types are presently available used on Ebay for about $30, half that in the case of UT+. As you can see in the pictures, jumper wires also work perfectly well in lieu of an adapter. There's enough current at either 3.3V or 5V to power a typical receiver with active antenna, as well.

Here is laureline paired with an Oncore GT+, the board at lower left is an isolated USB UART I'm using for debugging:


A (blurry) closeup of the board:


Current status: rev 1 of the hardware works flawlessly, except for the power supply which needed extra capacitance. rev 2 will have a separate PSU module of my own design, so that when I screw it up again at least I can test it separately and/or swap it out.

The software is still in early development. All of the disciplining/GPSDO stuff is not written yet, although I have written such things before for an earlier project that actually was a GPSDO. Presently I hacked together a simple mechanism that just resets the counter each time a PPS arrives and does no disciplining but it's still performing quite well. It also needs to handle leap seconds, both internally and also for presenting the leap flag to NTP clients. I haven't added the code to the repository but I'll do so in the next day or two.

Repository (design docs, code, etc.): http://hg.partiallystapled.com/circuits/laureline/
In zip format: http://hg.partiallystapled.com/circuits/laureline/archive/tip.zip
Also download the library and unzip it to lib/: http://hg.partiallystapled.com/circuits/alib/archive/tip.zip
Schematic PDF: http://hg.partiallystapled.com/circuits/laureline/raw-file/tip/out/production.PDF

gxti:
Forgot to post this yesterday -- actual NTP results:

--- Code: ---[root@rei ~]# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
-64.73.32.134    192.41.214.45    4 u  501 1024  377   65.940    7.184   0.689
-24.124.0.251    128.206.12.130   3 u  457 1024  377  106.168  -18.808  46.581
+64.73.32.135    18.26.4.105      2 u  443 1024  377   67.824    5.759   0.714
-169.229.70.95   128.32.206.55    2 u  629 1024  377  103.428    7.904   1.133
*172.24.0.6      .GPS.            1 u   19   64  377    2.483    0.777   0.346
-172.24.0.66     172.24.0.1       3 u  491 1024  377    0.169    1.038   0.369
x172.24.0.68     172.24.0.66      4 u  530 1024  377    0.202  109.953 170.476
+172.24.0.1      172.24.0.6       2 u  607 1024  377    0.129    1.566   0.049

--- End code ---

--- Code: ---[root@hanmyo ~]# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*172.24.0.6      .GPS.            1 u    5   64  377    2.531   -0.583   0.291
 172.24.0.64     172.24.0.6       2 u  730 1024  377    0.135   -1.500   0.077
 172.24.0.66     172.24.0.1       3 u  889 1024  377    0.387   -0.636   0.329
x172.24.0.68     108.133.178.111  2 u  932 1024  377    0.314  157.627 123.609
-64.73.32.134    192.41.214.45    4 u  993 1024  377   66.944    4.189   1.518
-24.124.0.251    64.6.144.6       3 u  846 1024  357  106.791  -21.016  37.217
+64.73.32.135    18.26.4.105      2 u  831 1024  377   68.850    4.766   0.517
+169.229.70.95   128.32.206.55    2 u   27 1024  377  103.022    5.961   0.445

--- End code ---

172.24.0.6 is laureline, 172.24.0.68 is a windows box that just can't seem to keep up :[

Note the not-fantastic 2.4ms delay. I will see what I can do about that, probably it is due to context switching. I am using ChibiOS and its example LWIP bindings, which ends up having one thread handling packets and another doing the NTP server stuff and on top of that some third thread ends up processing the receive interrupt to begin with. Which means there's a lot of handing off to other threads, which incurs additional delay. So reducing the entire network stack to a single thread will probably improve latency considerably.

gxti:
Turns out those Oncore receivers are not suitable for timing purposes. The auction listed them as "GT+" but they seem to be some older revision and don't say "GT" at all in the receiver ID. Also "GT+" isn't even the timing-oriented model, "UT+" is. That part is my fault. In any case, the dealbreaker is that the pulse-per-second output jumps forward by exactly 1ms every 16-20 seconds. With enough smoothing it could be made to work since I presume that on average the pulses are still accurate, but for now I've switched to my known-good Trimble Resolution SMT receiver. I bought 3 of these stupid Oncore receivers too, for $10 each... not the most expensive mistake I've made, and at least they will work well for position applications. I always wanted to make a data logger for my car.

I also fixed the Ethernet latency issue by using a single thread to process network data. I talked to someone else who is using the same stack and was able to get good latency figures using the regular, multi-threaded arrangement but I was unable to determine why I was not. Either way, single-threaded works and doesn't make the code any more complex so long as I'm not trying to do TCP.

New NTP figures:

--- Code: ---[root@rei ~]# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
-138.236.128.36  216.218.254.202  2 u   21 1024  377   68.819    3.228  0.641
+108.59.14.130   209.51.161.238   2 u  298 1024  377   34.920    1.167  0.288
+108.61.73.244   96.47.67.105     2 u  300 1024  377   39.524    1.135  1.604
-64.6.144.6      128.252.19.1     2 u  772 1024  377   84.329    6.609  0.252
*172.24.0.6      .GPS.            1 u    2   16  377    0.320   -0.073  0.016
-172.24.0.66     135.34.116.162   3 u  237 1024  377    0.197    0.130  0.581
x172.24.0.68     172.24.0.6       2 u  291 1024  377    0.237  113.341 77.665
-172.24.0.1      172.24.0.6       2 u  287  512  377    0.123    2.382  0.876

--- End code ---

--- Code: ---[root@maruko ~]# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
-67.18.187.111   129.7.1.66       2 u  850 1024  177   66.888    2.844   1.485
+174.129.25.69   158.227.98.15    2 u  639 1024  377   35.557    2.227   0.196
+2001:470:1:15b: 132.239.1.6      2 u  397 1024  377  107.438    1.415   0.126
 172.24.0.1      172.24.0.6       2 u  673 1024  377    0.175    2.176   0.446
*172.24.0.6      .GPS.            1 u   48   16  377    0.324    0.382   0.083
 172.24.0.64     172.24.0.6       2 u  795 1024  377    0.309   -0.067   0.073
 172.24.0.68     172.24.0.6       2 u  821 1024  377    0.837  193.564  57.882

--- End code ---

joe912:
Cool project.
What's the end use for it? Have you investigated the IEEE 1588 timestamping features of the uC?

Also taking a look at the schematic I would recommend 0.1uF caps from TCT and RCT of the magjack to ground.

gxti:
Just for fun, mainly. I plan on building a few into enclosures and maybe selling them, but sourcing the GPS module is the limiting factor for making them in any volume. Probably I will try to find a module that's good enough for NTP but not "timing grade" since it seems that new timing receiver modules cost $70 and up. Buying more Resolution Ts from China on ebay is also an option but not ideal as I've seen similar stock dry up and disappear. I need to do some experiments with the Oncores that have a phase skip as that will likely be similar to what I see with new non-timing receivers. I don't foresee it being problematic for NTP due to less demanding precision needs and use of the VCXO as a "flywheel" to smooth out jitter. The PLL parameters will need to be slower and I will need to soak test everything to make sure they track well over time.

I may investigate IEEE 1588 in the future. A 1588 PHY is only another $5, but I would probably want to upgrade to a full ovenized oscillator once getting into that territory. Definitely worth investigating though.

I'll look at best practice for the Ethernet grounding. I don't recall if the one I'm using has builtin EMI caps but I didn't tie the shield to ground anywa.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version