Montecri/GNSSTimeServer

Stratum 4? (and a couple of issues/bugs)

Closed this issue · 17 comments

I'm playing around with this a bit to see if it will work as a replacement to the RPi I have been running as a time server for many years. One thing that I noticed when I added this as a time server to one of my systems is that it only shows up as stratum 4. From what I know of NTP, shouldn't this be stratum 1 since it is synced directly to GPS?

The ESP device is also showing an odd refid from ntpq -p. From what I know of the spec, that should either be the IP address if this is a stratum 4 server, or either GPS or PPS if this is stratum 1. The code is setting GPS, but since it is sending stratum 4, that gets interpreted as an IP address. So it should probably only set GPS if it is stratum 1, and the IP if it is anything else.

There is bug in how you are setting the root delay and dispersion, your packetBuffer indices are off by 2. The indices are back in sync by the time you set the refid value, so essentially you've shifted those values right by 2 bytes. https://github.com/Montecri/GPSTimeServer/blob/main/src/main.cpp#L642

I'm noticing rather high delay and offset values from this, I'm assuming because it is running over wifi. I'm debating picking up an ethernet shield and seeing if that makes things any better.

Here's an example of ntpq -pn from my server, the GPSTimeServer ESP is running as xxx.xxx.xxx.159 (this is from before I changed it to stratum 1):

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 xxx.xxx.xxx.7      91.82.186.52  2 u    4   16  377    0.642   -0.024   0.055
 xxx.xxx.xxx.1      172.16.42.7   3 u    3   16  377    0.150   -0.184   0.050
 xxx.xxx.xxx.159    71.80.83.0    4 u    2   16  377  140.446  -395.88  29.181
 xxxx:xxxx:xxxx:7  .INIT.        16 u    -   16    0    0.000   +0.000   0.000
*xxxx:xxxx:xxxx:40 .PPS.          1 u   21   64   37   12.056   +0.343   0.189

