From 316517337aab0bff09a110fb5839e35ccc64ea07 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 13 Apr 2020 22:07:26 +0200 Subject: [PATCH 1/3] battery percentage calculation improved --- include/power.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++-- src/cyclic.cpp | 4 --- src/lorawan.cpp | 6 ++--- src/power.cpp | 24 ++++++++++++----- 4 files changed, 86 insertions(+), 17 deletions(-) diff --git a/include/power.h b/include/power.h index 12e8c032..9fd1a73c 100644 --- a/include/power.h +++ b/include/power.h @@ -7,6 +7,7 @@ #include "i2c.h" #include "reset.h" +#include "lorawan.h" #define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate #define NO_OF_SAMPLES 64 // we do some multisampling to get better values @@ -15,11 +16,12 @@ #define BAT_MAX_VOLTAGE 4200 // millivolts #endif #ifndef BAT_MIN_VOLTAGE -#define BAT_MIN_VOLTAGE 2800 // millivolts +#define BAT_MIN_VOLTAGE 3100 // millivolts #endif +typedef uint8_t (*mapFn_t)(uint16_t, uint16_t, uint16_t); + uint16_t read_voltage(void); -uint8_t read_battlevel(void); void calibrate_voltage(void); bool batt_sufficient(void); @@ -34,4 +36,67 @@ void AXP192_showstatus(void); #endif // HAS_PMU +// The following map functions were taken from + +/* + Battery.h - Battery library + Copyright (c) 2014 Roberto Lo Giacco. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +// +// Plots of the functions below available at +// https://www.desmos.com/calculator/x0esk5bsrk +// + +/** + * Symmetric sigmoidal approximation + * https://www.desmos.com/calculator/7m9lu26vpy + * + * c - c / (1 + k*x/v)^3 + */ +static inline uint8_t sigmoidal(uint16_t voltage, uint16_t minVoltage, uint16_t maxVoltage) { + // slow + // uint8_t result = 110 - (110 / (1 + pow(1.468 * (voltage - minVoltage)/(maxVoltage - minVoltage), 6))); + + // steep + // uint8_t result = 102 - (102 / (1 + pow(1.621 * (voltage - minVoltage)/(maxVoltage - minVoltage), 8.1))); + + // normal + uint8_t result = 105 - (105 / (1 + pow(1.724 * (voltage - minVoltage)/(maxVoltage - minVoltage), 5.5))); + return result >= 100 ? 100 : result; +} + +/** + * Asymmetric sigmoidal approximation + * https://www.desmos.com/calculator/oyhpsu8jnw + * + * c - c / [1 + (k*x/v)^4.5]^3 + */ +static inline uint8_t asigmoidal(uint16_t voltage, uint16_t minVoltage, uint16_t maxVoltage) { + uint8_t result = 101 - (101 / pow(1 + pow(1.33 * (voltage - minVoltage)/(maxVoltage - minVoltage) ,4.5), 3)); + return result >= 100 ? 100 : result; +} + +/** + * Linear mapping + * https://www.desmos.com/calculator/sowyhttjta + * + * x * 100 / v + */ +static inline uint8_t linear(uint16_t voltage, uint16_t minVoltage, uint16_t maxVoltage) { + return (unsigned long)(voltage - minVoltage) * 100 / (maxVoltage - minVoltage); +} + +uint8_t read_battlevel(mapFn_t mapFunction = &sigmoidal); + #endif \ No newline at end of file diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 92d98acf..3bc4ccdb 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -68,10 +68,6 @@ void doHousekeeping() { #if (defined BAT_MEASURE_ADC || defined HAS_PMU) batt_level = read_battlevel(); ESP_LOGI(TAG, "Battery: %d%%", batt_level); -#if (HAS_LORA) - // to come with future LMIC version - // lora_setBattLevel(batt_level); -#endif #ifdef HAS_PMU AXP192_showstatus(); #endif diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 6a033580..4e3d7469 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -485,12 +485,10 @@ void lora_setBattLevel(uint8_t batt_percent) { #endif // HAS_PMU else - lmic_batt_level = static_cast( - (float)batt_percent / - (float)(MCMD_DEVS_BATT_MAX - MCMD_DEVS_BATT_MIN + 1) * 100.0f); + lmic_batt_level = + batt_percent / 100.0 * (MCMD_DEVS_BATT_MAX - MCMD_DEVS_BATT_MIN + 1); LMIC_setBattLevel(lmic_batt_level); - ESP_LOGD(TAG, "lmic_batt_level = %d", lmic_batt_level); } // event EV_RXCOMPLETE message handler diff --git a/src/power.cpp b/src/power.cpp index 47e4fb0a..c5da9a13 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -210,19 +210,29 @@ uint16_t read_voltage(void) { return voltage; } -uint8_t read_battlevel() { +uint8_t read_battlevel(mapFn_t mapFunction) { - // return the battery level in values 0 ... 255 [percent], - // values > 100 probably mean external power, depending on hardware + // returns the estimated battery level in values 0 ... 100 [percent], const uint16_t batt_voltage = read_voltage(); - float batt_percent_fl = (float)(batt_voltage - BAT_MIN_VOLTAGE) / - (float)(BAT_MAX_VOLTAGE - BAT_MIN_VOLTAGE) * 100.0f; - const uint8_t batt_percent = static_cast(batt_percent_fl); + uint8_t batt_percent; - ESP_LOGD(TAG, "batt_voltage = %dmV / batt_percent = %u%%", batt_voltage, + if (batt_voltage <= BAT_MIN_VOLTAGE) + batt_percent = 0; + else if (batt_voltage >= BAT_MAX_VOLTAGE) + batt_percent = 100; + else + batt_percent = + (*mapFunction)(batt_voltage, BAT_MIN_VOLTAGE, BAT_MAX_VOLTAGE); + + ESP_LOGD(TAG, "batt_voltage = %dmV / batt_percent = %d%%", batt_voltage, batt_percent); +#if (HAS_LORA) + // to come with future LMIC version + // lora_setBattLevel(batt_percent); +#endif + return batt_percent; } From c8a5896043f99e0af10117b68a88b832e1ddab13 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 13 Apr 2020 23:47:59 +0200 Subject: [PATCH 2/3] power.h sanitization --- include/power.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/power.h b/include/power.h index 9fd1a73c..f8604252 100644 --- a/include/power.h +++ b/include/power.h @@ -53,11 +53,6 @@ void AXP192_showstatus(void); along with this program. If not, see . */ -// -// Plots of the functions below available at -// https://www.desmos.com/calculator/x0esk5bsrk -// - /** * Symmetric sigmoidal approximation * https://www.desmos.com/calculator/7m9lu26vpy From af02c2c6613bb7d79c0e2c4f84f34361f7857369 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 14 Apr 2020 00:15:51 +0200 Subject: [PATCH 3/3] battery level calculation fixes --- include/power.h | 23 ++++++----------------- src/lorawan.cpp | 2 +- src/power.cpp | 4 ++-- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/include/power.h b/include/power.h index f8604252..c2c91c94 100644 --- a/include/power.h +++ b/include/power.h @@ -7,7 +7,6 @@ #include "i2c.h" #include "reset.h" -#include "lorawan.h" #define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate #define NO_OF_SAMPLES 64 // we do some multisampling to get better values @@ -28,6 +27,7 @@ bool batt_sufficient(void); #ifdef HAS_PMU #include +extern AXP20X_Class pmu; enum pmu_power_t { pmu_power_on, pmu_power_off, pmu_power_sleep }; void AXP192_powerevent_IRQ(void); void AXP192_power(pmu_power_t powerlevel); @@ -37,22 +37,11 @@ void AXP192_showstatus(void); #endif // HAS_PMU // The following map functions were taken from - -/* - Battery.h - Battery library - Copyright (c) 2014 Roberto Lo Giacco. - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - +// +// Battery.h - Battery library +// Copyright (c) 2014 Roberto Lo Giacco +// https://github.com/rlogiacco/BatterySense + /** * Symmetric sigmoidal approximation * https://www.desmos.com/calculator/7m9lu26vpy diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 4e3d7469..e6a35534 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -488,7 +488,7 @@ void lora_setBattLevel(uint8_t batt_percent) { lmic_batt_level = batt_percent / 100.0 * (MCMD_DEVS_BATT_MAX - MCMD_DEVS_BATT_MIN + 1); - LMIC_setBattLevel(lmic_batt_level); + //LMIC_setBattLevel(lmic_batt_level); } // event EV_RXCOMPLETE message handler diff --git a/src/power.cpp b/src/power.cpp index c5da9a13..192c2255 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -212,7 +212,7 @@ uint16_t read_voltage(void) { uint8_t read_battlevel(mapFn_t mapFunction) { - // returns the estimated battery level in values 0 ... 100 [percent], + // returns the estimated battery level in values 0 ... 100 [percent] const uint16_t batt_voltage = read_voltage(); uint8_t batt_percent; @@ -230,7 +230,7 @@ uint8_t read_battlevel(mapFn_t mapFunction) { #if (HAS_LORA) // to come with future LMIC version - // lora_setBattLevel(batt_percent); + lora_setBattLevel(batt_percent); #endif return batt_percent;