Skip to content

nRF52840 Power Management Stage 1 v2.1 - Boot lockout fix - #2088

Draft
entr0p1 wants to merge 1 commit into
meshcore-dev:devfrom
entr0p1:nrf52840-pwrmgt-stage1-v2_1
Draft

nRF52840 Power Management Stage 1 v2.1 - Boot lockout fix#2088
entr0p1 wants to merge 1 commit into
meshcore-dev:devfrom
entr0p1:nrf52840-pwrmgt-stage1-v2_1

Conversation

@entr0p1

@entr0p1 entr0p1 commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Improvements:

  • Add configurable battery chemistry
  • Add per-chemistry LPCOMP wake threshold and boot lockout voltage
  • Add configurable enabled/disabled state for boot lockout
  • Reduce Li-ion/Li-Po lockout threshold to 3.0V from 3.3V
  • Initialise FS earlier in the startup process to allow reading configured settings for boot lock

Fixes:

  • Add additional shutdown reason "None" for instances where the reason isn't set
  • Boot lockout disabled by default

@MGJ520

MGJ520 commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Good job

Improvements:
- Add configurable battery chemistry
- Add per-chemistry LPCOMP wake threshold and boot lockout voltage
- Add configurable enabled/disabled state for boot lockout
- Reduce Li-ion/Li-Po lockout threshold to 3.0V from 3.3V
- Initialise FS earlier in the startup process to allow reading configured settings for boot lock

Fixes:
- Add additional shutdown reason "None" for instances where the reason isn't set
- Boot lockout disabled by default
@entr0p1
entr0p1 force-pushed the nrf52840-pwrmgt-stage1-v2_1 branch from d5f6c76 to e32e30b Compare March 22, 2026 01:37
@entr0p1
entr0p1 marked this pull request as ready for review March 23, 2026 01:29
@entr0p1

entr0p1 commented Mar 23, 2026

Copy link
Copy Markdown
Contributor Author

Tested on a couple of boards now without issues so far. Ready to be reviewed.

@Pacjunk

Pacjunk commented Mar 27, 2026

Copy link
Copy Markdown

Does setting pwrmgt.bootlock to off also prevent the low voltage shutdown? or is it only for boot?

@recrof

recrof commented Apr 18, 2026

Copy link
Copy Markdown
Member

I truly understand what @entr0p1 wanted to do here and I respect it, however: I feel this became tad too over-engineered and we need to regroup and make it really simple:
ability to configure shutdown voltage and make it 0V as default. adding chemistries raises complexity and resources - we need to get rid of that. make the feature opt-in and not opt-out is also important.

@entr0p1

entr0p1 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor Author

@recrof appreciate the respectful approach you've taken, I'm not fussed if it has to be pared right back or removed entirely. The fix is here if desired, but if you'd rather a different approach I won't be offended if you want to close it and do that.

@fschrempf

Copy link
Copy Markdown
Contributor

I truly understand what @entr0p1 wanted to do here and I respect it, however: I feel this became tad too over-engineered and we need to regroup and make it really simple:
ability to configure shutdown voltage and make it 0V as default. adding chemistries raises complexity and resources - we need to get rid of that.

100% agree.

make the feature opt-in and not opt-out is also important.

This is the most crucial point. #1413 was not ready for merging and still got merged for v1.12. It broke a lot of setups and now three months and three releases later things are still broken. People need to modify their firmware manually and climb on roofs because of this.

Can we please either:

  1. leave the current code as is, but add a configuration option that enables/disables the undervoltage bootlock and have this option disabled by default or
  2. just disable NRF52_POWER_MANAGEMENT for all boards.

Thanks!

@ssozonoff

Copy link
Copy Markdown

When the final decision has been made and code merged and released it will be important to communicate about this in any case. I personally believe we will be seeing more and more LTO and Sodium-ion based repeaters in the future.

@fschrempf

Copy link
Copy Markdown
Contributor

just disable NRF52_POWER_MANAGEMENT for all boards.

I've implemented this as a quick fix in #2377. After deciding on and implementing a proper solution this can be reenabled.

@entr0p1

entr0p1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor Author

I've been thinking about this more and based on what @recrof said I remembered we already have an auto shutdown voltage in the companion firmware (I think its in others now too?). Couldn't we basically drop this entire feature out of the codebase and just build on that to make the voltage configurable via the CLI?

No chemistries, wake, or lockouts to worry about and the code basically exists and just needs a pref added.

Thoughts?

@1nerdherder

Copy link
Copy Markdown

My thoughts after being on the 2088 adventure:
In a world where people are getting busier and reading less, I agree simpler is better.
The majority of users will not be concerned with this feature because they are using standard boards, generally with the one chemistry allowed. If they do go "custom" with an external solar battery charge controller, or some other adaptation, it will be too difficult for the firmware to know all the permutations (it would be a rather large table chasing innovation). So, those of us who are using advanced configurations, should be knowledgeable enough to change the defaults.
Simplifying to one parameter (the low voltage shutdown level - using zero to disable it completely) is a good start.
The only downside I can think of is that we lose the ability to tell the iOS/Android app what battery type it is so it can calculate percentage. However I have full confidence that someone smart will figure that one out at some point.

@TheSlowGrowth

Copy link
Copy Markdown

Regarding the app percentage display: The app could configure the battery chemistry for pecentage display purposes on the app level instead of polling it from the device. It's then saved locally in the app preferences. That way the device stays clean of any unnecessary settings; boot lock voltage can be configured freely by expert users and we can still have a sensible percentage display in the app.

@luigi311

Copy link
Copy Markdown
Contributor

looking at this it does look like this is trying to do a lot at once. Instead of trying to add battery chemistry on here i would instead look at building this on top of my battery chemistry implementation at #1176.

You could just do an ifdef for the different cell types and use that to set the minimum voltage either hard coded or perhaps even just fetch the last value in OCV_ARRAY as that should line up with 0% to the devices configured chemistry. In most cases though for Liion it will set it to 3.1v though instead of your proposed 3.0v if you take the OCV route.

@entr0p1

entr0p1 commented May 11, 2026

Copy link
Copy Markdown
Contributor Author

I understand the apprehension here, but I really want to get this one off my plate once and for all and put an end to the frustration and complaints. So we really need to make a call on what we want here.

If I distil down the various conversations on what people want, I can think of these options:

  1. Drop it entirely
  2. Drop the chemistry selection, leave two configurables: lockout voltage (which we probably shouls make the same setting as runtime shutdown voltage to keep simple), and wake REF for the voltage divider.
  3. Keep this version that I've posted which sows the seeds for a chemistry setting so that the app can use it later (this was the intent in addition to people asking for it to be configurable)

Its already opt-in (disabled by default) in this PR so that's implied.

What do we think?

@LennertVA

Copy link
Copy Markdown

Yes, this really should be pushed out the door, especially since not having it can (and has) cause(d) serious operational problems.

1 is not an option. 2 sounds good, will keep it simple and solves the core of the problem. 3 sounds equally good to me - but I'm in no position to judge whether it's a base which will have future use, or falls under YAGNI.

Regardless of whether it's 2 or 3, please get this merged 🙏

@luigi311

Copy link
Copy Markdown
Contributor

i think 2 makes the most sense to get this out quickly. It massively reduces the code change and if someone else wants to use this with a different chemistry they can just do a build with the voltage overriden to match their chemistry themselves until there is a better way merged in for battery chemistry management.

@1nerdherder

Copy link
Copy Markdown

Here is my $0.02
There has been a lot of good work done here - that merits inclusion into the code.
If we think about the situations that require this feature - they will be those who mostly know what they are doing, using less common boards with their own particular power configuration issues, or bypassing existing charging hardware with external power management boards - for which we can never accomodate all the permutations; therefore an approach like #3 will need more thought to consider how to handle all of those permutations. What I do like about #3 is that there is a declaration of the battery type that can be queried and acted upon when calculating charge % - we lose this in option 2 (meaning the iOS and Android apps will always report the incorrect battery % if not LiPo).
So, as others have said, If we go with #2, it is quick, flexible - but really should be accompanied by table of the two suggested settings for particular chemistries in the user documentation (particularly for LiFePO4). This should NOT require a custom firmware build and would release with the standard LiPo settings.
If we go with #3, people need to understand it is a first iteration and be invited to innovate toward something that equally simple to use. The "opt-in" flag that was mentioned, allows people to try it and provide valuable feedback or additional code or just leave it off (default).
Make sense?

@entr0p1

entr0p1 commented May 14, 2026

Copy link
Copy Markdown
Contributor Author

Great feedback folks, all makes perfect sense to me. So now it seems we've boiled down to option 2 or 3.

I put my "think like recrof" hat on for a moment and even though it does feed the app useful info about chemistry, it would be simpler for the firmware to let Liam hard-code the chemistry in the app. The reason I say that is that the percentage reading doesn't actually come from the firmware in the first place; its derived in the app.

That said it would probably be nice to have it there on the board so its just another piece of information to be interrogated and calculated more consistency by the various apps that now interface with these boards, but if having the chemistry selection is going to be the next stalemate I'd rather just rip it out. We could then have (as suggested) the shutdown voltage and wake divider ref as configurables, with a guidance table based on chemistry. Rather than trying to protect people from themselves I think it just needs to be a case of "here's the advice, ignore it at your own peril".

So.. basically option 2 I guess?

Apologies for the ping folks however I need the cavalry so we can put this to bed - @recrof @oltaco @ripplebiz do you have any strong opinions on which of the 3 options I mentioned is most favourable to you?

I'd love to get the fix merged before the next release.

@recrof

recrof commented May 14, 2026

Copy link
Copy Markdown
Member

@entr0p1 2. all the way.

@KPrivitt

KPrivitt commented May 16, 2026

Copy link
Copy Markdown
Contributor

Sorry for the late response and not exactly the answer you are looking for, but here are my 3 cents....

  1. Using the two voltages is essentially using a 3rd order polynomial with the first two coefficients as 0.

  2. The Battery Chemistry is essentially using all four coefficients but using the single name to describe them rather than the individual numbers.

A 3rd order polynomial can be used to fit ANY of the battery chemistries to within a 1% accuracy. Giving a fairly close approximation to ANY battery. This is what the applications actually need to display the percentage. A polynomial is also more efficient in terms of calculation time and storage space vs. a piece wise linear table (typically 10 points or option 2 which is only 2 points)

Apps actually need the polynomial rather than the type name which they then use to choose a look table (piece-wise linear) or ideally the four polynomial coefficients.

So my vote is #2.5 which is in order of priority is:

#2 with coefficients of 0, 0, b, -b/a. y = ax + b

#3, this is what Apps "really" need (yes the two points does this but with a very low accuracy). But a polynomial is what they actually need to create a single piece of code that covers ALL batteries, all it needs is the coefficients.

LiFe = aXexp3 + bXexp2 + cX + d
LiPo = a1Xexp3 + b1Xexp2 + c1X + d2
LIon= a2Xexp3 + b2Xexp2 + c2X + d2
xxx = a3Xexp3 + b3Xexo2 + c3X + d3

As NerdHerder said external charge controllers can never be accommodated so let's just do internal batteries where the voltage can be measured.

The default should be "on" with the LIon coefficients.

The CLI has an option to turn it "on/off" with the four coefficients.

set batterytype off 1 2 3 4

set batterytype on 1 2 3 4

Set the shutdown voltage at 2% and the turn on at 5% (this is to give it a little power to start transmitting, which draws more)

This is simple and covers most bases...

@KPrivitt

KPrivitt commented May 16, 2026

Copy link
Copy Markdown
Contributor

Here is some data showing the improvement with a higher order model.

https://www.sba.org.br/Proceedings/SBAI/SBAI2017/SBAI17/papers/paper_29.pdf

Figure 6 shows that the Model Simulation Error is less than 3% for a 3rd order model and 11% for a first order model.

So for two additional coefficients you get an 8% improvement in "accuracy". This seems worth it.

This is way beyond a simplistic model but:

A static model cannot adjust for temperature or number of charge cycle affect. Some devices have a temperature sensor and the charge cycles can be counted and either could be added to improve the accuracy. But 3% should be plenty good enough.

I hope you consider option 2.5

@IoTThinks

IoTThinks commented May 19, 2026

Copy link
Copy Markdown
Contributor

I choose Option 2.

Follow KISS. Simplicity works best.

@1nerdherder

Copy link
Copy Markdown

My use case is the Solar Xiao board (from FloodWave Systems) with LiFePO4 batteries.
I think Option #3 makes it simple and easy to configure for its chemistry - leaving a simple framework that anticipates future battery chemistry options - and gives a way to query the node for its battery type.
Let's go for it with #3!

@entr0p1

entr0p1 commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

Big thank you @1nerdherder for stepping in to get something in the meantime, much appreciated :)

