nRF52840 Power Management Stage 1 v2.1 - Boot lockout fix#2088
Conversation
e3c0529 to
d5f6c76
Compare
|
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
d5f6c76 to
e32e30b
Compare
|
Tested on a couple of boards now without issues so far. Ready to be reviewed. |
|
Does setting pwrmgt.bootlock to off also prevent the low voltage shutdown? or is it only for boot? |
|
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: |
|
@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. |
100% agree.
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:
Thanks! |
|
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. |
I've implemented this as a quick fix in #2377. After deciding on and implementing a proper solution this can be reenabled. |
|
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? |
|
My thoughts after being on the 2088 adventure: |
|
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. |
|
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. |
|
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:
Its already opt-in (disabled by default) in this PR so that's implied. What do we think? |
|
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 🙏 |
|
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. |
|
Here is my $0.02 |
|
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. |
|
@entr0p1 2. all the way. |
|
Sorry for the late response and not exactly the answer you are looking for, but here are my 3 cents....
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 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... |
|
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 |
|
I choose Option 2. Follow KISS. Simplicity works best. |
|
My use case is the Solar Xiao board (from FloodWave Systems) with LiFePO4 batteries. |
|
There are two distinctly different aspects that need to be addressed with this PR.
Both of these can be accomplished with just the current battery voltage as an input to a function. The solution needs to be enabled/disabled via a CLI command. Some indication of the battery chemistry needs to be provided. The default chemistry type will be Liion/LiPo. The only inputs I have seen is that providing a “battery” type is not a good direction since new battery types are being developed that may have different voltages and provide better capacity in the future. The solution needs to be forward looking, but a continuously growing table is not a scalable solution. Solution #2 is only a two-point solution (a 1st Order Polynomial) and was favored because it was “simple”. But this simplicity is short lived and doesn't address all the current needs and WILL require future modifications, why not use a 3rd Order Polynomial which is “future proof” without much additional complexity. I have not seen any comments regarding the constraints or requirements of the Apps. Some consideration should be given to this. Can someone contact them and point them to this thread? Current Apps have used a two-point linear solution and a table with capacity percentage vs. voltage. I know this because I have recorded the voltage/capacity values for a battery using two different Apps. I could see that a linear solution had an 11% difference in the middle of the curve, while a table matches what is provided by the battery manufactures. So, Apps that used a table were much more accurate. The problem with using a table is that they are very inefficient in terms of storage requirements: LiFe Capacity vs. Voltage Chart This is much more efficiently expressed as a polynomial using just four float values. Liion/LiPo battery: y = 4E-06x3 - 0.0007x2 + 0.0389x + 2.5943 A polynomial is a continuous curve and no extrapolation is needed between points. The bootlock voltage can be set using the 10% value, the only criterion is that sufficient remaining capacity needs to allow for a graceful shutdown. The wake voltage can be set at 15, 20 or 25%, the only criterion is how long to wait for the unit to charge. It will take some time to charge up to this value, and a higher value will take longer to reach. For the Apps a polynomial is a much better solution than multiple tables since it only needs to be written once, the storage is much more efficient (it’s not an endless list of new entries), and future battery chemistries are easily accommodated by simply providing updated coefficient values. The Apps can be passed the chemistry type via a uint_8 value (Other = -1, Liion/LiPo = 0, LiFe = 1, xxx =2, yyy = 3 etc.) These can be stored in the firmware and used with the already passed in voltage value. If a negative value is passed the App will know that it is a custom coefficient or its current solution is not contained in the local storage (it does not know what 4 = ?), but it can request the user to input the four values (or update the firmware in a future rev with additional entries). Solution #2 is not forward looking, is only 50% more efficient, and is not accurate in the middle of the curve. It will require a future update and it somewhat incomplete (Apps will have to guess the battery type from the two values?) The type is not really needed (only the polynomial, but it is a simple way to provide an index into a battery type table. Solution #3 does not address an Apps need for scalability, future looking and storage efficiency. A CLI command can be added to input the four coefficients and store them. Future battery chemistries are accommodated. A 3rd order polynomial addresses all of these inadequacies. From an Architectural perspective this is the preferrable solution over #2 or #3. |
|
The bootlock voltage is also VERY important for companion nodes. Lithium batteries should not be fully discharged because deep discharge causes permanent chemical damage, capacity loss, and can even make the cell unsafe to recharge. The core issue is that lithium‑ion chemistry becomes unstable when voltage falls below its safe operating range. Deeply discharged lithium cells are more prone to short circuits, swelling, or catastrophic failure if recharged improperly. Battery fires are a well known failure mode of Liion and LiPo batteries. LiFePO₄ (LiFe) batteries are dramatically less prone to fires than typical lithium‑ion (Li‑ion/LiPo) chemistries. Most lithium packs include a Battery Management System (BMS) that shuts the battery off around 2.5–3.0 V to prevent damage. If the cell goes below this, the BMS may refuse to recharge it at all. |
That's why it's important to use protection circuits with the batteries.. don't rely on software! Most of pre-made pouch cell batteries already include undervolt and overvolt protection circuits. if you DYI your node, include it |
|
I've been watching the discussion on this topic.With due respect to all involved - I want to push back a little. |
It's not that simple. we need to be sure that added features will be:
we can use UI on the app to give user ability to choose values that represent the chemistry needed. we really don't want this in the firmware. that's why most of the devs chose option no. 2. |
|
Great - so let's get the first iteration of #2 onto the to-do list. |
|
I vote option #0. Leave it alone. Adding a CLI disable and two override settings is making the code worse. |
that doesn't fix the issues people are having with other chemistries. it needs to be optional and disabled by default. |
That kicks people who have acute problems now due to shortcomings in the firmware, back to square one.
I prefer worse code that works over code that is better according to some metric unknown to me, but causes dead repeaters. ✌️ |
|
To be direct, its going to be option 2. We need to develop features that are flexible to most, rather than ideal for some. And maintainable. Its already underway and should be finished some time this week or next, depending on how testing pans out.
Agreed. Removing it entirely would be throwing the baby out with the bath water. Selectable chemistries is easier for the user, but starts to become unwieldy to maintain in firmware. If Liam so desires, he might elect to add a nice UI in the app down the track. In the meantime, we can have some guidance in the docs on what thresholds are appropriate for the most common chemistries.
This is simply not an option. While well-intended, this has caused far too many issues in its current state and must be iterated. The settings aren't overrides, they are the configuration. Right now, users are forcibly shut down at a hard coded voltage threshold (with some exceptions). The change will be to:
The board will continue to self-recover when external power is detected via VBUS (USB, Solar input) as it currently does. This includes cleaning out any superseded code from v1, such as the static lockout voltage that is hard-coded. |
|
Awesome. My LiFePO4 repeaters are looking forward to it! |
|
While waiting for The official dev updates, I took a swing at merging PR2088 to the latest dev source. The AI helper on platform.io made some reasonable suggestions for resolving conflicts - but the CLI commands are still the intermediate ones, not the final ones proposed for outcome #2 (see the previous comments on this thread). So, right now the CLI command "get pwrmgt.batt" returns "lfp," so my Solar Xiao + advanced board is set to LiFePO4). The documentation for these commands are also mentioned earlier in the comment threads. My apologies for the confusion - I just wanted to respond to others who asked for a respin of the V14 code that had this PR. When it officially releases, the CLIs will change. |
|
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 To configure the lockout voltage, you need to run: E.g. To configure the LPCOMP REFSEL for booting the board back up from lockout when the battery voltage increases, you need to run: The setting values correspond to the following REFSEL values: 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. |
|
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. |
|
Will you be posting a table of suggested settings for different chemistries (because we didn’t go with path #3)?I’ll be getting some time later this evening to give it a go.On Jun 7, 2026, at 17:55, Dom ***@***.***> wrote:entr0p1 left a comment (meshcore-dev/MeshCore#2088)
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.jpg (view on web)
IMG_20260608_103533.jpg (view on web)
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
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. |
|
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:
For the Xiao, LFP is a bit awkward. You can err on the side of caution and set your REFSEL to 3/8 ( The next option would be 5/16 ( |
|
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. |
|
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 :) |


Improvements:
Fixes: