Skip to content

GPS power cycling between fixes (companion) 🤖🤖 - #3684

Open
ajgray2017 wants to merge 6 commits into
meshcore-dev:devfrom
ajgray2017:feature/gps-duty-cycle
Open

ajgray2017 wants to merge 6 commits into
meshcore-dev:devfrom
ajgray2017:feature/gps-duty-cycle

Conversation

@ajgray2017

@ajgray2017 ajgray2017 commented Oct 26, 2026 •

Copy link
Copy Markdown

Problem

On battery companions the GPS is either powered all the time or off. Meshtastic users expect an interval mode: wake, get a fix, power down, repeat. Nodes that rarely move save a lot of battery this way.

Change

  • New sensor setting gps_duty: seconds between fixes, 0 = always on (the default), max 86400. It uses the existing CMD_GET/SET_CUSTOM_VAR, so there is no protocol change.
  • Opt-in: listed only after the firmware calls EnvironmentSensorManager::configureGPSDuty(). The companion calls it because it saves the value. Repeater and room server firmware don't list it, so sensor set can't create an unsaved setting there.
  • While GPS is on and gps_duty > 0, EnvironmentSensorManager::loop():
    1. powers the GPS on and waits for a fix;
    2. holds the fix GPS_DUTY_SETTLE_SECS (default 10 s) so the RTC can sync;
    3. stores the position and powers the GPS off;
    4. waits gps_duty seconds before the next wake.
  • The NMEA parser doesn't run while the GPS is off. It still holds the last fix, and running it would let the periodic RTC resync set the clock back to that fix's time.
  • gps_active stays true while the GPS is off, so the gps setting, adverts and telemetry keep using the last fix. Setting gps_duty=0 while asleep powers the GPS straight back on.
  • With gps_duty=0, behaviour is the same as before. The parser clear and RTC re-sync on wake only happen when cycling.
  • Saved in NodePrefs (gps.duty) and re-applied in applyGpsPrefs().
  • OLED GPS page:
    • It shows gps on 5m, or gps sleep 5m while the GPS is off.
    • Long-press on the GPS page now steps through off → on → 1m → 5m → 15m → 1h → off.
    • Boards without gps_duty keep the old toggle, and the sensors page keeps the plain toggle.
  • Optional GPS_DUTY_MAX_ON_SECS gives up without a fix (default 0 = wait for a fix).
  • Not applied to RAK WisBlock GPS boards, which have their own power handling.
  • FAQ entry 5.17. It notes that boards with no GPS power switch save no power; the setting only limits how often the position updates.

Testing

Heltec V3 companion, u-blox module powered from a GPIO enable pin (GPIO42):

  • Bounds: gps_duty=-5 and gps_duty=90000 are rejected. 60 and 300 are accepted and persist across a reboot.

  • No fix, indoors (debug build, GPS_DUTY_MAX_ON_SECS=45, gps_duty=60): no fix, sleeping 45 s after power-on, then waking 60.0 s later, repeating.

  • gps_duty=0 while asleep: NMEA output resumes 0.2 s later and the GPS stays on (no sleep for 60 s). Setting 60 again resumes cycling.

  • Repeater with the same GPS: sensor list shows only gps, and sensor set gps_duty 60 replies can't find custom var.

  • Unit tests: pio test -e native -e native_kiss_modem passes (54/54).

  • Cycle with a fix (gps_duty=300, indoors near a window): fix, power down, wake 300.0 s later, new fix (541 s cold start), power down.

  • RTC during sleep, original vs. this PR. Test-only build with the provider's resync interval cut from 30 min to 120 s so the bug shows within one sleep. The clock was checked against the host:

    at fix 150 s into sleep 270 s into sleep
    parser left running while asleep (first version) −1 s −114 s −234 s
    this PR 0 s 0 s 0 s

    With the parser running, each resync put the clock back to the last fix's time. With the stock 30 min interval and the 1h preset, this sets the clock back by up to an hour.

  • OLED: long-press on the GPS page steps through the presets (checked by hand).

  • Boards: the fix and RTC tests ran on a second Heltec V3 with the same wiring. The other tests ran on the first board.

