Skip to content

Cut NRF52 bluetooth power usage by 300% - testers needed!#8858

Merged
thebentern merged 9 commits into
meshtastic:developfrom
phaseloop:nrf52-power-saving-1
Dec 9, 2025
Merged

Cut NRF52 bluetooth power usage by 300% - testers needed!#8858
thebentern merged 9 commits into
meshtastic:developfrom
phaseloop:nrf52-power-saving-1

Conversation

@phaseloop

@phaseloop phaseloop commented Dec 4, 2025

Copy link
Copy Markdown
Contributor

According to Nordic online power profiler and general industry recommendation for low power BLE devices (see below), this change should reduce raw bluetooth subsystem power usage by at least 300%.

In advertisement mode (no phone connection) simulated current drop should be from 146 uA to 56 uA for the RF layer only.

When phone is connected to node (theoretical) yield should be around 400% as node is allowed to skip up to 5 extra interrogation/keep-alive frames longer if there is no data to send (so called slave latency).

Physics behind it:

https://docs.silabs.com/bluetooth/2.13/bluetooth-general-system-and-performance/optimizing-current-consumption-in-bluetooth-low-energy-devices

Changes introduced:

  • increase advertisement frame interval from 152.5 ms to 417.5 ms for slow discovery mode - which is still in the lower range of available BLE intervals and way within values recommended by Apple (link in the source code). For many low power BLE devices intervals starts above 500 ms.

This change to be in effect was confirmed by nRF Connect logs. I don't see any visible impact on Meshtastic app connection/discovery times to node or general Android visibility of the device.

  • increase Slave Latency factor to 5 (from default value of 0), which means node can freely ignore up to 5 keep-alive frames from a phone when it has no data to transmit - and it will not affect anything with connection stability. Which means we don't need to waste power sending BLE frames that do nothing.

Screenshot by SiLabs from link above:

slave-latency

While this is a generic industry knowledge and we know power savings are there, it would be good if someone with a decent power profiler can check how theoretical yield looks in practice. It would be great if other people can test this change with their phones and nodes.

Those are still pretty conservative settings so we can have further fun once this is verified to be stable across general population.

I suppose similar change to ESP32 may bring much drastic power savings.

🤝 Attestations

  • I have tested that my proposed changes behave as described.

  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:

    • Promicro/NiceNanoV2 - Faketec custom board

@thebentern thebentern added the enhancement New feature or request label Dec 4, 2025
@thebentern

Copy link
Copy Markdown
Contributor

@phaseloop are you on the discord? We can probably engage more testers there,

@phaseloop

Copy link
Copy Markdown
Contributor Author

@thebentern I joined discord now, I'll ping you there

@neopiccolorat

Copy link
Copy Markdown

Would this be the fix to the drainage of phone battery some of us experienced?

@phaseloop

Copy link
Copy Markdown
Contributor Author

Can you share more specifics? Which phones and boards, etc? I would expect this to happen with esp32 because bluetooth timings set there are crazy and if phone stack does not support timing renegotiation I would pretty much expect it to drain battery fast.

@rbomze

rbomze commented Dec 6, 2025

Copy link
Copy Markdown
Contributor

i think you mean -66%. you can't 'cut' 300% - you'll end up BLE generating us power for Lora :D. And .. this just refers to the power of BLE advertising - which is a cut from 100uA down to 33uA. Those Airtags and 'Faketecs' (which are flashed nRF52820 with coin battery) do this BLE advertising 24/7 ... for a year+.
Anyway congratulations 🎉 for this cool discovery. Need to test it tomorrow :D

@phaseloop

Copy link
Copy Markdown
Contributor Author

i think you mean -66%. you can't 'cut' 300% - you'll end up BLE generating us power

lmao, we don't need solar panels anymore! You're right - I should change it to "improve by" maybe.

Yeah I thought description was clear that this BT subsystem power usage only. Funny enough much bigger power saving can be at the phone side as timing influences battery drain too.

@mdecourcy

Copy link
Copy Markdown

Funny enough much bigger power saving can be at the phone side as timing influences battery drain too.

Can you expand on this and potentially create an issue in the app repos?

@RichieFrame

Copy link
Copy Markdown

Flashed to a t-echo and custom RAK4631 device, no noticeable changes in behavior yet

@ndoo

ndoo commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

Tested this on a T114v2, so far no regression, Android app works fine over BLE.

  1. Forget device from Android settings -> Bluetooth
  2. Scan from Meshtastic app
  3. Pair and key in BLE PIN again

Above works well.

Screenshot_20251208-112930

@ndoo

