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
Open
feat: Enable GPS on RAK 1W kit + fix RAK12500 i2c-ublox polling (affects all RAK ublox boards) 🤖🤖#2640disq wants to merge 5 commits into
disq wants to merge 5 commits into
Conversation
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>
jakymiwm
reviewed
May 28, 2026
jakymiwm
reviewed
May 28, 2026
jakymiwm
reviewed
May 28, 2026
jakymiwm
reviewed
May 28, 2026
jakymiwm
reviewed
May 28, 2026
jakymiwm
reviewed
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>
# 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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)-D RAK_BOARDon[rak3401](removed in the feat: Enable GPS on RAK 1W kit #2401 revert due to "RadioLib error -707"). The real cause wasrakGPSInit()'s WB_IO4 fallback probe pulsing pin 4 (= SX126X_RESET on RAK3401) LOW for 500 ms, hard-resetting the radio afterradio_init(). Fixes below makeRAK_BOARDsafe 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.-D FORCE_GPS_ALIVEon the RAK3401 base env sostop_gps()can't later pullgpsResetPin(which may resolve to the radio reset / rail pin) LOW after init.Stale PVT data fix (
b6e6730f)RAK12500LocationProviderpassed 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.getAltitude()(height above WGS84 ellipsoid) togetAltitudeMSL()for more intuitive altitude.Cold-start false fix (
f2ad72e6)gnssFixOKandfixType == 3before reporting coordinates. Ublox reportsgnssFixOK == truewith bogus almanac-derived coords during cold start; requiring a 3D fix filters those out.Main-loop / button responsiveness fix (
a13098a5)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").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 needloop()every iteration to avoid dropping bytes.Debug-print cleanup (
c9dfd1bd)Merged up to date with
dev.Scope / affected boards
The
RAK12500LocationProviderandrakGPSInit()changes compile underRAK_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), andgat562_30s_mesh_kit. (gat562_mesh_watch13has GPS disabled;rak_wismesh_tagis excluded.)Implications for the already-shipping RAK4631 / GAT562 boards:
fixType == 3gating — 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_ALIVEis scoped to therak3401env only, sostop_gps()behavior is unchanged on the other boards. Worth a smoke-test on RAK4631 + i2c GPS before merge.