If you're interested, I have a fork in my repo at https://github.com/sjthespian/GPSTimeServer. I've made a few changes like joining an existing wifi network and falling back to AP mode (which I really want to add to the web page at some point), adding more info on the web page, adding syslog support, and cleaning up some of the warnings I was getting (which probably have a lot more to do with the version of the pio tools I'm running than the code).

I would also like to add a text-graph of current satellite info on the web page, but I haven't had time to play with that yet. I'm not sure how badly I want to try and parse that out of the raw GPGSV data.

Wow! Great analysis, debugging, and additions!

You're right, it should be Stratum 1. Don't know how I missed that.

Will definitely absorb your fixes and improvements.

Think a web interface with more information and functionalities would be a great addition, especially if the hardcoded defaults could be changed through it. Not a great web designer myself, would need help with that.

Your plans will definitely improve this little project.

Thank you, man! And feel free to reach me anytime.

A couple of new features in my fork:

  • It sets the nap data to stratum 16 if not synced, stratum 1 when synced (not tested yet as my server doesn't see it when it isn't synced)
  • added support for setting the wifi credentials on the web endpoint and it saves those in a local "filesystem" so they persist across reboots

Now that I have a filesystem, I'm probably going to move the web "homepage" there. I just need to figure out how best to do the templating so I can inject variables into it.

Very nice!

Will run some tests this weekend.

Thanks.

  • Cristiano

Just tested your latest version and you truly made great changes!

Just some points to keep in mind:

  • When DEBUG/Serial is activated, either the WIFI_STA (connection to my access point) or the Webserver will not work consistently, sometimes not work at all, at least on my board. As soon as I disable DEBUG (thus, Serial is never initialized and Serial.print never issued) things start working perfectly. For this reason, I changed the line "Serial.print(".");" on enableWifi() to DEBUG_PRINT(".")).

  • Perhaps you can include the syslog server name/IP on the variables saved on LittleFS (or I can do it myself), since not everybody will have a syslog server on their network, and the address will probably be different from whatever is in the code.

  • Saw you changed U8G2_SH1106_128X64_NONAME_F_HW_I2C with U8G2_SSD1306_128X64_NONAME_F_HW_I2C, believe that's the controller version you got. Can you leave both lines, with the one that doesn't work for you commented? I intend to replace the current version with yours (of course, giving you credits for these improvements) and also take care of people that got the original build parts.

  • The dual information screen with short/long press handling is a great addition! However, it is not working reliably :( (everybody that hates button debouncing raises your hand!!!). If you have improved that already, please, let me know so I don't invest time in that.

Thank you for these contributions, now the project is much more useful than before.

Regards,

  • Cristiano

@mmarkin please keep an eye on this thread, there are some bug fixes and improvements that you probably want to implement on your Dual Display tree.

I had a quick look at sjthespian's code. I haven't had a chance to check it out in detail yet but it looks like there are some good improvements. I was wondering about that Stratum 1 / Stratum 4 stuff myself. My version fixed the PlatformIO warnings. The web server is a nice touch. Yes, since LittleFs is being used the HTML code should be in a file there. It makes it a lot easier to write and maintain the code.

It's good to be able to see the latitude and longitude, too. This is a timeserver, not a navigation aid, but as long as it uses GPS it might as well show where you are!

I have noticed some oddities that I'm trying to track down...

  1. The display doesn't always seem to match the GPS status. At the moment for example the display is showing 3 satellites, but looking at the GPS raw GPGSV data I currently have none (it's on my desk inside the house, so it's hit or miss how much sky I get out of the window). I have also seen cases where the GPS debug logs are showing as many as 3 sats but they display still shows zero.
  2. Similarly I have seen a couple of cases where the GPS hardware appears to have a sync and the PPS led there is flashing, but the red led I have wired in isn't.

These are both edge cases that most folks will probably never see, but I think it shows an issue with either how things are being updated or how the TinyGPS library is returning data that might have some other impacts.

EDIT: it's as if there is either a processing loop having or something is dropping interrupts. Right now for example, the red LED on the GPS board is flashing once per second, but the wired LED is sold on.

I changed the code on my server to implement Daniel's packet buffer corrections. I updated the code on the Dual Display branch to show the changes as well. Everything is running properly. I haven't added the web page yet. It's a nice addition but I don't have a need for it at this time.

I have never seen the front panel red LED and the LED on the GPS board flashing differently on my server. I'll keep an eye on them, though.

Daniel, did you try disabling the web page that your code serves to see if it runs better? ESP8266s are powerful little devices but they can be overloaded if you try to get them to do too much. Their WiFi functions take up a lot of processing power and sometimes there isn't enough left for other functions to run properly. That might be what's causing the glitches with the GPS data.

An NTP clock I built that used an ESP8266 to drive 120 WS2812 LEDs ran fine until I tried to get it to also serve a web page to do some setup. After that, it had problems generating the precise timing needed for the LED data. I had to upgrade the clock to use an ESP32.

Weird. On my build, both pps leds blink in sync.

Perhaps making the web server run on the second core would help. I face issues when both Serial and Webserver were being used simultaneously, once I disabled Serial, web server went smoothly.

Working on the short/long/debounce button code, not running reliably for me. Doing some experiments to diagnose if it is a wiring problem or something else. If I can improve the code will update on the main tree together with the other improvements done by @sjthespian.

Thanks!

I have used a library called OneButton written by Matthias Hertel in some of my projects. I find that it works quite well. It handles single clicks, double clicks, short presses, long presses, and debouncing. You can specify if the switches are active high or active low and easily change the timing for short presses, long presses, and double clicks. It works best with tactile switches for double clicks, but ordinary momentary pushbuttons work too. The library is available in PlatformIO's library manager. Just search for "onebutton."

@mmarkin Nice find and easy to implemetn -- it works great and it fixed some of the odd button timing issues I had. 8c6080a

@Montecri I think a lot of my performance problems were the debugging I had turned on. Disabling that makes it fly.

I do still want to do something with the web server, but I want to find a way of dealing with embedding variables in the content. If this were python I would just use "f-strings", I haven't found. decent way of doing that with C++ yet.

It's not overly easy to embed C++ variables in a web page if the HTML file is stored with LittleFS. However having the HTML separate from the C++ makes the code easier to write and maintain. You should use the Async webserver library and some JavaScript is involved. This tutorial might help. It mentions SPIFFS but LittleFS uses the same code. Just substitute LittleFS wherever you see SPIFFS.
https://randomnerdtutorials.com/esp8266-web-server-spiffs-nodemcu/

@mmarkin Nice find and easy to implemetn -- it works great and it fixed some of the odd button timing issues I had. 8c6080a

@Montecri I think a lot of my performance problems were the debugging I had turned on. Disabling that makes it fly.

I do still want to do something with the web server, but I want to find a way of dealing with embedding variables in the content. If this were python I would just use "f-strings", I haven't found. decent way of doing that with C++ yet.

And just yesterday I reworked the short/long/debounce code to make it work better, and now it is working very reliably. What's your guys' view on that? it's better to abstract and use the library for that or put the code inside? I, personally, like libraries for very complex stuff, but for all the rest I prefer to have the code in plain sight. Please let me know your thoughts.

Scrap my suggestion to move the webserver code to the second core. ESP8266 is single core, the dual one is the ESP32. I mixed one for the other.

Just updated the main tree with the improvements and fixes and moved syslog address to LittleFS and placed the configuration of it on the webpage.

Please let me know if I can close this issue.

Thanks! Feel free to close this out, I'll go ahead and merge in your code to my fork.

I started playing with moving the HTML file(s) to LittleFS yesterday, we'll see if I can make any progress with that. I still don't have a good idea on how to do variable substitution in it.

Hi!

Just added RDATE support (RFC868) to the main tree. Take a look!