Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/components/battery/BatteryController.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "components/battery/BatteryController.h"
#include "components/utility/LinearApproximation.h"
#include "drivers/PinMap.h"
#include <hal/nrf_gpio.h>
#include <nrfx_saadc.h>
Expand Down Expand Up @@ -60,8 +61,14 @@ 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<uint16_t, uint8_t, 6> aprox {{{
{3500, 0}, // Minimum voltage before shutdown (depends on the battery)
{3600, 10}, // Keen point that corresponds to 10%
{3700, 25},
{3750, 50},
{3900, 75},
{4180, 100} // Maximum voltage during charging is 4.21V
}}};

if (p_event->type == NRFX_SAADC_EVT_DONE) {

Expand All @@ -77,10 +84,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) {
Expand Down
41 changes: 41 additions & 0 deletions src/components/utility/LinearApproximation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <cstddef>
#include <array>

namespace Pinetime {
namespace Utility {

// based on: https://github.com/SHristov92/LinearApproximation/blob/main/Linear.h
template <typename Key, typename Value, std::size_t Size> class LinearApproximation {
using Point = struct {
Key key;
Value value;
};

public:
LinearApproximation(const std::array<Point, Size>&& sorted_points) : points {sorted_points} {
}

Value GetValue(Key key) const {
if (key <= points[0].key) {
return points[0].value;
}

for (std::size_t i = 1; i < Size; i++) {
const auto& p = points[i];
const auto& p_prev = points[i - 1];

if (key < p.key) {
return p_prev.value + (key - p_prev.key) * (p.value - p_prev.value) / (p.key - p_prev.key);
}
}

return points[Size - 1].value;
}

private:
std::array<Point, Size> points;
};
}
}