I've finished the first rough cut of the code and have some pre-compiled copies based on 1.16 for the Xiao nRF52840, RAK4631 and Heltec T114.

I have only flashed the Heltec T114 and RAK4631 thus far. They boot fine, the values can be set, and so far no incorrect boot locks.

I will get the boards on a lab bench today at some point and test the lockout and subsequent recovery.

For now, here's the builds I'm working with. These are very likely to change before I push the code into the PR, so if you want to hold out for the final, do so.

heltec_t114_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta1.zip
Xiao_nrf52_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta1.zip
RAK_4631_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta1.zip

To configure the lockout voltage, you need to run:

set pwrmgt.lvshutdown <mV>

E.g. set pwrmgt.lvshutdown 3000 will lock out at 3.0V. Setting to 0 disables lockout and it is disabled by default.

To configure the LPCOMP REFSEL for booting the board back up from lockout when the battery voltage increases, you need to run:

set pwrmgt.lpcompwake <0-16>

The setting values correspond to the following REFSEL values:
0 - disabled
1 - 1/8
2 - 2/8
3 - 3/8
4 - 4/8
5 - 5/8
6 - 6/8
7 - 7/8
8 - External AREF
9 - 1/16
10 - 3/16
11 - 5/16
12 - 7/16
13 - 9/16
14 - 11/16
15 - 13/16
16 - 15/16

More detail on what these mean is available here: https://docs.nordicsemi.com/r/bundle/ps_nrf52840/page/lpcomp.html

As a quick reference point, on the RAK4631 I've used 5 for both Li-ion and LFP. This is purely based on math and not tested yet, will likely need to be revised.

The boards will still recover when external power is introduced via USB or Solar (I.e. VBUS in) as before.

@entr0p1

entr0p1 commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

Request for feedback from the core dev team (and of course the very patient testers along for the ride) - is there appetite here to tie this value to the runtime low voltage shutdown so it is both configurable to the user via CLI, and there is one setting to configure the low voltage threshold that is specifically set by the user?

My thinking is if we want to do this, now is the time. We don't want to surprise people with it later by and having one unified setting for both makes it very clear where the threshold is coming from. This change is already long awaited and expected so there's ample attention on the details, its already disabled by default, and it just might save a few more browned out repeaters.

If we want it, its trivial at this point for me to add it in as well. The provisions were already there in the code for it.

@entr0p1

entr0p1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

I've now tested the lockout and subsequent LPCOMP recovery on the Xiao nRF52840 and am stoked to announce it works as intended.

I set the lockout to 3.0V and the REFSEL to wake around 3.3-3.7V. I connected a power supply to the VBAT rail, ran the board down to about 2.9V and rebooted. Confirmed it did not boot. Then I slowly raised the voltage up to about 3.7V and the board booted. The CLI output shows LPCOMP is what booted the board and boot lock is what powered it off.

I'll test some more boards and thresholds to ensure everything is robust before pushing the commit.

IMG_20260608_035135 IMG_20260608_103533

@1nerdherder

1nerdherder commented Jun 8, 2026 via email

Copy link
Copy Markdown

@1nerdherder

Copy link
Copy Markdown

I have successfully loaded the Xiao code and was able to get and set pwrmgt.lpcomp and pwrmgt.lvshutdown parameters via config.meshcore.io on USB. The older parameters (pwrmgt.batt) are no longer accepted.

@entr0p1

entr0p1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Alright, further testing has shown the board is pulling more power than it should in the "SYSTEMOFF" state. Its definitely "powered off", but just flagging I'm aware and looking into it.

I will be putting a table of the REFSEL values and rough voltage ranges in the documentation for the power management module, but here is a rough cut in the meantime:

