Skip to content

feat: Enable GPS on RAK 1W kit + fix RAK12500 i2c-ublox polling (affects all RAK ublox boards) 🤖🤖#2640

Open
disq wants to merge 5 commits into
meshcore-dev:devfrom
disq:gps-fixes
Open

feat: Enable GPS on RAK 1W kit + fix RAK12500 i2c-ublox polling (affects all RAK ublox boards) 🤖🤖#2640
disq wants to merge 5 commits into
meshcore-dev:devfrom
disq:gps-fixes

Conversation

@disq
Copy link
Copy Markdown

@disq disq commented May 28, 2026

Re-application of #2401

Tested on RAK3401 + RAK12500 in SLOT A (UART / I2C Communication)
At the time of testing, the RAK19007 board also had RAK13302 (1W) and RAK12002 (RTC)


Changes beyond the original #2401 re-application

RAK3401 GPS enablement (b6e6730f)

  • Restore -D RAK_BOARD on [rak3401] (removed in the feat: Enable GPS on RAK 1W kit #2401 revert due to "RadioLib error -707"). The real cause was rakGPSInit()'s WB_IO4 fallback probe pulsing pin 4 (= SX126X_RESET on RAK3401) LOW for 500 ms, hard-resetting the radio after radio_init(). Fixes below make RAK_BOARD safe to re-enable.
  • rakGPSInit() WB_IO2 probe: WB_IO2 also controls the 3V3_S switched peripheral rail; a failed probe left it as INPUT, dropping the rail (and the RTC/display/GPS with it). Restore WB_IO2 HIGH before falling through to the WB_IO4/WB_IO5 probes.
  • Add -D FORCE_GPS_ALIVE on the RAK3401 base env so stop_gps() can't later pull gpsResetPin (which may resolve to the radio reset / rail pin) LOW after init.

Stale PVT data fix (b6e6730f)

  • RAK12500LocationProvider passed maxWait of 2/8 ms to the ublox getters — below the I²C response window, so polls timed out and the SparkFun library returned stale/garbage PVT (observed: a current latitude paired with a longitude from a previous fix). Bumped to a 250 ms ceiling.
  • Switched getAltitude() (height above WGS84 ellipsoid) to getAltitudeMSL() for more intuitive altitude.

Cold-start false fix (f2ad72e6)

  • Require both gnssFixOK and fixType == 3 before reporting coordinates. Ublox reports gnssFixOK == true with bogus almanac-derived coords during cold start; requiring a 3D fix filters those out.

Main-loop / button responsiveness fix (a13098a5)

  • The 250 ms maxWait above, combined with RAK12500LocationProvider::loop() running on every main-loop iteration, meant the loop spent most of its time blocked on redundant I²C polls (the GNSS solution only updates at the 1 Hz nav rate). This made the AIN1 button sluggish and dropped double-clicks ("prev").
  • Throttle the poll to ~1 Hz inside the provider, and gate all field reads on a single getPVT(250) (returning early on a timeout so no getter fires its own ~1100 ms default poll on a stale cache). The throttle lives in the provider rather than the shared outer loop because the serial/NMEA providers need loop() every iteration to avoid dropping bytes.

Debug-print cleanup (c9dfd1bd)

  • Dropped a duplicate lat/lon debug print and throttled the remaining one (~every 10th update tick).

Merged up to date with dev.


Scope / affected boards

The RAK12500LocationProvider and rakGPSInit() changes compile under RAK_WISBLOCK_GPS (ENV_INCLUDE_GPS && RAK_BOARD && !RAK_WISMESH_TAG), so they affect every RAK i2c-ublox GPS board, not just the RAK 1W kit: rak3401, rak4631 (all envs except the two rs232 bridges), and gat562_30s_mesh_kit. (gat562_mesh_watch13 has GPS disabled; rak_wismesh_tag is excluded.)

Implications for the already-shipping RAK4631 / GAT562 boards:

  • 1 Hz poll throttle — strictly beneficial; the GPS poll previously ran on every main-loop iteration. (The sluggish-button symptom was only visible on RAK3401 because of its AIN1 analog button, but the redundant blocking affected all of these boards.)
  • fixType == 3 gating — coordinates are now withheld until a 3D fix (filters cold-start false fixes).
  • getAltitudeMSL() — altitude is now height above mean sea level instead of the WGS84 ellipsoid.
  • rakGPSInit() WB_IO2 rail-restore — safety fix for a failed first probe dropping the 3V3_S peripheral rail.

-D FORCE_GPS_ALIVE is scoped to the rak3401 env only, so stop_gps() behavior is unchanged on the other boards. Worth a smoke-test on RAK4631 + i2c GPS before merge.

disq and others added 2 commits May 28, 2026 16:18
Three related issues hit by RAK3401 + RAK19007 + RAK12500 (I²C ublox).

1. -D RAK_BOARD restored on [rak3401].
   It was removed in 68363d9 (revert of meshcore-dev#2401) with the symptom
   "RadioLib error -707", because adding RAK_BOARD enables rakGPSInit(),
   whose WB_IO4 fallback probe pulses pin 4 (= SX126X_RESET on RAK3401)
   LOW for 500 ms — hard-resetting the SX1262 after radio_init() has
   already configured it, and (via stop_gps + gpsResetPin = WB_IO4)
   leaving it held in reset afterwards.
   Without RAK_BOARD, RAK_WISBLOCK_GPS isn't auto-defined, the I²C
   ublox path is unreachable, and the firmware falls back to
   Serial1-NMEA detection — which silently fails on a serial-less
   RAK12500. Fixes 2 and 3 below make RAK_BOARD safe to re-enable.

2. RAK12500LocationProvider passed maxWait of 2/8 ms to getLatitude()
   etc. These are below the ublox I²C response window, so the polls
   routinely timed out and the SparkFun library returned stale/garbage
   PVT bytes. Observed: getGnssFixOk() returning true with a current
   latitude but a longitude from some previous fix. Bumped to 250 ms.
   Also switched getAltitude() (height above WGS84 ellipsoid) to
   getAltitudeMSL() for more intuitive altitude readings.

3. rakGPSInit() probes WB_IO2 first. On failure, gpsIsAwake() leaves
   the probed pin as INPUT. WB_IO2 also controls the 3V3_S switched
   peripheral rail on these RAK base boards, so a failed first probe
   left I²C peripherals (RTC, display, the GPS itself) unpowered
   before the WB_IO4/WB_IO5 fallbacks ran. The else-branch now
   restores WB_IO2 HIGH before falling through.

   On RAK3401, those fallback probes (WB_IO4 = pin 4 = SX126X_RESET,
   WB_IO5 = pin 9 = SX126X_BUSY) are also dangerous, see point 1.
   Adding -D FORCE_GPS_ALIVE in the RAK3401 base env skips stop_gps()
   after detection, so even if gpsResetPin ends up = WB_IO2 (kills
   the rail) or pin 4 (= radio reset), it can't be pulled LOW again
   after init.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The loop() function printed lat/lon, then computed altitude, then
printed lat/lon/alt — making the first print pure noise. Every
gps_update_interval_sec (default 1 s) the log got two near-identical
lines, drowning out anything else when MESH_DEBUG=1 is on.

Drop the first MESH_DEBUG_PRINTLN entirely (in both the RAK_WISBLOCK_GPS
and the non-RAK branches). Throttle the surviving lat/lon/alt line to
roughly every 10th update via a static skip counter, so a debug build
gets a position sample every ~10 s instead of every second while still
covering the typical GPS visibility window.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread src/helpers/sensors/EnvironmentSensorManager.cpp Outdated
Comment thread src/helpers/sensors/EnvironmentSensorManager.cpp Outdated
Comment thread src/helpers/sensors/EnvironmentSensorManager.cpp
Comment thread src/helpers/sensors/EnvironmentSensorManager.cpp
Comment thread src/helpers/sensors/EnvironmentSensorManager.cpp
Comment thread src/helpers/sensors/EnvironmentSensorManager.cpp
@disq disq changed the title feat: Enable GPS on RAK 1W kit feat: Enable GPS on RAK 1W kit 🤖🤖 May 28, 2026
Ublox modules sometimes report gnssFixOK=true with bogus coordinates
during cold start, before any actual fix has been acquired — e.g.
factory-almanac defaults that look like real positions. Observed: an
unfixed module reporting plausible-looking but wrong-hemisphere
coordinates persistently, with _location->isValid() returning true.

Tighten RAK12500LocationProvider::loop() to require BOTH gnssFixOK
(DOP/accuracy masks satisfied) AND fixType == 3 (3D fix). fixType
values: 0=no fix, 1=dead reckoning only, 2=2D, 3=3D, 4=GNSS+DR,
5=time only. Only the 3D fix is a position we want to publish.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@disq disq marked this pull request as draft June 1, 2026 09:56
disq and others added 2 commits June 1, 2026 10:57
# Conflicts:
#	src/helpers/sensors/EnvironmentSensorManager.cpp
…n loop

The stale-PVT fix bumped every ublox getXxx() maxWait to 250 ms. Each getter
does a synchronous I²C poll, and RAK12500LocationProvider::loop() runs on every
main-loop iteration — so the loop spent most of its time blocked on redundant
GPS polls (the GNSS solution only updates at the 1 Hz nav rate anyway). That
stall made the AIN1 button feel sluggish and drop double-clicks ("prev"), which
is what the separate interrupt-driven AIN1 button work was chasing — turns out
unnecessary once this is fixed.

Throttle the poll to once per nav epoch (~1 Hz) inside the provider, and gate
all field reads on a single getPVT(250): if that poll times out we return early
and keep the last values, so no getter fires its own ~1100 ms default-maxWait
poll on a stale cache. The throttle lives in the provider (not the shared outer
loop) because the serial/NMEA providers must keep getting loop() every iteration
to avoid dropping bytes. Same proven polling logic that was getting fixes, just
not hammered every iteration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@disq disq marked this pull request as ready for review June 1, 2026 10:21
@disq disq changed the title feat: Enable GPS on RAK 1W kit 🤖🤖 feat: Enable GPS on RAK 1W kit + fix RAK12500 i2c-ublox polling (affects all RAK ublox boards) Jun 1, 2026
@disq disq changed the title feat: Enable GPS on RAK 1W kit + fix RAK12500 i2c-ublox polling (affects all RAK ublox boards) feat: Enable GPS on RAK 1W kit + fix RAK12500 i2c-ublox polling (affects all RAK ublox boards) 🤖🤖 Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants