From d75927ff92b3513732573b70747e8311f91bfaed Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 25 Jun 2024 12:45:39 +1000 Subject: [PATCH] Use a curve to estimate battery % This is a bit more accurate than our previous linear relationship, particularly at lower voltages. --- src/tangara/battery/battery.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/tangara/battery/battery.cpp b/src/tangara/battery/battery.cpp index 2d2fff56..3cfdb20c 100644 --- a/src/tangara/battery/battery.cpp +++ b/src/tangara/battery/battery.cpp @@ -5,7 +5,9 @@ */ #include "battery/battery.hpp" +#include +#include #include #include "drivers/adc.hpp" @@ -58,14 +60,17 @@ auto Battery::Update() -> void { auto charge_state = samd_.GetChargeStatus(); - // FIXME: So what we *should* do here is measure the actual real-life - // time from full battery -> empty battery, store it in NVS, then rely on - // that. If someone could please do this, it would be lovely. Thanks! uint32_t mV = std::max(adc_->Millivolts(), kEmptyChargeMilliVolts); - uint_fast8_t percent = static_cast(std::min( - std::max(0.0, mV - kEmptyChargeMilliVolts) / - (kFullChargeMilliVolts - kEmptyChargeMilliVolts) * 100.0, - 100.0)); + + // Ideally the way you're 'supposed' to measure battery charge percent is to + // keep continuous track of the amps going in and out of it at any point. I'm + // skeptical of this approach, and we're not set up with the hardware needed + // to do it anyway. Instead, we use a curve-fitting formula by StackOverflow + // user 'Roho' to estimate the remaining capacity based on the battery's + // voltage. This seems to work pretty good! + double v = mV / 1000.0; + uint_fast8_t percent = static_cast(std::clamp( + 123 - (123 / std::pow(1 + std::pow(v / 3.7, 80.0), 0.165)), 0.0, 100.0)); bool is_charging; if (!charge_state) {