lpcompwake Hardware REFSEL Fraction RAK/R1 Neo (1.73) GAT562 (1.75) XIAO/SenseCAP (3.0) Heltec 4.90 Heltec T1 (4.916)
0 - Disabled Disabled Disabled Disabled Disabled Disabled
1 0 1/8 0.65-0.71 V 0.66-0.72 V 1.12-1.24 V 1.84-2.02 V 1.84-2.03 V
2 1 2/8 1.30-1.43 V 1.31-1.44 V 2.25-2.47 V 3.68-4.04 V 3.69-4.06 V
3 2 3/8 1.95-2.14 V 1.97-2.17 V 3.38-3.71 V 5.51-6.06 V 5.53-6.08 V
4 3 4/8 2.59-2.85 V 2.62-2.89 V 4.50-4.95 V 7.35-8.09 V 7.37-8.11 V
5 4 5/8 3.24-3.57 V 3.28-3.61 V 5.62-6.19 V 9.19-10.11 V 9.22-10.14 V
6 5 6/8 3.89-4.28 V 3.94-4.33 V 6.75-7.42 V 11.03-12.13 V 11.06-12.17 V
7 6 7/8 4.54-5.00 V 4.59-5.05 V 7.88-8.66 V 12.86-14.15 V 12.90-14.19 V
8 7 ARef ARef ARef ARef ARef ARef
9 8 1/16 0.32-0.36 V 0.33-0.36 V 0.56-0.62 V 0.92-1.01 V 0.92-1.01 V
10 9 3/16 0.97-1.07 V 0.98-1.08 V 1.69-1.86 V 2.76-3.03 V 2.77-3.04 V
11 10 5/16 1.62-1.78 V 1.64-1.80 V 2.81-3.09 V 4.59-5.05 V 4.61-5.07 V
12 11 7/16 2.27-2.50 V 2.30-2.53 V 3.94-4.33 V 6.43-7.07 V 6.45-7.10 V
13 12 9/16 2.92-3.21 V 2.95-3.25 V 5.06-5.57 V 8.27-9.10 V 8.30-9.13 V
14 13 11/16 3.57-3.92 V 3.61-3.97 V 6.19-6.81 V 10.11-11.12 V 10.14-11.15 V
15 14 13/16 4.22-4.64 V 4.27-4.69 V 7.31-8.04 V 11.94-13.14 V 11.98-13.18 V
16 15 15/16 4.87-5.35 V 4.92-5.41 V 8.44-9.28 V 13.78-15.16 V 13.83-15.21 V

For the Xiao, LFP is a bit awkward. You can err on the side of caution and set your REFSEL to 3/8 (set pwrmgt.lpcompwake 3) which would ensure the battery is almost completely charged, but there is a chance it may never pull the voltage high enough to trigger the wake.

The next option would be 5/16 (set pwrmgt.lpcompwake 11), but that could boot the board too early and run it dead pretty quickly. In either case, it's best to test out the settings on your equipment and see how it behaves.

@entr0p1

entr0p1 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Howdy folks,

Quick update on this - I'm still working on the code, particularly around the shutdown process to ensure it is as robust and consistent between boards as possible. I've managed to make a lot of it less board-specific which is great; less maintenance overhead, less duplication of code, less places for things to go wrong.

I should have the next beta available for you all some time this week/next weekend.

@entr0p1

entr0p1 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

Setting this back to draft as the commit is nearing completion.

We will need testers for as many boards as possible to make sure things work right. I have ordered a few boards that I don't yet have to try and hit as much of the testing as I can.

Hang in there guys, its nearly done :)

@entr0p1
entr0p1 marked this pull request as draft June 21, 2026 13:20
@IoTThinks

Copy link
Copy Markdown
Contributor

How is this going?
I can help in testing.

I have Rak4631, T114, T096, T-echo Lite, Xiao Nrf52 and Wio L1 pro for NRF52 type.

@entr0p1

entr0p1 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

How is this going? I can help in testing.

I have Rak4631, T114, T096, T-echo Lite, Xiao Nrf52 and Wio L1 pro for NRF52 type.

Your sixth sense is impeccable - just finished it this afternoon. I have one annoying quirk to solve around the sensecap solar, but that shouldn't be difficult. I'm flashing some boards to do a preliminary test before sharing it.

I expect I'll have a build for you within a couple hours.

@entr0p1

entr0p1 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

@IoTThinks First cab off the rank - Lilygo T-Echo Lite. Tested and confirmed the shutdown and subsequent wake works.

lilygo_techo_lite_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta2.zip

To configure:

set pwrmgt.lvshutdown <mV>
set pwrmgt.lpcompwake <value>

Reference list of the thresholds you can use for the LPCOMP value:

lpcompwake 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
T-Echo Lite (2.0) Disabled 0.75-0.82 V 1.50-1.65 V 2.25-2.47 V 3.00-3.30 V 3.75-4.12 V 4.50-4.95 V 5.25-5.77 V ARef 0.38-0.41 V 1.12-1.24 V 1.88-2.06 V 2.62-2.89 V 3.38-3.71 V 4.12-4.54 V 4.88-5.36 V 5.62-6.19 V

