geerlingguy/time-pi

Debug NEO-M9N module on TimeHAT V2

Closed this issue · 26 comments

I received a newer TimeHAT kit to match the one shipping from Tindie, and instead of swapping that into my existing grandmaster Pi, I've upgraded the TimeHAT to the V4 model, but taken the M.2 NEO-M9N-OOB-00 (M2 NEO-M9N V3) board and inserted that into my TimeHAT V2.

However, I can't get any GPS data through it.

I've set the following in /boot/firmware/config.txt:

dtoverlay=pciex1-compat-pi5,mmio-hi
dtparam=uart0=on

I've removed console=serial0,115200 from /boot/firmware/cmdline.txt.

And I've installed the gpsd tooling. But if I ensure gpsd is stopped and the socket is gone, and I use gpsmon /dev/ttyAMA0, I get no output. Same with just listening to that socket, there's no raw data coming across at all.

I see the i226V on the TimeHAT V2, and I can set a manual IP address and force a 1 Gbps network connection, but I can't get packets to flow on there, even though the same HAT/i226 had worked on another Pi.

So far the only difference is the NEO-M9N (instead of the other board with the ZED-F9T), and using the included white non-impedance-matched PCIe FFC that was included with the TimeHAT V4 kit.

I may try swapping the PCIe FFC for one of my Pineboards ones, but it seems like that might only change things regarding the NIC, not the GPS modem. Unless it's a power issue?

Ah... according to the NEO-M9N datasheet, default data rate (baud) is 38400.

I had it set to 115200, which seemed to work on the ZED-F9T. But maybe that was reconfigured because the ZED-F9T datasheet also mentions a 38400 baud default...

Finally, found on the Tindie page that I had to add a symlink:

sudo ln -s /dev/ttyAMA0 /dev/ttyS10

Testing that now.

That works, but the symlink doesn't persist across reboots. So when I try running cgps I get nothing, until I quit out of there, run sudo ln -s /dev/ttyAMA0 /dev/ttyS10 again, then run sudo systemctl restart gpsd.

Then I get data through cgps:

Image

I'll add a script to do those things at boot. Seems like ttyAMA0 is working for me now, as long as I have the appropriate baud settings.

Now, after letting GPS run a while, I have a 3D fix, and I see the following in dmesg:

[  560.242275] pps_ldisc: PPS line discipline registered

However, the antenna is still indoors, and cgps -s is showing distance errors in the 15-30m range, along with time offsets around 0.12-0.15s. Thus, chrony seems to indicate it is an unreliable time:

pi@mini-time:~ $ chronyc sources -v

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
#x GPS                           0   4   377    22   +179ms[ +174ms] +/- 1366us
^+ rn-03.koehn.com               2   7   377   128    +14ms[+3873us] +/-   45ms
^+ nu.binary.net                 2   7   377    69    +11ms[ +267us] +/-   52ms
^* time-h.den.codehof.net        2   6   377     1    -41ms[  -46ms] +/-   47ms
^+ 149.28.200.179.vultruser>     2   8   377     2  +8599us[+3819us] +/-   45ms

Re-checking on the original Time Pi board, I see the ZED-F9T is set to 115200 baud. Looking if there's an easy way to configure the u-blox through the Pi itself so they can both use the same baud setting instead of having to break it out by host.

Would I have to use something like https://www.u-blox.com/en/product/u-center ?

Might be possible to set the baud using ubxtool.

# Get the protocol version ('PROTVER')
ubxtool -p MON-VER
...
UBX-MON-VER:
  swVersion EXT CORE 4.04 (7f89f7)
  hwVersion 00190000
  extension ROM BASE 0x118B2060
  extension FWVER=SPG 4.04
  extension PROTVER=32.01
...

# Set the version in ubxtool options
export UBXOPTS="-P 32.01"

# Set the baud rate to 115200
ubxtool -S 115200

That worked! But... after a reboot, it seems like I can't see it now with cgps -s, nor can I set the baud again:

$ ubxtool -S 115200
{"class":"ERROR","message":"Type of /dev/ttyAMA0 is unknown."}

I have to go back into /etc/default/gpsd and re-set the baud back to 38400, then I can use ubxtool again to change the baud back to 115200 again, then tweak and restart gpsd again.

