frame.battery_level() should give the battery's current value in percent, but instead gives wildly varying numbers. The numbers returned do correlate with the battery level. For example, over time, we might get readings like 81.0, 79.0, 80.0, 82.0, 77.0, 80.0, 78.0, etc. The general trend is downward and the values give a rough ballpark estimate of the actual battery level, but they are not at all user friendly.
LIKELY SOURCE
It appears the impercision in the battery readings stems from readings on the nRF SoC. We see that in 2 places in the codebase:
/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts.
*
* @details The calculation is based on a linearized version of the battery's discharge
* curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and
* is considered to be the lower boundary.
*
* The discharge curve for CR2032 is non-linear. In this model it is split into
* 4 linear sections:
* - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV)
* - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV)
* - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV)
* - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV)
*
* These numbers are by no means accurate. Temperature and
* load in the actual application is not accounted for!
...
Which attempts to apply the nRF logic to the Frame.
(I also don't think the Frame uses a CR2032 battery, so the piecewise function recommended for the nRF would likely need to be adjusted regardless)
RECOMMENDATION
A good start for this issue might be to store actual voltage readings in a variable, average the raw data to bring out the general trends while ignoring the noise of load and environment, Then apply whatever transforms are needed to that raw value. It would also be nice to expose the raw readings in a raw_battery_mv method or the likes for debugging.
To give a bit more description on this:
PROBLEM
frame.battery_level()
should give the battery's current value in percent, but instead gives wildly varying numbers. The numbers returned do correlate with the battery level. For example, over time, we might get readings like 81.0, 79.0, 80.0, 82.0, 77.0, 80.0, 78.0, etc. The general trend is downward and the values give a rough ballpark estimate of the actual battery level, but they are not at all user friendly.LIKELY SOURCE
It appears the impercision in the battery readings stems from readings on the nRF SoC. We see that in 2 places in the codebase:
https://github.com/brilliantlabsAR/frame-codebase/blob/90b71a8594a16a38b69f05d2aaedda87b9c49d01/libraries/nrf5sdk/util/app_util.h#L1256 Which states:
And: https://github.com/brilliantlabsAR/frame-codebase/blob/90b71a8594a16a38b69f05d2aaedda87b9c49d01/source/application/lua_libraries/system.c#L116
Which attempts to apply the nRF logic to the Frame. (I also don't think the Frame uses a CR2032 battery, so the piecewise function recommended for the nRF would likely need to be adjusted regardless)
RECOMMENDATION
A good start for this issue might be to store actual voltage readings in a variable, average the raw data to bring out the general trends while ignoring the noise of load and environment, Then apply whatever transforms are needed to that raw value. It would also be nice to expose the raw readings in a
raw_battery_mv
method or the likes for debugging.