I used a value of 13 for pwrmgt.lpcompwake, which triggered the wake at the high end of the range (around 3.7V).

I'll be testing the T114 next and will post the beta build once it all works.

Edit: fixed the file name. Mistakenly labelled RAK4631.

@entr0p1

entr0p1 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Updated builds - this drops the LPCOMP hysteresis threshold as it might be a bit heavy-handed for some of the wider dividers (e.g. a lot of heltec boards use ~4.9).

Adding the Heltec T114 as lockout and recovery tests have passed. pwrmgt.lpcompwake set to 2 for the T114 and the wake occurred at ~4.15V.

heltec_t114-nodisplay_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta3.zip
lilygo_techo_lite_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta3.zip

@recrof

recrof commented Jul 5, 2026

Copy link
Copy Markdown
Member

Updated builds - this drops the LPCOMP hysteresis threshold as it might be a bit heavy-handed for some of the wider dividers (e.g. a lot of heltec boards use ~4.9).

can you please share rak4631 build as well? uArt mesh motherboard is pretty popular in Czech republic and they would want to test it with LTO cells.

@IoTThinks

Copy link
Copy Markdown
Contributor

@entr0p1 May I know why the numbers are not linear from 1 to 16?
image

@entr0p1

entr0p1 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

can you please share rak4631 build as well? uArt mesh motherboard is pretty popular in Czech republic and they would want to test it with LTO cells.

@recrof Sure thing, its next in queue. Just getting the shutdown process right for it and running a bench power supply test before I share it.

May I know why the numbers are not linear from 1 to 16?

@IoTThinks its the way Nordic have them laid out, unfortunately. It does make it challenging to find the "sweet spot" for some boards on particular chemistries. Here's the documentation reference: https://docs.nordicsemi.com/r/bundle/ps_nrf52840/page/lpcomp.html?section=register.REFSEL

@IoTThinks

IoTThinks commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@entr0p1 I believe the first and the second parts is about voltage steps 1/8 or 1/16.
image

If we use 1/16 for finer steps, then we can only care about the second parts.
Or we can care about 12 or 13.
NRF52 can work fine at 2v. Lipo and protected board will cut off at 2.5v.
So 12 (2.6 to 2.8v) may be a sweet voltage to wake up.
13 (3.3 to 3.7) can be the default value as they are very safe voltage.
8-11 can be for LTO.

What do you think?
image

@entr0p1

entr0p1 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@IoTThinks I think you're on the right track, just a few caveats worth mentioning which I've listed below.

  1. The REFSEL is going to be different board-to-board - its calculated based on the voltage divider relative to the nRF's VDD_sys input. This is why we need to keep the divider powered during SYSTEMOFF; so the regulator is alive and giving us reference voltage to know when to trigger the reset (the "boot" is actually a reset).
    The math is:
    VBAT_wake = REFSEL_fraction x VDD_sys x divider_scale
    Where VDD_sys is approx 3.0-3.3V (regulator output during SYSTEMOFF) and divider_scale is the board's voltage divider scale factor.

  2. The board might run (barely) as low as ~2V, but your batteries will be as good as cooked if you draw down harder on them when they're that low (unless they're LTO of course). Even with the protection kicking in at 2.5V, they're essentially at 0% at that point and one TX from the radio would pull enough current from the battery to drag the voltage down enough to brownout the 3V3 rail, wedge the board, and require a physical reset (and a corrupt flash if you're really unlucky).
    You might know from your own tests but for others to see (all readings taken at ~3.8V supply):

  • At idle, the boards draw ~5-12mA (generally around 9mA).
  • A good board that lets us power off peripherals fully should draw no more than 2mA in SYSTEMOFF state.
  • On TX, it ramps up to ~25mA (or more).
  1. The threshold may actually be lower/higher than what the REFSEL says (due to how it gets read at the nRF as explained in point 1). Its good to do your own tests and see where the board kicks over. I found I got different results with actual cells (due to how the charge/discharge curve works) vs lab power supply tests.

For example, the Heltec T114 shows a range of 3.68-4.04 V at lpcompwake setting 2 (see below). When I stepped the voltage up, the board didn't actually wake until crossing ~4.15V (according to the power supply).

