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
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
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
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
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
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

@weebl2000 weebl2000 force-pushed the powersaving-ble-companion branch from 40d12c7 to 3243527 Compare February 25, 2026 02:15
weebl2000 and others added 3 commits February 26, 2026 23:16
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>
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