Skip to content

Fixed hibernate / poweroff for BLE companions and repeaters to stay at uA#2895

Merged
fdlamotte merged 6 commits into
meshcore-dev:devfrom
IoTThinks:MCdev-Fixed-poweroff-to-uA-202607
Jul 6, 2026
Merged

Fixed hibernate / poweroff for BLE companions and repeaters to stay at uA#2895
fdlamotte merged 6 commits into
meshcore-dev:devfrom
IoTThinks:MCdev-Fixed-poweroff-to-uA-202607

Conversation

@IoTThinks

@IoTThinks IoTThinks commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Hi all,
This is another big PR to fix hibernate / poweroff for BLE companions and repeaters to stay at uA. E.g: Heltec v4 is at 13uA (not mA).
When hibernating / powerOff, the device with 3000 mAh should last months or even years.

Current situations in hibernating / poweroff:

  • powerOff / enterDeepSleep are duplicated in many variants and not stay at uA. The boards are stay in 6-10mA or more.
  • GPS: GPS is never off and consumes 10-20mA.
  • BLE companions: BLE companions with GPS does not off GPS when hibernating.
  • Repeaters: powerOff in NRF52 will stay at 6mA not work as "sd_power_system_off()" only works for devices with soft device (such as BLE).
  • poweroff CLI in repeaters does not cut power for OLED, LoRa and GPS.
  • Wakeup when there is LoRa packets: It should remain off even there are coming LoRa packets. In crowded areas, the devices will be waken up in 5s.

The proposed PR:

  • Put powerOff() in NRF52Board and ESP32Board to turn off OLED, LoRa, GPS.
  • Child variants can put in extra code and reuse the powerOff in NRF52Board and ESP32Board
  • Remove wakeup by buttons for ESP32Board. No board uses it. You can click RESET button to power on the board again.

I have tested with common boards in our lab.
However, you are welcome to test the PR for your boards.

Have a great day.

m0urs added a commit to m0urs/MeshCore that referenced this pull request Jul 5, 2026
…-202607

Io t thinks m cdev fixed poweroff to u a 202607
meshcore-dev#2895
@fdlamotte

Copy link
Copy Markdown
Collaborator

Yes, this was definitely necessary ... it's a lot cleaner now

@fdlamotte
fdlamotte merged commit 9e66a2e into meshcore-dev:dev Jul 6, 2026
12 checks passed
m0urs added a commit to m0urs/MeshCore that referenced this pull request Jul 6, 2026
Merge pull request meshcore-dev#2895 from IoTThinks/MCdev-Fixed-poweroff-to-uA-20…
@fdlamotte

fdlamotte commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

I think I might have been a little too fast to merge this ...

Seems all the boards are not refactored yet ...

Since _display-turnOff() and radio_driver.powerOff() have been moved away of UITask(), now on those boards that have not been refactored, display and radio will not be turned off :(

I think I'll add them back, to give time for all the boards to be updated

@IoTThinks

IoTThinks commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Since _display-turnOff() and radio_driver.powerOff() have been moved away of UITask(), now on those boards that have not been refactored, display and radio will not be turned off :(

By right, in this PR, _board->turnOff() will turn off display, radio, MCU and GPS.
Which boards are missing?

BTW, it is no harm to have _display-turnOff() and radio_driver.powerOff() besides _board->turnOff() in BLE companions.
It is just duplicated and gives no harm to BLE companions.

@fdlamotte

fdlamotte commented Jul 6, 2026 via email

Copy link
Copy Markdown
Collaborator

@IoTThinks

Copy link
Copy Markdown
Contributor Author

Yah, it is fine.

hermes-gadget added a commit to gadgethd/MeshCore-MQTT that referenced this pull request Jul 7, 2026
Upstream dev: b40968a..fec88e1 (9 commits)
- a92046b Put powerOff and enterDeepSleep to ESP32Board
- 73b7367 Put powerOff to NRF52Board
- 7d7de88 board->powerOff() is sufficient to power off radio, display, GPS and components
- eec75ea Cleanup Poweroff for NRF52 boards
- 6b205da Added missing driver/rtc_io.h
- 35f654c Fixed hibernate/powerOff for ESP32 boards to stay at uA
- 9e66a2e Merge pull request meshcore-dev#2895 (poweroff fixes)
- 3ee2f77 restore display and radio poweroff in ui
- fec88e1 fix tenstar c3 repeater build

Integration work:
- Squash merge of all MQTT additions from origin/main
- Resolved CommonCLI.cpp conflict: kept origin/main version (no new upstream fields)
- Removed firmware binaries from webflasher/
- Added missing gitignore patterns for webflasher/, .build-test/, *.bin

All MQTT additions preserved.
@Quency-D

Copy link
Copy Markdown
Contributor

@IoTThinks @fdlamotte I noticed that radio_driver.powerOff(); has been added back to UITask.cpp in the latest dev code. In fact, during my testing with the Heltec RC32, I found that repeatedly calling this function increases power consumption; it should be removed from UITask.cpp.

@IoTThinks

IoTThinks commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

@Quency-D Due to a bug in this (my) PR, T-echo of @fdlamotte can only sleep at 1mA instead of 1uA, so he added back radio_driver.powerOff() to UITask.cpp.
Later, this fix #2906 should let T-echo to power off at uA. And we can remove the radio_driver.powerOff() in UITask.cpp after this PR is merged to dev.

@Quency-D

Copy link
Copy Markdown
Contributor

Thanks for the clarification. That makes sense as a temporary workaround for the T-Echo.

Once #2906 is merged into dev, I’ll retest the Heltec RC32. If the duplicated radio_driver.powerOff() call is removed, I expect the shutdown current to return to the lower level I measured before.

So for now, keeping it temporarily is fine.

@fdlamotte

Copy link
Copy Markdown
Collaborator

#2906 is now merged

other variants than t-echo needs to get the same fix (shutdown global peripherals before variant ones) I'll do this in the morning ...

@fdlamotte

Copy link
Copy Markdown
Collaborator

@Quency-D @IoTThinks @entr0p1 I wonder if we could unify the shutdown procedures (with and without power management)

  • powerOff and initiateShutdown are two distinct entries to do shutdown (maybe initiateShutdown could rely on powerOff at some point to have the same shutdown procedure
  • I've introduced shutdownPeripherals and now I see there is a variant_shutdown in some variants, I think they serve more or less the same purpose (shutdownPeripherals is first defined at NRF52Board level and shuts down display, radio and gps and can be overriden by variants to shut down variant specific peripherals)

@IoTThinks

IoTThinks commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

For me, as long as the default methods can shutdown MCU, LoRa, OLED and GPS at parent boards, then it is fine for me.
As these components comsume 90+% of the powers.

There will be less work at the child boards for new variants to power off properly (mainly LEDs, Buzzers...) which consume little powers even when forgetting to off them.

@fdlamotte

Copy link
Copy Markdown
Collaborator

now removed duplicate call to display and radio poweroff in #2976

@entr0p1

entr0p1 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@Quency-D @IoTThinks @entr0p1 I wonder if we could unify the shutdown procedures (with and without power management)

* powerOff and initiateShutdown are two distinct entries to do shutdown (maybe `initiateShutdown` could rely on `powerOff` at some point to have the same shutdown procedure

* I've introduced `shutdownPeripherals` and now I see there is a `variant_shutdown` in some variants, I think they serve more or less the same purpose (`shutdownPeripherals` is first defined at NRF52Board level and shuts down display, radio and gps and can be overriden by variants to shut down variant specific peripherals)

I've already been doing this but looks like I've been beaten to the punch :)

The new power management code isnt gated; its on all nRF52840 now, just disabled unless the user turns it on. Shutdown path is unified.

There is a central powerOff() in nRF52Board that redirects to the new functions to maintain compatibility for UITask and CommonCLI's calls to it.

The flow is:

  1. something wants to power off the board -> calls initiateShutdown() which sits at the board level (powerOff just redirects to this)
  2. initiateShutdown: board-specific tasks run (e.g. turn off LEDs), then calls enterSystemOff() which is back in nRF52Board
  3. enterSystemOff: Sleeps the radio, turns off GPS (if fitted), handles any recovery provisioning (e.g. if it needs to arm LPCOMP wake because the user has configured it), then powers off the MCU

I've already cleaned up all the different iterations of powerOff overrides, initiateShutdown, variant_shutdown and its all in one tidy place. Much of the stuff duplicated across boards has also been centralised as well. Every board tested so far is reading nanoamps in off state.

@fdlamotte

Copy link
Copy Markdown
Collaborator

@entr0p1 nice ! as you've wrote the powermgmt stuff for nrf52 you're the best choice for getting it all sorted out

do you have a PR so I can review and merge it ?

@entr0p1

entr0p1 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

@fdlamotte I do have a PR, but I've marked it back to a draft so I can run the board shutdown tests and rebase onto the latest dev commits: #2088

Funnily enough the recent merged commits have gotten some things over the line that I wanted to do in the PR, but avoided since it was already a pretty big commit :) I just need to retrofit it all together now. @IoTThinks has been especially integral to all things power management (and the testing) so I'll ensure none of that gets lost in translation to the final version.

The latest build is being tested by some folks in the thread, and the boards I've ordered to test the shutdown and recovery have mostly arrived so I'll be working through the bench tests this weekend.

Edit: The draft commit is far from what it is now by the way, so probably worth saving your energy til I push the updated one.

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.

4 participants