lpcompwake 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Heltec T096/T114 (4.90) Disabled 1.84-2.02 V 3.68-4.04 V 5.51-6.06 V 7.35-8.09 V 9.19-10.11 V 11.03-12.13 V 12.86-14.15 V ARef 0.92-1.01 V 2.76-3.03 V 4.59-5.05 V 6.43-7.07 V 8.27-9.10 V 10.11-11.12 V 11.94-13.14 V 13.78-15.16 V

@IoTThinks

Copy link
Copy Markdown
Contributor

@entr0p1 I see.
However, this makes the approach not general for current and future NRF52 boards since the lpcompwake is not the same for all boards.

No idea why all esp32 boards are just so trivial on this aspect.
They can keep bootloop until they succeed booting when the voltage is higher.

NRF52 should be similar.

@entr0p1

entr0p1 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@IoTThinks Technically we can allow it to reboot loop but it carries the risk of flash corruption and just generally "isn't good" as a practice. At least with the board fully powered down, it can recoup the batteries and not sporadically join and leave the mesh.

For those that really want to commit, they can use external low voltage cutoffs (similar to yourself), or a hardware watchdog. These can hold the reset pin closed when the voltage is too low and release them when it normalises. I know of people using them on ESP32 boards for other projects that swear by them.

At least with LPCOMP, even if finicky, we have a choice to use it or not to :)

RAK4631 build coming shortly. I've rolled the firmware, just testing it now.

@IoTThinks

Copy link
Copy Markdown
Contributor

@entr0p1 Is there anyway we can have a correct lpcompwake via "self-learning".
So a board can learn and set a correct lpcompwake during its normal run.

I think many users will not know what should we set for lpcompwake.
And manually setting lpcompwake will not scalable for current boards and future boards in the market.

@entr0p1

entr0p1 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@IoTThinks I like the idea, but if I'm honest I don't think it would be reliable and it would be chunky code-wise. This was similar to what I had on the initial version of this PR; user selects a chemistry and we have a predefined REFSEL value for that chemistry. Having it learn would mean watching the thresholds and knowing what "0%" vs "100%" actually looks like.

The "not knowing what to set" concern is valid, but I think this will likely be a setting used by more advanced operators. For example, I'll be using it extensively on hard to reach boards. At least when the batteries are going down, I know I can forcibly reboot to lock the board in a safe state and it will bring itself back when charge levels are stable.

That said, I'll be providing a table of the boards in the docs with the rough voltage thresholds to pwrmgt.lpcompwake mappings, as well as suggested settings for common chemistries (Li-Po, LFP, LTO). This will take some finessing over time from people actually running the boards. I actually bought quite a few different types just to test this as best I can beforehand.

Not all boards will work for all chemistries as the REFSEL won't always land in a "sweet spot", but it's not worth throwing the baby out with the bathwater over either. I still think there's good value in having the LPCOMP option for those that want it or don't have the means/inclination to go the hardware watchdog approach.

@entr0p1

entr0p1 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@recrof here's the RAK4631 build. Since the SX1262 doesn't have a hard power switch via pin, I used an SPI sleep command (same as radiolib does). This got the SYSTEMOFF current draw down from 5mA to being so low that the power supply doesn't register a draw (0.000A shown). Very happy with it.

Here are the lpcompwake values for it. I used 5 in my test with a low voltage shutdown of 2900mV. The board booted at ~3.28V.

lpcompwake 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Hardware REFSEL - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Fraction Disabled 1/8 2/8 3/8 4/8 5/8 6/8 7/8 ARef 1/16 3/16 5/16 7/16 9/16 11/16 13/16 15/16
RAK/R1 Neo (1.73) Disabled 0.65-0.71 V 1.30-1.43 V 1.95-2.14 V 2.59-2.85 V 3.24-3.57 V 3.89-4.28 V 4.54-5.00 V ARef 0.32-0.36 V 0.97-1.07 V 1.62-1.78 V 2.27-2.50 V 2.92-3.21 V 3.57-3.92 V 4.22-4.64 V 4.87-5.35 V

rak4631_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta3.zip

Edit: Tomorrow will be Xiao nRF52840 as I know that will likely be the next eagerly awaited.

@entr0p1

entr0p1 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

As it turns out, that little SX1262 sleep trick works very well even on boards that can toggle the SX1262_POWER_EN pin. All of these now read 0.000mA current when in SYSTEMOFF and still recover perfectly.