ndoo commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

Spoke too soon, I’m not able to change any settings from the Android app. Tried reset (rebooting) of the T114, clearing and re-pairing the BLE bonds.

Android app gets stuck at 0% when opening any settings pane, and the T114 spams this to serial log:

INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162

@ndoo

ndoo commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

Spoke too soon, I’m not able to change any settings from the Android app. Tried reset (rebooting) of the T114, clearing and re-pairing the BLE bonds.

Android app gets stuck at 0% when opening any settings pane, and the T114 spams this to serial log:

INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 843 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 843 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162
DEBUG | 19:38:08 844 Drop dup ToRadio packet we just saw
INFO  | 19:38:08 844 toRadioWriteCb data 0x2002abe2, len 162

Posted this too soon… the page did eventually load, after about a minute of spamming the log. Going to flash without the change to confirm this PR caused the issue.

Would appreciate if anyone else can confirm this PR makes configuration panes take much longer to load and spam the log too.

@ndoo

ndoo commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

Downgraded back to 2.7.16 tag, settings panes load instantly on Android, so this PR does cause a regression for my setup.

@RichieFrame

Copy link
Copy Markdown

Would appreciate if anyone else can confirm this PR makes configuration panes take much longer to load and spam the log too.

While I did not check the log, the settings loaded instantly, and I was able to modify them without issue or delay

Android app 2.7.8, on both devices I flashed

@phaseloop

phaseloop commented Dec 8, 2025

Copy link
Copy Markdown
Contributor Author

@ndoo I have some suspicions what may be the issue.

What phone is it? Does this happen only when trying to save settings? Can you try disabling BT on phone, waiting 15s and reconnecting again?

@mdecourcy As for phone battery drain - there is BLE setting called connection interval which influences radio subsystem power usage and sleep modes (this is what is broken in esp32 ESP-IDF before v5.5, lmao). But when talking about that I forgot this is something I have in other PR not yet published as we need to sort out this one first.

@ndoo

ndoo commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

I noticed the pushed commits involve the T114, do you still need me to make any changes to bisect the issue or do you wish me to just test the latest commit as-is?

@ndoo

ndoo commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

@ndoo I have some suspicions what may be the issue.

What phone is it?

Sonim XP8800, Android 10, Qualcomm SDM630.

Does this happen only when trying to save settings?

Yes, but not saving settings - just opening the settings pane where it tries to read settings.

Can you try disabling BT on phone, waiting 15s and reconnecting again?

Not tested yet.

@phaseloop

phaseloop commented Dec 8, 2025

Copy link
Copy Markdown
Contributor Author

@ndoo - yes, please test the latest commits. There are confirmed issues that damaged/off spec LF crystals may throw off bluetooth timings when using slave latency settings.

If this is XTAL issue - it may explain why it worked initially but stopped as the crystal heated a bit and deviated in freq

@max-arnold

Copy link
Copy Markdown

I can't connect from MacBook Pro 13" 2017 (Bluetooth 4.2) to T1000-E with 2.7.16 and this patch applied.

@ndoo

ndoo commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

Android app settings loading and reading back are are snappy for me again on the latest commit, T114v2, Android 10, Qualcomm SDM630.

Did not re-pair the node.

@phaseloop

phaseloop commented Dec 8, 2025

Copy link
Copy Markdown
Contributor Author

@max-arnold @ndoo - I pushed another change. I got a Mac to test but I'll check if the same issue can be replicated here.

Edit: works fine on Mac M3. I'll dig up some ancient Android.

@max-arnold

Copy link
Copy Markdown

@phaseloop The last commit fixed the issue on MB Pro 2017 (Bluetooth 4.2). Also tested on iPhone XR (Bluetooth 5.0).

@phaseloop

phaseloop commented Dec 8, 2025

Copy link
Copy Markdown
Contributor Author

@max-arnold awesome, thanks for testing!

It seems that some devices ignore GAT preferred settings and need to be forced to renegotiate it.

@thebentern thebentern merged commit ae8d3fb into meshtastic:develop Dec 9, 2025
66 of 67 checks passed
@ponzano

ponzano commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

Hi, just tested the power consumption difference with and without this commit using a lab bench multimeter and a MeshLink board.
On average, it consumes about 0.24mA less at 4.00v after the commit with app connected.
I found that bluetooth connection using iOS was very difficult but it connected successfully after about a minute of automatically retrying. Forgetting device did not help.
photo_2025-12-09_14-54-15
photo_2025-12-09_14-54-16

@phaseloop

phaseloop commented Dec 9, 2025

