Skip to content

Powersaving on companion when serial is off (ble/wifi)#1347

Open
weebl2000 wants to merge 3 commits intomeshcore-dev:devfrom
weebl2000:powersaving-ble-companion
Open

Powersaving on companion when serial is off (ble/wifi)#1347
weebl2000 wants to merge 3 commits intomeshcore-dev:devfrom
weebl2000:powersaving-ble-companion

Conversation

@weebl2000
Copy link
Copy Markdown
Contributor

@weebl2000 weebl2000 commented Jan 8, 2026

Build firmware: Build from this branch

Update 27 February 2026

I've been running this for nearly two months now on a range of ESP32 devices and have seen no issues. I think it's good to merge.

Summary

Adds power saving to the companion radio when BLE/WiFi is disabled by the user. When the serial interface is off (and GPS is not enabled), the device enters ESP32-S3 light sleep for 30-minute intervals, significantly reducing power consumption for battery-powered companion nodes that are left running as pure relays.

Changes

Light sleep in companion radio (examples/companion_radio/main.cpp)

  • Enters 30-minute light sleep cycles when serial_interface.isEnabled() is false and GPS is off
  • Wakes on: LoRa packet (ext1), timer (30min), or button press (GPIO wakeup)
  • Stays awake briefly after wake to process any pending work before sleeping again
  • Initial 2-minute delay before first sleep to allow setup/connection

WiFi radio actually turns off (src/helpers/esp32/SerialWifiInterface.cpp/h)

  • disable() now calls WiFi.disconnect(true) and WiFi.mode(WIFI_OFF) to power down the radio
  • enable() reconnects using stored SSID/password credentials
  • Previously disable() only set a flag — the WiFi radio stayed powered on

Button wakeup with correct polarity (src/helpers/ESP32Board.h)

  • enterLightSleep() accepts optional pin_wake_btn parameter (backward-compatible)
  • Uses GPIO wakeup (GPIO_INTR_LOW_LEVEL) for button — correct for active-LOW buttons
  • Keeps ext1 (ANY_HIGH) for LoRa DIO1 only — these can't share a mask since they need opposite trigger levels

Pending work detection (examples/companion_radio/MyMesh.cpp/h)

  • hasPendingWork() checks outbound packet queue to avoid sleeping while packets are queued

Notes

  • Only affects ESP32-S3 targets (gated by CONFIG_IDF_TARGET_ESP32S3)
  • Boards without PIN_USER_BTN gracefully skip button wakeup
  • GPS-enabled nodes skip sleep entirely (GPS needs continuous operation)
  • No changes to the repeater sleep path — sleep() still calls enterLightSleep(secs) without button

@weebl2000 weebl2000 changed the base branch from main to dev January 8, 2026 16:04
@weebl2000 weebl2000 changed the title Powersaving ble companion Powersaving on companion when serial is off (ble/wifi) Jan 8, 2026
@weebl2000 weebl2000 force-pushed the powersaving-ble-companion branch from 35fad46 to 69f1ad3 Compare January 8, 2026 23:01
@weebl2000
Copy link
Copy Markdown
Contributor Author

Moved button handling logic to ESP32Board - this has the added benefit that repeaters will also wake up when you press the button (they do not currently).

@weebl2000
Copy link
Copy Markdown
Contributor Author

weebl2000 commented Jan 10, 2026

@fschrempf Actually basically all devices are low when pressed. Updated the code accordingly.

On my Heltec v4 the screen turns off when I disable bluetooth.

@weebl2000
Copy link
Copy Markdown
Contributor Author

I have confirmed this saves a bunch of milliamps when bluetooth is disabled, but even more so look at pr #1686. When bluetooth is enabled but phone isn't connected, we sleep for 3 seconds out of every and this saves about 80% power while still having bluetooth enabled. This PR works great but I'd suggest merging #1686 for even more power saving.

@IoTThinks
Copy link
Copy Markdown
Contributor

Button wakeup with correct polarity (src/helpers/ESP32Board.h)

  • enterLightSleep() accepts optional pin_wake_btn parameter (backward-compatible)
  • Uses GPIO wakeup (GPIO_INTR_LOW_LEVEL) for button — correct for active-LOW buttons
  • Keeps ext1 (ANY_HIGH) for LoRa DIO1 only — these can't share a mask since they need opposite trigger levels

Hi @weebl2000,
I intended to do for companion but using dynamic power management.
Eager to test yours and hope it can be in dev soon.

How much is power consumption during sleep? Still 10mA as same as repeater.
So when it sleeps, it will wakeup on: LoRa packet (ext1), timer (30min), or button press (GPIO wakeup)
=> During the wakeup, will the companion push the latest messages to the phone app?
if yes, then we don't need to press the button on the companion frequently.

In my latest PR, I shifted from ext1 use GPIO wakeup instead of ext1 so the sleep is available to all esp32 boards.
Ext1 is available to RTC GPIOs only and some Esp32 boards only have ext0.

https://github.com/meshcore-dev/MeshCore/pull/1687/changes#diff-bf2a85f9de86622aa1706e48181c52038e533cae13e3f52f5cd2a2a063b61dc8R85

@IoTThinks
Copy link
Copy Markdown
Contributor

IoTThinks commented Mar 18, 2026

I'm testing PowerSaving for Heltec v3 companion with BLE on .
Able to reduced from 120mA down to 40mA with BLE on. So 3000mAh battery can last Heltec v3 companion 3+ days.
Trying to reduce it to 20mA.

Yes, BLE connection to MeshCore app still works as normal.
I would say it much harder but more fun and helpful to keep BLE on.

@weebl2000
Copy link
Copy Markdown
Contributor Author

I'm testing PowerSaving for Heltec v3 companion with BLE on . Able to reduced from 120mA down to 40mA with BLE on. So 3000mAh battery can last Heltec v3 companion 3+ days. Trying to reduce it to 20mA.

Yes, BLE connection to MeshCore app still works as normal. I would say it much harder but more fun and helpful to keep BLE on.

See #1686

@IoTThinks
Copy link
Copy Markdown
Contributor

@weebl2000 My PowerSaving reduces power consumption to connected and fully functional BLE companions.
Your PRs only save battery when no BLE or BLE is disconnected.

A normal sleep as in repeaters can not save power without breaking BLE connection.
Nevermind, we can go with different approaches.

@IoTThinks
Copy link
Copy Markdown
Contributor

IoTThinks commented Mar 18, 2026

Ah, your PowerSaving still can provide extra power saving when BLE is not connected.
My PowerSaving provides power saving when BLE is connected.

The code is not overlapped / conflicted anyway. They complement each other. 👯‍♂️

@weebl2000 weebl2000 force-pushed the powersaving-ble-companion branch from ce18d1f to c21d9dc Compare March 23, 2026 13:29
weebl2000 and others added 3 commits April 4, 2026 13:19
Use millisHasNowPassed() (2's complement safe) instead of direct
comparison, consistent with the repeater's sleep timing logic.

Co-Authored-By: Wessel <weebl@users.noreply.github.com>
@weebl2000 weebl2000 force-pushed the powersaving-ble-companion branch from c21d9dc to be446c5 Compare April 4, 2026 11:19
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.

3 participants