Xiao added. Tested with pwrmgt.lpcompwake at 3 and booted at ~3.6V.

lpcompwake 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Hardware REFSEL - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
RAK/R1 Neo (1.73) Disabled 0.65-0.71 V 1.30-1.43 V 1.95-2.14 V 2.59-2.85 V 3.24-3.57 V 3.89-4.28 V 4.54-5.00 V ARef 0.32-0.36 V 0.97-1.07 V 1.62-1.78 V 2.27-2.50 V 2.92-3.21 V 3.57-3.92 V 4.22-4.64 V 4.87-5.35 V
T-Echo Lite (2.0) Disabled 0.75-0.82 V 1.50-1.65 V 2.25-2.47 V 3.00-3.30 V 3.75-4.12 V 4.50-4.95 V 5.25-5.77 V ARef 0.38-0.41 V 1.12-1.24 V 1.88-2.06 V 2.62-2.89 V 3.38-3.71 V 4.12-4.54 V 4.88-5.36 V 5.62-6.19 V
XIAO/SenseCAP (3.0) Disabled 1.12-1.24 V 2.25-2.47 V 3.38-3.71 V 4.50-4.95 V 5.62-6.19 V 6.75-7.42 V 7.88-8.66 V ARef 0.56-0.62 V 1.69-1.86 V 2.81-3.09 V 3.94-4.33 V 5.06-5.57 V 6.19-6.81 V 7.31-8.04 V 8.44-9.28 V
Heltec T096/T114 (4.90) Disabled 1.84-2.02 V 3.68-4.04 V 5.51-6.06 V 7.35-8.09 V 9.19-10.11 V 11.03-12.13 V 12.86-14.15 V ARef 0.92-1.01 V 2.76-3.03 V 4.59-5.05 V 6.43-7.07 V 8.27-9.10 V 10.11-11.12 V 11.94-13.14 V 13.78-15.16 V

Full list of current files:

heltec_t114-nodisplay_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta4.zip
lilygo_techo_lite_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta4.zip
rak4631_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta4.zip
xiao_nrf52_repeater-v1.16.0-DEV-pwrmgt-v2.2-beta4.zip

@entr0p1

entr0p1 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Just a heads up here, dev has diverged way too far from where I started with this PR. I'll be opening a few smaller ones in anticipation of the bigger change, otherwise the maintainers will hunt me down and tar + feather me for the size of the PR :)

@1nerdherder

Copy link
Copy Markdown

Hello @entr0p1|
Just checking in to see where this is.
I have LiFePO4 battery Xioa boards that are waiting to get fielded for whatever the next intermediate step is that allows me to get more life out to the batteries (they are lower voltage than LiPo)
Any updates? I can help test if you have anything.
Thanks!

@IoTThinks

Copy link
Copy Markdown
Contributor

I will use another approach.

To deepsleep at 3.0v and wakeup every hour to check voltage.

Deepsleep takes less than 10uA and can stay for months.

@HPunktErbert

Copy link
Copy Markdown

(Your posting form 8. Jun 2026)
One firmware file is for the RAK4631 and the other is for the Seeed Studio Xiao nRF52 board. Xiao_nrf52_repeater_firmwarePR2088.zip RAK4631_repeater_firmwarePR2088.zip

@1nerdherder ,
just have registered to github to ask you whether you would create these two files again, basing on the new 1.17 release?
Even if it seems to be a "simple operation": I must admit I'm not able to do it because im completely new in programming.

I really appreciate your former work and have it working successful im my local node.

THX & regards!

@1nerdherder

Copy link
Copy Markdown

@HPunktErbert - Hello.
I am waiting to find out what the status of this is - some of the recently made improvements to the code are good, but the mechanisms through which the CLI turns them on/off seem to be missing. if @entr0p1 could advise the list of required PRs that make it work - I could give it a go. Unfortunately I don't think what is here now will create a build that works.
I'm not trying to be negative, so please don't ban me for sharing my opinion. It truly seems a shame - those of us working to use different battery chemistries to lower the potential battery fire risk of field deployed nodes should be getting more attention. Seems there just aren't enough hands to the keyboards to give this the priority is deserves. This would be a particularly meaningful change to MeshCore - expanding our choice of batteries and getting full utilization from them. The author of the code has done good work and it deserves its due support - or an explanation of what other approach is going to expand our use of different batteries.

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.