Skip to content

Comments

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

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 weebl2000 force-pushed the powersaving-ble-companion branch from f090774 to 28773f8 Compare February 6, 2026 01:10
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
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

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