Fix: Use a lookup table & interpolation to better estimate remaining battery capacity
The current battery capacity estimate uses a linear approximation to estimate the remaining battery capacity. This is computationally very efficient, however, the estimate is very inaccurate once below 60%.
This PR uses a small table of bounded functions to provide a more accurate estimate of remaining capacity.
The original data to create the estimate was taken from here: https://blog.ampow.com/lipo-voltage-chart/
The accuracy of the functions (in relation to the lookup chart least) can be seen below:
In terms of testing I've used a Python version of the algorithm to validate the behaviour. I am also running the change on my daily driver keyboard.
Adding a little to the data/numbers on this: If a search is done for "lipo discharge lookup chart" in Goole/DuckDuckGo image search these numbers keep coming up or numbers that are within a few millivolts of those that I've used. So long as the discharge rate is substantially below C (most charts show 0.2C) then the shape and values are very consistent.
Wonderful, thanks for that.
Is the testing something that usually handles itself or should I try to recruit people to test or…?
I put a message in the testing channel on Discord, but not sure if anyone has seen it.
@MickiusMousius Could you rebase this onto the tip of main or merge the tip of main into it? I think there were some issues with the GitHub actions that caused the checks to fail, which aren't related to your change, and the recent changes on main should fix that.
Done
If anyone would like to help validate whether this does improve things, I wrote a Windows program to record and graph battery levels over time: https://github.com/joelspadin/BleBatteryRecorder
To test this PR, first load software that does not include this PR and record the battery going from a full charge to empty. Then, load software that does include this PR and repeat. Graph the results. If we can confirm that the second line is more linear than the first, then we can merge this.
It may be not a good idea to take random data from a site for this, since the battery type and discharge method can be different. A while ago I graphed data from discharging a battery with constant current and constant power (like a buck regulator), with a more common li-ion batterie rather than lipo, which can make a significant difference.
| Discharge curve using linear regulator | Discharge curve using buck regulator |
|---|---|
@sctanf Sorry for the slow reply, suffice to say it's been a busy few months. I do agree that the optimal solution here would be to log the energy consumption from a typical set of batteries with the same power profile as a typical ZMK keyboard to find the most accurate "common curve".
That said, I am also a firm believer in the idea of aiming to make things better with a "perfect" end goal being easier to reach as a result.
Personally I do not have the tools to record this profile (or the time), however, I decided that finding the a common profile for the most common chemistry and then implementing a solution that allowed for a better curve later is a step along the path to "perfect".
If you're able to supply a more representative discharge curve using the most common parts (controller, battery size & chemistry etc) that would get things much closer to perfect IMO. I imagine most people would welcome that (I certainly would).
My biggest concern is that we don't yet have any data that says this is better than the linear approximation. I do think using a lookup table is an improvement since it will let us use any piecewise linear function we want, but I want to make sure this new function isn't worse than what we have already.
Anecdotally I suspect that it is “equivalent”. Overall it felt better to start off, but the end of the curve is still quite poor.
The final 10-15% of charge lasts more than a week on my work keyboard.
The first 10% lasts a few days at most (better than before, but not great).
EDIT: Thinking about this, I've been testing on the SuperMini boards, I might see what happens when I use a nice nano controller instead. Hopefully this coming weekend I'll have some time to build a new board with a nice nano controller.
@joelspadin I've tested with a nice nano controller, the difference compared to a supermini is not significant in my opinion. I'm happy to purchase a tool to record the battery over time.
However, I'd like the following features:
- Able to log without being attached to a computer
- Able to record both voltage & current (I could log the voltage drop across a small resistor too I guess)
Do you have any recommendations?
@sctanf If you've got any suggestions that would be welcome too.
https://www.nordicsemi.com/Products/Development-hardware/Power-Profiler-Kit-2 is probably the best way to monitor power usage, but I think it does still require the profiler be connected to a computer. (It's also a bit expensive. I have one myself, but I'd need to get a new battery to test this well, since all my batteries under 500 mAh are very dead. Probably also would want to test on a variety of batteries.)
I have a few batteries that are all new and unused, at least the more common sizes used by splits like the Corne and Sofle anyway (e.g 301230, 801230).
I looked at the PPK2 but could not tell if it also recorded voltage when in amp meter mode. If it can I’ll buy one as it’ll be handy for a few upcoming projects anyway. Do you know if it also logs voltage in amp meter mode?
I’ll need to get my hands on a computer I can leave logging. I suspect my work may have some NUCs collecting dust on a shelf I can borrow for a few weeks.