mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 23:08:11 +00:00
Battery %: use LiPo discharge curve with variable shutdown threshold
Replace linear voltage-to-percent formula with a LiPo discharge curve lookup table and linear interpolation. The curve is then rescaled so that low_batt_mv (configurable shutdown threshold) maps to 0% and 4200mV maps to 100%, preserving the non-linear shape regardless of the chosen threshold. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -558,13 +558,34 @@ class HomeScreen : public UIScreen {
|
||||
#ifndef BATT_MIN_MILLIVOLTS
|
||||
#define BATT_MIN_MILLIVOLTS 3200
|
||||
#endif
|
||||
#ifndef BATT_MAX_MILLIVOLTS
|
||||
#define BATT_MAX_MILLIVOLTS 4200
|
||||
#endif
|
||||
// 0% anchor: low_batt_mv if set, otherwise BATT_MIN_MILLIVOLTS
|
||||
int minMv = (_node_prefs && _node_prefs->low_batt_mv > 0)
|
||||
? (int)_node_prefs->low_batt_mv : BATT_MIN_MILLIVOLTS;
|
||||
int pct = ((int)batteryMilliVolts - minMv) * 100 / (BATT_MAX_MILLIVOLTS - minMv);
|
||||
// LiPo discharge curve: voltage (mV) → raw capacity (%)
|
||||
static const struct { uint16_t mv; uint8_t pct; } CURVE[] = {
|
||||
{3200, 0}, {3300, 3}, {3400, 8}, {3500, 15},
|
||||
{3600, 25}, {3650, 33}, {3700, 45}, {3750, 58},
|
||||
{3800, 68}, {3900, 77}, {4000, 86}, {4100, 93}, {4200, 100}
|
||||
};
|
||||
static const int CURVE_LEN = sizeof(CURVE) / sizeof(CURVE[0]);
|
||||
|
||||
auto curveAt = [&](int mv) -> int {
|
||||
if (mv <= (int)CURVE[0].mv) return CURVE[0].pct;
|
||||
if (mv >= (int)CURVE[CURVE_LEN-1].mv) return CURVE[CURVE_LEN-1].pct;
|
||||
for (int i = 1; i < CURVE_LEN; i++) {
|
||||
if (mv <= (int)CURVE[i].mv) {
|
||||
int span_mv = CURVE[i].mv - CURVE[i-1].mv;
|
||||
int span_pct = CURVE[i].pct - CURVE[i-1].pct;
|
||||
return CURVE[i-1].pct + (mv - (int)CURVE[i-1].mv) * span_pct / span_mv;
|
||||
}
|
||||
}
|
||||
return 100;
|
||||
};
|
||||
|
||||
int low_mv = (_node_prefs && _node_prefs->low_batt_mv > 0)
|
||||
? (int)_node_prefs->low_batt_mv : BATT_MIN_MILLIVOLTS;
|
||||
int raw_pct = curveAt((int)batteryMilliVolts);
|
||||
int low_pct = curveAt(low_mv);
|
||||
// rescale so low_mv = 0% and 4200mV = 100%
|
||||
int pct = (low_pct >= 100) ? 0
|
||||
: (raw_pct - low_pct) * 100 / (100 - low_pct);
|
||||
if (pct < 0) pct = 0;
|
||||
if (pct > 100) pct = 100;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user