Compile-checked (all build, no new warnings; wio_wm1110_repeater shows the same 5 ENV_INCLUDE_GPS redefined warnings as dev):
Heltec_v3_companion_radio_usb, Heltec_v3_companion_radio_ble, Heltec_v3_repeater, Heltec_v3_room_server,
Heltec_t114_companion_radio_ble, Heltec_Wireless_Tracker_companion_radio_ble, Tbeam_SX1276_companion_radio_ble,
Tbeam_SX1276_repeater, LilyGo_TDeck_companion_radio_ble, RAK_4631_companion_radio_ble, RAK_4631_companion_radio_ethernet,
RAK_4631_repeater, RAK_4631_repeater_ethernet, RAK_4631_room_server, RAK_4631_room_server_ethernet,
PicoW_repeater, wio-e5-mini_repeater, LilyGo_Tlora_C6_repeater_, wio_wm1110_repeater.

Open questions for maintainers

  1. Is it OK for the GPS-page long-press to cycle presets instead of a pure on/off toggle?
  2. Should GPS_DUTY_MAX_ON_SECS default to a timeout (e.g. 300 s), so the GPS doesn't drain the battery indoors waiting for a fix?

Note

This is independent of #3683 (runtime GPS pins) and branches from dev. Both touch the GPS settings list, GPSPrefs and the FAQ numbering. I test-merged the two: the conflicts are "keep both sides", plus one shared #if block in the header and the FAQ renumbered to 5.18. The result runs on a Heltec V3 with all six GPS settings working.

🤖 Generated with Claude Code

ajgray2017 and others added 6 commits October 26, 2026 11:00
Battery companions with a GPS enable pin could only keep the GPS powered
all the time or turn it off.

- New sensor setting gps_duty (seconds between fixes, 0 = always on,
  default; max 86400) via the existing custom vars, persisted in
  NodePrefs (gps.duty) and re-applied in applyGpsPrefs().
- While GPS is on and gps_duty > 0: power on, wait for a fix, hold it
  GPS_DUTY_SETTLE_SECS (10 s) so the RTC syncs, store the position, power
  off, wake gps_duty seconds later. gps_active stays true throughout, so
  adverts/telemetry keep the last fix. gps_duty=0 behaves as before.
- Optional GPS_DUTY_MAX_ON_SECS gives up without a fix (default 0).
- OLED GPS page shows "gps on 5m" / "gps sleep 5m"; long-press on the GPS
  page cycles off -> on -> 1m -> 5m -> 15m -> 60m -> off (plain toggle if
  the board has no gps_duty).
- Not applied to RAK WisBlock GPS boards. FAQ 5.17.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With gps_duty > 0, loop() kept calling _location->loop() while the GPS
was powered down. The NMEA parser still held the last fix (it is only
cleared on wake), so isValid() stayed true, and the provider's 30-minute
RTC re-sync could fire during the sleep and set the clock to the last
fix's time: up to gps_duty seconds in the past (an hour with the 1h
preset, a day at the 86400 maximum).

Only run the parser while the GPS is powered, or when not duty cycling.
The stored position is unaffected; it is copied before power-down.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gps_duty was listed whenever a GPS was detected, so repeater and room
server firmware showed it in "sensor list" and accepted "sensor set
gps_duty N" with an immediate effect, but never saved it: the value was
lost on reboot. Only the companion persists gps_duty.

Follow the same opt-in as the runtime GPS pin settings: the setting is
listed and accepted only after the firmware calls configureGPSDuty(),
which the companion does from applyGpsPrefs(). ENV_GPS_DUTY_CYCLE moves
to the header so the companion can test for it; boards whose sensor
manager is not an EnvironmentSensorManager (e.g. Heltec Wireless
Tracker) don't define it and are unaffected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
On PERSISTANT_GPS boards initBasicGPS() leaves the GPS powered and sets
gps_active without going through start_gps(), so gps_powered stayed
false. With gps_duty > 0 the first loop then "woke" a GPS that was
already on: a second begin()/reset() and parser clear right after boot,
and an extra claim on the location provider. None of today's
PERSISTANT_GPS boards (T-Beam, T-Beam 1W, ThinkNode M5) pass a shared
power pin, so the extra claim had no effect yet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The GPS page showed a 3600 s duty as "gps on 1h" while the long-press
alert for the same preset said "GPS: 60m". Format both with one helper
that picks the largest exact unit (s, m or h), and update the FAQ preset
list to match.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gps_duty is listed on every board with a detected GPS, but it can only
power the GPS down where the firmware controls its power (an enable pin
or switched supply). Say so, and what it still does on other boards.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant