Skip to content

NmeaGpsDriver: optional UART baud rate detection from a per-board list - #3

Merged
fdlamotte merged 2 commits into
fdlamotte:gps_refactorfrom
AlexandrTyshchenko:feature/gps-baud-autodetect-refactor
Nov 9, 2026
Merged

fdlamotte merged 2 commits into
fdlamotte:gps_refactorfrom
AlexandrTyshchenko:feature/gps-baud-autodetect-refactor

Conversation

@AlexandrTyshchenko

@AlexandrTyshchenko AlexandrTyshchenko commented Nov 9, 2026 •

Copy link
Copy Markdown

@fdlamotte port of meshcore-dev#3729 onto gps_refactor, as discussed in meshcore-dev#3753.

Problem

NmeaGpsDriver opens the UART at a fixed GPS_BAUD_RATE (9600 by default). detect() only checks that bytes arrive, which also happens at the wrong rate: the GPS is reported as present, but the parser only sees garbage and never gets a fix. Modules such as the M5Stack GROVE GPS now default to 115200, and DIY boards are often wired to modules set to 38400.

Change

A board can pass NmeaGpsDriver a list of baud rates to try (a short constructor NmeaGpsDriver(serial, rates, count), or the last two arguments of the full one). Then detect() (on a real detection with a timeout, not the detect(0) polls) tries the configured rate first and then the board's rates, and keeps the first one that gives an NMEA sentence with a valid checksum within 2 s. The rate is stored in _baudRate, so startHardware() reopens the UART with it on every later power cycle (periodic mode, gps on). If no rate works, the configured one is kept.

  • Without a list nothing changes: only the configured rate is used, no probing.
  • The list belongs to the board, so its maintainer decides which rates are possible. As an example, variants/promicro/target.cpp takes an optional GPS_BAUD_PROBE_LIST (e.g. -D GPS_BAUD_PROBE_LIST=9600,38400,115200), since ProMicro boards are often wired to whatever UART GPS module is at hand.
  • Only the NMEA path is touched. The RAK serial path calls _nmeaDriver.detect(0) and is not probed.
  • Worst case at boot: one 2 s probe per listed rate when the module sends at none of them.

Testing

  • Builds: ProMicro_sensor with and without GPS_BAUD_PROBE_LIST, heltec_tracker_v2_sensor (no list).
  • Hardware: ProMicro nRF52840 (Faketec) + UART GPS module running at 38400 baud, firmware built with the default GPS_BAUD_RATE (9600) and GPS_BAUD_PROBE_LIST=9600,115200,38400. Boot log: GPS baud rate: 38400, GPS detected; the module then got a fix (up to 12 sats) and position/time were read normally. The first version of this PR (static list behind a build flag) gave the same result on the same board.

…TECT)

Bytes arriving on the UART does not mean the baud rate is right: at the
wrong rate the parser only sees garbage and never gets a fix. Modules
such as the M5Stack GROVE GPS now default to 115200, while boards
configure 9600.

With GPS_BAUD_AUTODETECT, detect() probes common GNSS rates, starting
with the configured one, and keeps the first one that yields an NMEA
sentence with a valid checksum. The rate is stored in the driver, so
later power cycles reopen the UART with it. Without the flag nothing
changes.

Ported from meshcore-dev#3729 onto the GpsDriver refactor.
Comment thread src/helpers/sensors/NmeaGpsDriver.h Outdated
_started = true;
}

#ifdef GPS_BAUD_AUTODETECT

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe instead of a static list of baudrates checked upon a compile option you could add a constructor for NMEAGpsDriver that accepts a list of baudrates to test ?

Then the maintener for a given port would decide which baudrates are possible for his board (if multiple baudrates are possible) ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in cbfa66d: NmeaGpsDriver now takes an optional list of rates to try (short constructor NmeaGpsDriver(serial, rates, count), or the last two arguments of the full one). Without a list nothing is probed. GPS_BAUD_AUTODETECT and the static list are gone. As an example, variants/promicro/target.cpp takes an optional GPS_BAUD_PROBE_LIST. Retested on the same board: GPS at 38400, firmware at 9600, list 9600,115200,38400 → GPS baud rate: 38400.

@AlexandrTyshchenko AlexandrTyshchenko changed the title NmeaGpsDriver: optional UART baud rate autodetection (GPS_BAUD_AUTODETECT) NmeaGpsDriver: optional UART baud rate detection from a per-board list Nov 9, 2026
@fdlamotte

Copy link
Copy Markdown
Owner

Thanks for your PR,
As you've seen I've made some comments, but it looks good overall (and something I was wanting ...)

@AlexandrTyshchenko

Copy link
Copy Markdown
Author

Thanks! The constructor list is in cbfa66d, see the thread above. Tested on a ProMicro with a GPS at 38400 and firmware at 9600.

@fdlamotte
fdlamotte merged commit 519cf4c into fdlamotte:gps_refactor Nov 9, 2026
1 check passed
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