diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp index 300d097827..cdcb1c8489 100644 --- a/src/components/battery/BatteryController.cpp +++ b/src/components/battery/BatteryController.cpp @@ -1,4 +1,5 @@ #include "components/battery/BatteryController.h" +#include "components/utility/LinearApproximation.h" #include "drivers/PinMap.h" #include #include @@ -60,8 +61,13 @@ void Battery::SaadcInit() { } void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) { - const uint16_t battery_max = 4180; // maximum voltage of battery ( max charging voltage is 4.21 ) - const uint16_t battery_min = 3200; // minimum voltage of battery before shutdown ( depends on the battery ) + static const Utility::LinearApproximation aprox {{{ + {3200, 0}, // minimum voltage of battery before shutdown ( depends on the battery ) + {3600, 10}, // keen point corresponded to 10% of battery + {3700, 25}, + {3800, 50}, + {4180, 100} // maximum voltage of battery ( max charging voltage is 4.21 ) + }}}; if (p_event->type == NRFX_SAADC_EVT_DONE) { @@ -77,10 +83,8 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) { uint8_t newPercent; if (isFull) { newPercent = 100; - } else if (voltage < battery_min) { - newPercent = 0; } else { - newPercent = std::min((voltage - battery_min) * 100 / (battery_max - battery_min), isCharging ? 99 : 100); + newPercent = std::min(aprox.GetValue(voltage), (isCharging ? uint8_t{99} : uint8_t{100})); } if ((isPowerPresent && newPercent > percentRemaining) || (!isPowerPresent && newPercent < percentRemaining) || firstMeasurement) { diff --git a/src/components/utility/LinearApproximation.h b/src/components/utility/LinearApproximation.h new file mode 100644 index 0000000000..bfa8e5d0e7 --- /dev/null +++ b/src/components/utility/LinearApproximation.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +namespace Pinetime { + namespace Utility { + + // based on: https://github.com/SHristov92/LinearApproximation/blob/main/Linear.h + template + class LinearApproximation { + using Point = struct { + Key key; + Value value; + }; + + public: + LinearApproximation(const std::array &&points) + : points{points} {} + + Value GetValue(Key key) const { + if (key <= points[0].key) { + return points[0].value; + } + + for (size_t i = 1; i < Size; i++) { + if (key < points[i].key) { + return points[i-1].value + (key - points[i-1].key) * (points[i].value - points[i-1].value) / (points[i].key - points[i-1].key); + } + } + + return points[Size - 1].value; + } + + private: + std::array points; + }; + } +}