How to get the baud setting to persist???

Ah, a comment on this blog post on GPS/PPS/time on Pi that helped me find the fix to persist the data:

ubxtool -S 115200
ubxtool -p SAVE

Then change the /etc/default/gpsd file to use the new baud rate, and restart gpsd.

Verify the baud rate on PortID 1 / UART1:

$ ubxtool -p CFG-PRT
UBX-MON-VER:
  swVersion EXT CORE 4.04 (7f89f7)
  hwVersion 00190000
  extension ROM BASE 0x118B2060
  extension FWVER=SPG 4.04
  extension PROTVER=32.01
  extension MOD=NEO-M9N
  extension GPS;GLO;GAL;BDS
  extension SBAS;QZSS

UBX-CFG-PRT:
 PortID 1 (UART1) reserved1 0 txReady 0x0
  mode 0x8c0 baudRate 115200
  inProtoMask 0x3 outProtoMask 0x3
  flags 0x0 reserved2 0
    inProtoMask (UBX NMEA)
    outProtoMask (UBX NMEA)
    flags ()
...

After a reboot... it goes back to 38400.

So I'm not sure how to get the baud rate setting to persist in flash yet. Need to figure out the magical incantation.

You want to hit the UBX-CFG-CFG command, look at PDF page 56 of the Ublox M9 protocol document: https://content.u-blox.com/sites/default/files/u-blox-M9-SPG-4.04_InterfaceDescription_UBX-21022436.pdf?#page=56

Just walking through the gpsd/ubxtool source, it looks like the SAVE function has an optional flag for the target device, try:

ubxtool -s 115200
ubxtool -c SAVE -f devFlash

I've never done this kind of configuration outside of the Ublox u-Center, so take my syntax with a grain of salt.

I'll try that later, thanks!

unn commented

I have to go back into /etc/default/gpsd and re-set the baud back to 38400, then I can use ubxtool again to change the baud back to 115200 again, then tweak and restart gpsd again.

While not ideal, this seems to work well enough to confirm the hat is installed and gps is connecting.

devFlash was not found, but:

$ ubxtool -p MON-VER -P 32.01
UBX-MON-VER:
  swVersion EXT CORE 4.04 (7f89f7)
  hwVersion 00190000
  extension ROM BASE 0x118B2060
  extension FWVER=SPG 4.04
  extension PROTVER=32.01
  extension MOD=NEO-M9N
...

$ ubxtool -S 115200
$ ubxtool -p SAVE -P 32.01
$ ubxtool -p COLDBOOT -P 32.01

After the coldboot, it seem to restart the GPS module and was at the proper baud rate. But the true test is a power off/on cycle... doing that now.

Yay! After a full system reboot, it seemed to persist the 115200 setting:

$ ubxtool -p CFG-PRT
UBX-CFG-PRT:
 PortID 1 (UART1) reserved1 0 txReady 0x0
  mode 0x8c0 baudRate 115200
  inProtoMask 0x23 outProtoMask 0x23
  flags 0x0 reserved2 0
    inProtoMask (UBX NMEA RTCM3)
    outProtoMask (UBX NMEA RTCM3)
    flags ()

Added notes in the README directing people here if needed.

I have the NEO-M9N-00B-00 with a Pi5 I am currently getting data but no PPP... Can you point me on the right direction if any?

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqklqqqqqqqqqqqqqqqqqqSeen 37/Used 25k
x Time: 2025-06-06T17:37:03.000Z (18)xxGNSS PRN Elev Azim SNR Usex
x Latitude: Edited N xxGP 6 6 30.0 84.0 39.0 Y x
x Longitude: Edited W xxGP 9 9 18.0 44.0 46.0 Y x
x Alt (HAE, MSL): 24.306, 58.636 m xxGP 11 11 62.0 56.0 47.0 Y x
x Speed: 0.09 km/h xxGP 13 13 13.0 168.0 33.0 Y x
x Track (true, var): 242.6, -12.9 deg xxGP 19 19 9.0 141.0 28.0 Y x
x Climb: -4.38 m/min xxGP 20 20 82.0 327.0 29.0 Y x
x Status: 3D FIX (636 secs) xxGP 25 25 25.0 269.0 13.0 Y x
x Long Err (XDOP, EPX): 0.38, +/- 5.6 m xxGP 29 29 26.0 314.0 33.0 Y x
x Lat Err (YDOP, EPY): 0.36, +/- 5.4 m xxGL 4 68 27.0 33.0 47.0 Y x
x Alt Err (VDOP, EPV): 0.71, +/- 2.0 m xxGL 5 69 67.0 88.0 49.0 Y x
x 2D Err (HDOP, CEP): 0.55, +/- 2.2 m xxGL 6 70 27.0 188.0 13.0 Y x
x 3D Err (PDOP, SEP): 0.90, +/- 25.8 m xxGL 11 75 14.0 279.0 23.0 Y x
x Time Err (TDOP): 0.45 xxGL 12 76 8.0 334.0 29.0 Y x
x Geo Err (GDOP): 1.01 xxGL 19 83 22.0 102.0 38.0 Y x
x Speed Err (EPS): +/- 0.8 km/h xxGL 20 84 62.0 42.0 37.0 Y x
x Track Err (EPD): n/a xxGA 2 302 7.0 191.0 31.0 Y x
x Time offset: 0.355542301 s xxGA 5 305 40.0 114.0 44.0 Y x
x Grid Square: FN30cv01 xxGA 6 306 9.0 35.0 45.0 Y x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqjmMore...qqqqqqqqqqqqqqqqqqqqqqqqqqj

@crlsgeraldino - Are you using the TimeHAT, or some other GPS HAT? The TimeHAT currently routes the PPS output of GPS straight into the NIC for it's own PHC, so you can't see any PPS data on the Pi itself using tools like gpsmon or cgps. If some other HAT, you have to configure the PPS separately, and sometimes custom route the PPS output of the GPS module to a GPIO pin on the Pi.

I am using the TimeHat

@crlsgeraldino - For TimeHAT, since the PPS is routed into the NIC and not to a GPIO pin on the Pi, there's no way to get PPS data directly into the Pi itself (there's no /dev/pps reference available from the GPS).

I've actually asked @julianstj1 about whether a follow-up version of TimeHAT could route PPS both to a GPIO pin and to the NIC, so you could build applications that reference the PPS directly on the Pi as well.

There is a BOM option on all versions of TimeHAT to route to the SMA from the GPS instead of the I226. It will require soldering some jumper pads, but it is possible if that's desired. A dynamic selection or run-time selection requires another mux that I didn't add to any current version of TimeHAT.

Interesting! That would be nice to have documented somewhere, make it a little more hackable in case someone wants to just use it as a GPS HAT and use the internal Pi 5 NIC.

I can add something to the Github in a bit, but basically need to remove one resistor ( 0 ohm ) and short across two sets of pads, to create 0 ohm connections.

  1. Remove the resistor on the top I'm pointing to.
  2. Short across the 0402 pads next to that resistor, also on the top
  3. Short across the 0402 pads on the bottom of the board where I'm pointing

This will change the output SMA 1PPS to come from the M.2 GPS PPS output rather than the I226

Image
Image
Image

I did the mod as proposed, but do not really understand where the M.2 GPS PPS signal is going to end up. Is it supposed to be handled automagically by gpsd or should I enable a pin on the GPIO for that?

@phoo8ar - if you do that mod, then the SMA connector (the little screw in port) will have the 1PPS output signal from the GPS module (instead of it routed to the i226 NIC chip).

Then you can fashion an adapter out of an SMA cable to two leads, connect one to a GPIO pin on the Pi (which you configure as PPS in for gpsd), and the other to a GND pin... I think. I haven't tested but that seems like how you'd want to do it. Might not even need GND because the GPS module should share the same ground as the Pi already.

Yep this is correct. The mod was to provide the 1PPS from the GPS to the SMA, instead of the default where the I226 SDP goes to the SMA. If you want it to go to the pi somehow, then that requires different cabling as Jeff mentioned.

Thx @geerlingguy and @JulianStj, that worked :) Just for clearness there are 2 SMA connectors on the v2 board. Obviously you need to use the output one.
Now let see what combination of receivers and servers that gets more accurate over time. This is really something that gets you hooked looking at small parts of a second..... Did I hear anything like a rabbithole?

@phoo8ar now you're seeing how deep the rabbit hole goes 🐇 :D

Damn rabbit hole... I love it!!