Copy link
Copy Markdown
Contributor Author

@ponzano did you test the branch with the changes I implemented yesterday?

Do you know what is overall power cost of having bluetooth enabled on NRF52?

@ponzano

ponzano commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

@ponzano did you test the branch with the changes I implemented yesterday?

Do you know what is overall power cost of having bluetooth enabled on NRF52?

Uh no I didn’t notice it, I’ll have time to test again with this (and better) instrumentation on Friday morning so we’ll have to wait a couple of days. I’ll also compare power usage with and without Bluetooth enabled.
Just to be sure, is it this one with the latest updates? https://github.com/phaseloop/meshtastic-firmware/tree/nrf52-power-saving-1

@phaseloop

phaseloop commented Dec 9, 2025

Copy link
Copy Markdown
Contributor Author

Yeah, that patch fixed connectivity issues on MacOS so there is a big change it will fix your issue too :).

The branch you mentioned is the one. Thanks for testing!

@thebentern - is it possible to reopen this PR somehow?

@max-arnold

Copy link
Copy Markdown

I did more tests with an iPhone XR (bluetooth 5.0) and after a couple of successful connects/disconnects (and maybe some idle time) the phone refuses to connect again. Rebooting the T1000-E usually helps.

@fifieldt

Copy link
Copy Markdown
Member

@phaseloop , need to make a new PR - but you can push to the same branch

@phaseloop

Copy link
Copy Markdown
Contributor Author

@max-arnold I've pushed a patch that may help. Please see if there is anything in debug log when the phone can't connect. Thanks!

@max-arnold

Copy link
Copy Markdown

@phaseloop I do not see any new commits in your branch develop...phaseloop:meshtastic-firmware:nrf52-power-saving-1 (I did my last test using the "force BLE param negotiation" revision)

@phaseloop

Copy link
Copy Markdown
Contributor Author

I commited to wrong branch, should be ok now

@max-arnold

Copy link
Copy Markdown

Here is the log when my phone fails to connect twice and then succeeds on the third attempt (all I did to reproduce the problem is just connecting and disconnecting multiple times):

INFO  | 14:02:51 553 BLE Connected to iPhone XR (Max)
DEBUG | 14:02:51 553 BluetoothStatus CONNECTED
INFO  | 14:02:51 553 BLE connection secured
INFO  | 14:02:52 555 BLE Disconnected, reason = 0x13
DEBUG | 14:02:52 555 PhoneAPI::close()
DEBUG | 14:02:52 555 BluetoothStatus DISCONNECTED
INFO  | 14:03:03 565 BLE Connected to iPhone XR (Max)
DEBUG | 14:03:03 565 BluetoothStatus CONNECTED
INFO  | 14:03:03 565 BLE connection secured
INFO  | 14:03:04 567 BLE Disconnected, reason = 0x13
DEBUG | 14:03:04 567 PhoneAPI::close()
DEBUG | 14:03:04 567 BluetoothStatus DISCONNECTED
INFO  | 14:03:09 572 BLE Connected to iPhone XR (Max)
DEBUG | 14:03:09 572 BluetoothStatus CONNECTED
INFO  | 14:03:09 572 BLE connection secured
INFO  | 14:03:11 573 CCCD Updated: 1
INFO  | 14:03:11 573 Notify/Indicate enabled
INFO  | 14:03:11 573 CCCD Updated: 1
INFO  | 14:03:11 573 Notify/Indicate enabled
INFO  | 14:03:11 573 toRadioWriteCb data 0x2001cf3a, len 8
DEBUG | 14:03:11 573 New ToRadio packet
DEBUG | 14:03:11 573 Got client heartbeat

I'm testing against 2.7.16 with your branch applied on top.

@max-arnold

Copy link
Copy Markdown

Another type of failure:

INFO  | 14:20:46 1629 BLE Connected to iPhone XR (Max)
DEBUG | 14:20:46 1629 BluetoothStatus CONNECTED
INFO  | 14:20:46 1629 BLE connection secured
INFO  | 14:20:48 1630 BLE Disconnected, reason = 0x13
DEBUG | 14:20:48 1630 PhoneAPI::close()
DEBUG | 14:20:48 1630 BluetoothStatus DISCONNECTED
INFO  | 14:20:55 1637 BLE Connected to iPhone XR (Max)
DEBUG | 14:20:55 1637 BluetoothStatus CONNECTED
INFO  | 14:20:55 1637 BLE connection secured
INFO  | 14:20:56 1639 BLE Disconnected, reason = 0x13
DEBUG | 14:20:56 1639 PhoneAPI::close()
DEBUG | 14:20:56 1639 BluetoothStatus DISCONNECTED
INFO  | 14:20:59 1642 BLE Connected to iPhone XR (Max)
DEBUG | 14:20:59 1642 BluetoothStatus CONNECTED
INFO  | 14:20:59 1642 BLE connection secured
INFO  | 14:21:01 1644 CCCD Updated: 1
INFO  | 14:21:01 1644 Notify/Indicate enabled
INFO  | 14:21:01 1644 CCCD Updated: 1
INFO  | 14:21:01 1644 Notify/Indicate enabled

... at this point the app says "Too Many Retries" (No device connected, and my T1000-E is not in the list of available radios)

However, the radio thinks it is connected and if I force close the app, radio prints the following lines:

INFO  | 14:25:10 1892 CCCD Updated: 0
INFO  | 14:25:10 1892 Notify/Indicate disabled
INFO  | 14:25:10 1893 BLE Disconnected, reason = 0x13
DEBUG | 14:25:10 1893 PhoneAPI::close()
DEBUG | 14:25:10 1893 BluetoothStatus DISCONNECTED

@phaseloop

Copy link
Copy Markdown
Contributor Author

Thanks! That helped a lot. I pushed another fix. It seems some Apple products between iOS versions have conflicting BLE requirements. So we probably need to test few settings to check what makes it happy. I

@max-arnold

Copy link
Copy Markdown

Unfortunately the problem is still there. Also found another way to reproduce it (not 100% reliably, sometimes it works just fine):

  1. Connect to the radio
  2. Wait till the phone finishes fetching the node list
  3. Disconnect
  4. Wait 1-5 minutes
  5. Try to connect - sometimes it fails to connect and the app shows "Too Many Retries" and needs to be restarted to be able to connect again

Without the patch the app always connects reliably. iOS version 18.7.2 (latest for an iPhone XR)

@phaseloop

Copy link
Copy Markdown
Contributor Author

Thanks! I pushed another change - this time disabled Slave Latency at all. I increased the connection interval a bit so we can offset energy saves there.

Are you on discord? Maybe we can switch there. I hope disabling SL will work this time xD

@ponzano

ponzano commented Dec 12, 2025

Copy link
Copy Markdown
Contributor

here are some tests:
1- Firmware without blt optimizations
-Bluetooth on and connected
photo_2025-12-12_10-29-11

-Bluetooth on but disconnected
photo_2025-12-12_10-29-13

-Bluetooth off
photo_2025-12-12_10-29-15

After updating to your version i can't connect anymore on iPhone 12 iOS 26.2

@ponzano

ponzano commented Dec 12, 2025

Copy link
Copy Markdown
Contributor

Connected using an android phone
2-Your version of firmware:
-Bluetooth enabled and connected
photo_2025-12-12_10-50-37

-Bluetooth enabled but disconnected
photo_2025-12-12_10-53-09

-Bluetooth disabled

photo_2025-12-12_10-57-11

@phaseloop

Copy link
Copy Markdown
Contributor Author

@ponzano thank you! That was helpful. Can you try the latest commit to check if iPhone issues were fixed?

@max-arnold

Copy link
Copy Markdown

@phaseloop With the latest version of your branch both my phone and laptop reliably connect to T1000-E

@phaseloop

Copy link
Copy Markdown
Contributor Author

Perfect, thanks! If @ponzano confirms latest patch works for their iPhone as well, I'll reopen the PR and merge those changes.

Thank you all for testing and helping!

@ponzano

ponzano commented Dec 15, 2025

Copy link
Copy Markdown
Contributor

Perfect, thanks! If @ponzano confirms latest patch works for their iPhone as well, I'll reopen the PR and merge those changes.

Thank you all for testing and helping!

Yes seems to work correctly with iPhone as well! Nice job 👍

scobert969 pushed a commit to zeropt/meshtastic-firmware that referenced this pull request Dec 22, 2025
…#8858)

* Improve NRF52 bluetooth power efficiency

* test T114 bad LFXO

* T1000 test

* force BLE param negotiation

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
scobert969 pushed a commit to zeropt/meshtastic-firmware that referenced this pull request Dec 22, 2025
jeek pushed a commit to jeek/Meshtastic-Exploiteers-Hacker-Pager that referenced this pull request Jun 30, 2026
…#8858)

* Improve NRF52 bluetooth power efficiency

* test T114 bad LFXO

* T1000 test

* force BLE param negotiation

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
jeek pushed a commit to jeek/Meshtastic-Exploiteers-Hacker-Pager that referenced this pull request Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants