Merge pull request #279 from bobbycar-graz/battery-graph
This commit is contained in:
@ -42,8 +42,8 @@ set(headers
|
||||
bobbycheckbox.h
|
||||
bobbyerrorhandler.h
|
||||
bobbyquickactions.h
|
||||
bobbytypesafeenum.h
|
||||
bobbyschedulertask.h
|
||||
bobbytypesafeenum.h
|
||||
buildserver.h
|
||||
can.h
|
||||
changevaluedisplay_bluetoothmode.h
|
||||
@ -59,6 +59,7 @@ set(headers
|
||||
debugcolorhelpers.h
|
||||
debuginputhandler.h
|
||||
debugtexthelpers.h
|
||||
displays/batterygraphdisplay.h
|
||||
displays/bmsdisplay.h
|
||||
displays/bobbychangevaluedisplay.h
|
||||
displays/bobbydisplay.h
|
||||
@ -294,6 +295,7 @@ set(sources
|
||||
debugcolorhelpers.cpp
|
||||
debuginputhandler.cpp
|
||||
debugtexthelpers.cpp
|
||||
displays/batterygraphdisplay.cpp
|
||||
displays/bmsdisplay.cpp
|
||||
displays/bobbychangevaluedisplay.cpp
|
||||
displays/bobbydisplay.cpp
|
||||
|
265
main/battery.cpp
265
main/battery.cpp
@ -9,10 +9,6 @@
|
||||
#include "globals.h"
|
||||
#include "newsettings.h"
|
||||
|
||||
#define CURVE(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
if (cellVoltage >= lowerVoltage && cellVoltage <= higherVoltage) \
|
||||
return 100 * (expected_ah - cpputils::mapValue<float>(cellVoltage, higherVoltage, lowerVoltage, fromAh, toAh)) / expected_ah;
|
||||
|
||||
float getBatteryPercentage(float batVoltage, BatteryCellType cellType)
|
||||
{
|
||||
const float cellVoltage = batVoltage / configs.battery.cellsSeries.value;
|
||||
@ -21,116 +17,52 @@ float getBatteryPercentage(float batVoltage, BatteryCellType cellType)
|
||||
{
|
||||
case BatteryCellType::_22P:
|
||||
{
|
||||
const float expected_ah = 2.2;
|
||||
const float expected_ah = BAT_MIN_AH_22P;
|
||||
if (cellVoltage > 4.15)
|
||||
return 100;
|
||||
|
||||
CURVE(4.15, 4.04, 0, 0.25)
|
||||
CURVE(4.04, 3.95, 0.25, 0.5)
|
||||
CURVE(3.95, 3.86, 0.5, 0.75)
|
||||
CURVE(3.86, 3.74, 0.75, 1.0)
|
||||
CURVE(3.74, 3.64, 1.0, 1.25)
|
||||
CURVE(3.64, 3.59, 1.25, 1.5)
|
||||
CURVE(3.59, 3.54, 1.5, 1.75)
|
||||
CURVE(3.54, 3.43, 1.75, 2.0)
|
||||
CURVE(3.43, 3.35, 2.0, 2.1)
|
||||
CURVE(3.35, 2.50, 2.1, 2.2)
|
||||
BAT_CURVE_22P(PERCENTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::MH1:
|
||||
{
|
||||
const float expected_ah = 3.2;
|
||||
const float expected_ah = BAT_MIN_AH_MH1;
|
||||
if (cellVoltage > 4.15)
|
||||
return 100;
|
||||
|
||||
CURVE(4.15, 4.09, 0, 0.25)
|
||||
CURVE(4.09, 4.04, 0.25, 0.5)
|
||||
CURVE(4.04, 3.95, 0.5, 0.75)
|
||||
CURVE(3.95, 3.88, 0.75, 1.0)
|
||||
CURVE(3.88, 3.79, 1.0, 1.25)
|
||||
CURVE(3.79, 3.70, 1.25, 1.5)
|
||||
CURVE(3.70, 3.65, 1.5, 1.75)
|
||||
CURVE(3.65, 3.60, 1.75, 2.0)
|
||||
CURVE(3.60, 3.56, 2.0, 2.25)
|
||||
CURVE(3.56, 3.50, 2.25, 2.5)
|
||||
CURVE(3.50, 3.40, 2.5, 2.75)
|
||||
CURVE(3.40, 3.30, 2.75, 3.0)
|
||||
CURVE(3.30, 2.5, 3.0, 3.2)
|
||||
BAT_CURVE_MH1(PERCENTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HG2:
|
||||
{
|
||||
const float expected_ah = 3.0;
|
||||
const float expected_ah = BAT_MIN_AH_HG2;
|
||||
if (cellVoltage > 4.15)
|
||||
return 100;
|
||||
|
||||
CURVE(4.15, 4.08, 0, 0.25)
|
||||
CURVE(4.08, 4.01, 0.25, 0.5)
|
||||
CURVE(4.01, 3.92, 0.5, 0.75)
|
||||
CURVE(3.92, 3.84, 0.75, 1.0)
|
||||
CURVE(3.84, 3.75, 1.0, 1.25)
|
||||
CURVE(3.75, 3.67, 1.25, 1.5)
|
||||
CURVE(3.67, 3.62, 1.5, 1.75)
|
||||
CURVE(3.62, 3.55, 1.75, 2.0)
|
||||
CURVE(3.55, 3.44, 2.0, 2.25)
|
||||
CURVE(3.44, 3.30, 2.25, 2.5)
|
||||
CURVE(3.30, 3.05, 2.5, 2.75)
|
||||
CURVE(3.05, 2.50, 2.75, 3.0)
|
||||
BAT_CURVE_HG2(PERCENTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::VTC5:
|
||||
{
|
||||
const float expected_ah = 2.6;
|
||||
const float expected_ah = BAT_MIN_AH_VTC5;
|
||||
if (cellVoltage > 4.15)
|
||||
return 100;
|
||||
|
||||
CURVE(4.15, 4.08, 0, 0.25)
|
||||
CURVE(4.08, 3.98, 0.25, 0.5)
|
||||
CURVE(3.98, 3.89, 0.5, 0.75)
|
||||
CURVE(3.89, 3.79, 0.75, 1.0)
|
||||
CURVE(3.79, 3.71, 1.0, 1.25)
|
||||
CURVE(3.71, 3.64, 1.25, 1.5)
|
||||
CURVE(3.64, 3.53, 1.5, 1.75)
|
||||
CURVE(3.53, 3.44, 1.75, 2.0)
|
||||
CURVE(3.44, 3.20, 2.0, 2.25)
|
||||
CURVE(3.20, 2.80, 2.25, 2.5)
|
||||
CURVE(2.80, 2.50, 2.5, 2.60)
|
||||
BAT_CURVE_VTC5(PERCENTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::BAK_25R:
|
||||
{
|
||||
const float expected_ah = 2.5;
|
||||
const float expected_ah = BAT_MIN_AH_BAK_25R;
|
||||
if(cellVoltage > 4.15){
|
||||
return 100;
|
||||
}
|
||||
CURVE(4.15, 4.06, 0, 0.25)
|
||||
CURVE(4.06, 3.96, 0.25, 0.5)
|
||||
CURVE(3.96, 3.88, 0.5, 0.75)
|
||||
CURVE(3.88, 3.77, 0.75, 1)
|
||||
CURVE(3.77, 3.68, 1, 1.25)
|
||||
CURVE(3.68, 3.62, 1.25, 1.5)
|
||||
CURVE(3.62, 3.56, 1.5, 1.75)
|
||||
CURVE(3.56, 3.47, 1.75, 2)
|
||||
CURVE(3.47, 3.31, 2, 2.25)
|
||||
CURVE(3.31, 2.50, 2.25, 2.5)
|
||||
BAT_CURVE_25R(PERCENTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HE4:
|
||||
{
|
||||
const float expected_ah = 2.3;
|
||||
const float expected_ah = BAT_MIN_AH_HE4;
|
||||
if(cellVoltage > 4.15){
|
||||
return 100;
|
||||
}
|
||||
CURVE(4.15, 4.02, 0, 0.25)
|
||||
CURVE(4.02, 3.91, 0.25, 0.5)
|
||||
CURVE(3.91, 3.81, 0.5, 0.75)
|
||||
CURVE(3.81, 3.72, 0.75, 1)
|
||||
CURVE(3.72, 3.61, 1, 1.25)
|
||||
CURVE(3.61, 3.62, 1.25, 1.5)
|
||||
CURVE(3.62, 3.53, 1.5, 1.75)
|
||||
CURVE(3.53, 3.45, 1.75, 2)
|
||||
CURVE(3.45, 3.21, 2, 2.25)
|
||||
CURVE(3.21, 2.80, 2.25, 2.3)
|
||||
BAT_CURVE_HE4(PERCENTAGE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -194,11 +126,6 @@ std::string getBatteryRemainingWattHoursString()
|
||||
return fmt::format("{:.1f}Wh", getRemainingWattHours());
|
||||
}
|
||||
|
||||
std::string getBatteryCellTypeString()
|
||||
{
|
||||
return fmt::format("Cells: {}", toString(BatteryCellType(configs.battery.cellType.value)));
|
||||
}
|
||||
|
||||
std::string getRemainingRangeString()
|
||||
{
|
||||
return fmt::format("{:.1f} km", getRemainingWattHours() / configs.battery.watthoursPerKilometer.value);
|
||||
@ -213,6 +140,174 @@ std::string getBatteryDebugString()
|
||||
return "No Battery";
|
||||
}
|
||||
|
||||
float getMinBatCellVoltage(BatteryCellType cellType) {
|
||||
float minimumVoltage = std::numeric_limits<float>::max();
|
||||
switch (cellType)
|
||||
{
|
||||
case BatteryCellType::_22P:
|
||||
{
|
||||
BAT_CURVE_22P(GET_MINIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HG2:
|
||||
{
|
||||
BAT_CURVE_HG2(GET_MINIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::MH1:
|
||||
{
|
||||
BAT_CURVE_MH1(GET_MINIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::VTC5:
|
||||
{
|
||||
BAT_CURVE_VTC5(GET_MINIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::BAK_25R:
|
||||
{
|
||||
BAT_CURVE_25R(GET_MINIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HE4:
|
||||
{
|
||||
BAT_CURVE_HE4(GET_MINIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0.f;
|
||||
}
|
||||
return minimumVoltage;
|
||||
}
|
||||
|
||||
float getMaxBatCellVoltage(BatteryCellType cellType)
|
||||
{
|
||||
switch (cellType)
|
||||
{
|
||||
case BatteryCellType::_22P:
|
||||
{
|
||||
BAT_CURVE_22P(GET_MAXIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HG2:
|
||||
{
|
||||
BAT_CURVE_HG2(GET_MAXIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::MH1:
|
||||
{
|
||||
BAT_CURVE_MH1(GET_MAXIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::VTC5:
|
||||
{
|
||||
BAT_CURVE_VTC5(GET_MAXIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::BAK_25R:
|
||||
{
|
||||
BAT_CURVE_25R(GET_MAXIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HE4:
|
||||
{
|
||||
BAT_CURVE_HE4(GET_MAXIMUM_BAT_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
uint8_t count_curve_points(BatteryCellType cellType)
|
||||
{
|
||||
#define COUNT_CURVE_POINTS(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
count++;
|
||||
|
||||
uint8_t count = 0;
|
||||
switch (cellType)
|
||||
{
|
||||
case BatteryCellType::_22P:
|
||||
{
|
||||
BAT_CURVE_22P(COUNT_CURVE_POINTS);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HG2:
|
||||
{
|
||||
BAT_CURVE_HG2(COUNT_CURVE_POINTS);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::MH1:
|
||||
{
|
||||
BAT_CURVE_MH1(COUNT_CURVE_POINTS);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::VTC5:
|
||||
{
|
||||
BAT_CURVE_VTC5(COUNT_CURVE_POINTS);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::BAK_25R:
|
||||
{
|
||||
BAT_CURVE_25R(COUNT_CURVE_POINTS);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HE4:
|
||||
{
|
||||
BAT_CURVE_HE4(COUNT_CURVE_POINTS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
std::optional<CalibrationPointVoltages> get_point_n_voltages(BatteryCellType cellType, uint8_t num)
|
||||
{
|
||||
#define GET_POINT_N_VOLTAGES(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
if (count == num) { \
|
||||
uint16_t minVoltage = (lowerVoltage) * 100; \
|
||||
uint16_t maxVoltage = (higherVoltage) * 100; \
|
||||
return CalibrationPointVoltages{ .minVoltage=minVoltage, .maxVoltage=maxVoltage }; \
|
||||
} \
|
||||
count++;
|
||||
|
||||
uint8_t count = 0;
|
||||
CalibrationPointVoltages point;
|
||||
switch (cellType)
|
||||
{
|
||||
case BatteryCellType::_22P:
|
||||
{
|
||||
BAT_CURVE_22P(GET_POINT_N_VOLTAGES);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HG2:
|
||||
{
|
||||
BAT_CURVE_HG2(GET_POINT_N_VOLTAGES);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::MH1:
|
||||
{
|
||||
BAT_CURVE_MH1(GET_POINT_N_VOLTAGES);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::VTC5:
|
||||
{
|
||||
BAT_CURVE_VTC5(GET_POINT_N_VOLTAGES);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::BAK_25R:
|
||||
{
|
||||
BAT_CURVE_25R(GET_POINT_N_VOLTAGES);
|
||||
break;
|
||||
}
|
||||
case BatteryCellType::HE4:
|
||||
{
|
||||
BAT_CURVE_HE4(GET_POINT_N_VOLTAGES);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
namespace battery {
|
||||
std::optional<float> bootBatPercentage;
|
||||
std::optional<float> bootBatWh;
|
||||
|
129
main/battery.h
129
main/battery.h
@ -6,6 +6,126 @@
|
||||
// local includes
|
||||
#include <bobbytypesafeenum.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t minVoltage;
|
||||
uint16_t maxVoltage;
|
||||
} CalibrationPointVoltages;
|
||||
|
||||
// battery curves
|
||||
#define PERCENTAGE(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
if (cellVoltage >= lowerVoltage && cellVoltage <= higherVoltage) \
|
||||
return 100 * (expected_ah - cpputils::mapValue<float>(cellVoltage, higherVoltage, lowerVoltage, fromAh, toAh)) / expected_ah;
|
||||
|
||||
#define GET_MINIMUM_VOLTAGE(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
if (expected_ah >= toAh) \
|
||||
return lowerVoltage;
|
||||
|
||||
#define GET_MAXIMUM_VOLTAGE(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
if (fromAh == 0) \
|
||||
return higherVoltage;
|
||||
|
||||
#define GET_MINIMUM_BAT_VOLTAGE(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
if (lowerVoltage < minimumVoltage) \
|
||||
minimumVoltage = lowerVoltage;
|
||||
|
||||
#define GET_MAXIMUM_BAT_VOLTAGE(higherVoltage,lowerVoltage,fromAh,toAh) \
|
||||
if (fromAh == 0) \
|
||||
return higherVoltage;
|
||||
|
||||
|
||||
// All curves here have to follow the same order (highest-voltage first)
|
||||
// as some functions require this to display data in correct order
|
||||
|
||||
// 22P
|
||||
#define BAT_MIN_AH_22P 2.2
|
||||
#define BAT_CURVE_22P(func) \
|
||||
func(4.15, 4.04, 0, 0.25) \
|
||||
func(4.04, 3.95, 0.25, 0.5) \
|
||||
func(3.95, 3.86, 0.5, 0.75) \
|
||||
func(3.86, 3.74, 0.75, 1.0) \
|
||||
func(3.74, 3.64, 1.0, 1.25) \
|
||||
func(3.64, 3.59, 1.25, 1.5) \
|
||||
func(3.59, 3.54, 1.5, 1.75) \
|
||||
func(3.54, 3.43, 1.75, 2.0) \
|
||||
func(3.43, 3.35, 2.0, 2.1) \
|
||||
func(3.35, 2.50, 2.1, 2.2)
|
||||
|
||||
// MH1
|
||||
#define BAT_MIN_AH_MH1 3.2
|
||||
#define BAT_CURVE_MH1(func) \
|
||||
func(4.15, 4.09, 0, 0.25) \
|
||||
func(4.09, 4.04, 0.25, 0.5) \
|
||||
func(4.04, 3.95, 0.5, 0.75) \
|
||||
func(3.95, 3.88, 0.75, 1.0) \
|
||||
func(3.88, 3.79, 1.0, 1.25) \
|
||||
func(3.79, 3.70, 1.25, 1.5) \
|
||||
func(3.70, 3.65, 1.5, 1.75) \
|
||||
func(3.65, 3.60, 1.75, 2.0) \
|
||||
func(3.60, 3.56, 2.0, 2.25) \
|
||||
func(3.56, 3.50, 2.25, 2.5) \
|
||||
func(3.50, 3.40, 2.5, 2.75) \
|
||||
func(3.40, 3.30, 2.75, 3.0) \
|
||||
func(3.30, 2.5, 3.0, 3.2)
|
||||
|
||||
// HG2
|
||||
#define BAT_MIN_AH_HG2 3.0
|
||||
#define BAT_CURVE_HG2(func) \
|
||||
func(4.15, 4.08, 0, 0.25) \
|
||||
func(4.08, 4.01, 0.25, 0.5) \
|
||||
func(4.01, 3.92, 0.5, 0.75) \
|
||||
func(3.92, 3.84, 0.75, 1.0) \
|
||||
func(3.84, 3.75, 1.0, 1.25) \
|
||||
func(3.75, 3.67, 1.25, 1.5) \
|
||||
func(3.67, 3.62, 1.5, 1.75) \
|
||||
func(3.62, 3.55, 1.75, 2.0) \
|
||||
func(3.55, 3.44, 2.0, 2.25) \
|
||||
func(3.44, 3.30, 2.25, 2.5) \
|
||||
func(3.30, 3.05, 2.5, 2.75) \
|
||||
func(3.05, 2.50, 2.75, 3.0)
|
||||
|
||||
// VTC5
|
||||
#define BAT_MIN_AH_VTC5 2.6
|
||||
#define BAT_CURVE_VTC5(func) \
|
||||
func(4.15, 4.08, 0, 0.25) \
|
||||
func(4.08, 3.98, 0.25, 0.5) \
|
||||
func(3.98, 3.89, 0.5, 0.75) \
|
||||
func(3.89, 3.79, 0.75, 1.0) \
|
||||
func(3.79, 3.71, 1.0, 1.25) \
|
||||
func(3.71, 3.64, 1.25, 1.5) \
|
||||
func(3.64, 3.53, 1.5, 1.75) \
|
||||
func(3.53, 3.44, 1.75, 2.0) \
|
||||
func(3.44, 3.20, 2.0, 2.25) \
|
||||
func(3.20, 2.80, 2.25, 2.5) \
|
||||
func(2.80, 2.50, 2.5, 2.60)
|
||||
|
||||
// BAK_25R
|
||||
#define BAT_MIN_AH_BAK_25R 2.5
|
||||
#define BAT_CURVE_25R(func) \
|
||||
func(4.15, 4.06, 0, 0.25) \
|
||||
func(4.06, 3.96, 0.25, 0.5) \
|
||||
func(3.96, 3.88, 0.5, 0.75) \
|
||||
func(3.88, 3.77, 0.75, 1) \
|
||||
func(3.77, 3.68, 1, 1.25) \
|
||||
func(3.68, 3.62, 1.25, 1.5) \
|
||||
func(3.62, 3.56, 1.5, 1.75) \
|
||||
func(3.56, 3.47, 1.75, 2) \
|
||||
func(3.47, 3.31, 2, 2.25) \
|
||||
func(3.31, 2.50, 2.25, 2.5)
|
||||
|
||||
// HE4
|
||||
#define BAT_MIN_AH_HE4 2.3
|
||||
#define BAT_CURVE_HE4(func) \
|
||||
func(4.15, 4.02, 0, 0.25) \
|
||||
func(4.02, 3.91, 0.25, 0.5) \
|
||||
func(3.91, 3.81, 0.5, 0.75) \
|
||||
func(3.81, 3.72, 0.75, 1) \
|
||||
func(3.72, 3.61, 1, 1.25) \
|
||||
func(3.61, 3.62, 1.25, 1.5) \
|
||||
func(3.62, 3.53, 1.5, 1.75) \
|
||||
func(3.53, 3.45, 1.75, 2) \
|
||||
func(3.45, 3.21, 2, 2.25) \
|
||||
func(3.21, 2.80, 2.25, 2.3)
|
||||
|
||||
#define BatteryCellTypeValues(x) \
|
||||
x(_22P) \
|
||||
x(HG2) \
|
||||
@ -21,12 +141,13 @@ float getRemainingWattHours();
|
||||
|
||||
float getBatteryWattHours();
|
||||
|
||||
float getMinBatCellVoltage(BatteryCellType cellType);
|
||||
float getMaxBatCellVoltage(BatteryCellType cellType);
|
||||
|
||||
std::string getBatteryPercentageString();
|
||||
|
||||
std::string getBatteryRemainingWattHoursString();
|
||||
|
||||
std::string getBatteryCellTypeString();
|
||||
|
||||
std::string getRemainingRangeString();
|
||||
|
||||
std::string getBatteryDebugString();
|
||||
@ -36,6 +157,10 @@ std::string getBatteryAdvancedPercentageString();
|
||||
float getPercentageByWh(float wh);
|
||||
float getTarget_mAh();
|
||||
|
||||
uint8_t count_curve_points(BatteryCellType cellType);
|
||||
|
||||
std::optional<CalibrationPointVoltages> get_point_n_voltages(BatteryCellType cellType, uint8_t num);
|
||||
|
||||
namespace battery {
|
||||
extern std::optional<float> bootBatPercentage;
|
||||
extern std::optional<float> bootBatWh;
|
||||
|
86
main/displays/batterygraphdisplay.cpp
Normal file
86
main/displays/batterygraphdisplay.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "batterygraphdisplay.h"
|
||||
constexpr const char * const TAG = "BatteryGraphDisplay";
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <screenmanager.h>
|
||||
#include <tftinstance.h>
|
||||
|
||||
// local includes
|
||||
#include "battery.h"
|
||||
#include "displays/menus/batterymenu.h"
|
||||
#include "globals.h"
|
||||
#include "newsettings.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace {
|
||||
constexpr char TEXT_BATTERY_GRAPH[] = "Battery Level";
|
||||
constexpr const uint8_t TOP_OFFSET = 40;
|
||||
} // namespace
|
||||
|
||||
void BatteryGraphDisplay::initScreen()
|
||||
{
|
||||
Base::initScreen();
|
||||
const auto points = count_curve_points(configs.battery.cellType.value);
|
||||
const auto max_height = espgui::tft.height() - 1;
|
||||
const auto max_width = espgui::tft.width() - 4;
|
||||
const uint16_t part = max_width / points;
|
||||
const auto min_voltage = getMinBatCellVoltage(configs.battery.cellType.value);
|
||||
const auto max_voltage = getMaxBatCellVoltage(configs.battery.cellType.value);
|
||||
ESP_LOGI(TAG, "min_voltage: %f, max_voltage: %f", min_voltage, max_voltage);
|
||||
for (uint8_t i = 0; points >= i; i++) {
|
||||
// draw lines between point->minVoltage and point->maxVoltage from left to right
|
||||
if (const auto point = get_point_n_voltages(configs.battery.cellType.value, points - i); point)
|
||||
{
|
||||
const int x1 = 2 + part * (points - i + 1);
|
||||
const int y1 = float_map(point->minVoltage / 100.f, min_voltage, max_voltage, max_height, TOP_OFFSET);
|
||||
const int x2 = 2 + part * (points - i);
|
||||
const int y2 = float_map(point->maxVoltage / 100.f, min_voltage, max_voltage, max_height, TOP_OFFSET);
|
||||
espgui::tft.drawLine(x1, y1, x2, y2, TFT_WHITE);
|
||||
ESP_LOGI(TAG, "espgui::tft.drawLine(%d, %d, %d, %d, TFT_WHITE);", x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string BatteryGraphDisplay::text() const
|
||||
{
|
||||
return TEXT_BATTERY_GRAPH;
|
||||
}
|
||||
|
||||
void BatteryGraphDisplay::redraw()
|
||||
{
|
||||
using namespace espgui;
|
||||
Base::redraw();
|
||||
|
||||
if (const auto avgVoltage = controllers.getAvgVoltage(); avgVoltage)
|
||||
{
|
||||
if (*avgVoltage == m_lastBatVoltage)
|
||||
return;
|
||||
const auto cellType = configs.battery.cellType.value;
|
||||
|
||||
const uint16_t onePercent = tft.width() / 100;
|
||||
const uint16_t xOffset = onePercent * getBatteryPercentage(*avgVoltage, cellType);
|
||||
const uint16_t lastXOffset = onePercent * getBatteryPercentage(m_lastBatVoltage, cellType);
|
||||
|
||||
// clear the old one and draw the new one
|
||||
tft.fillRect(lastXOffset, TOP_OFFSET, onePercent, tft.height() - TOP_OFFSET, TFT_BLACK);
|
||||
tft.fillRect(xOffset, TOP_OFFSET, onePercent, tft.height() - TOP_OFFSET, TFT_WHITE);
|
||||
m_lastBatVoltage = *avgVoltage;
|
||||
}
|
||||
|
||||
// tft.drawLine() code
|
||||
}
|
||||
|
||||
void BatteryGraphDisplay::buttonPressed(espgui::Button button)
|
||||
{
|
||||
Base::buttonPressed(button);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
using espgui::Button;
|
||||
case Button::Left:
|
||||
case Button::Right:
|
||||
espgui::switchScreen<BatteryMenu>();
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
18
main/displays/batterygraphdisplay.h
Normal file
18
main/displays/batterygraphdisplay.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
// local includes
|
||||
#include "bobbydisplaywithtitle.h"
|
||||
|
||||
class BatteryGraphDisplay : public BobbyDisplayWithTitle {
|
||||
using Base = BobbyDisplayWithTitle;
|
||||
|
||||
public:
|
||||
std::string text() const override;
|
||||
void initScreen() override;
|
||||
void redraw() override;
|
||||
|
||||
void buttonPressed(espgui::Button button) override;
|
||||
|
||||
private:
|
||||
float m_lastBatVoltage{0};
|
||||
};
|
@ -14,8 +14,10 @@
|
||||
// Local includes
|
||||
#include "accessors/settingsaccessors.h"
|
||||
#include "battery.h"
|
||||
#include "displays/batterygraphdisplay.h"
|
||||
#include "displays/bobbychangevaluedisplay.h"
|
||||
#include "displays/calibratevoltagedisplay.h"
|
||||
#include "icons/graph.h"
|
||||
#include "icons/settings.h"
|
||||
#include "mainmenu.h"
|
||||
#include "typesafeenumchangemenu.h"
|
||||
@ -26,6 +28,7 @@ constexpr char TEXT_BATTERY[] = "Battery";
|
||||
constexpr char TEXT_CELL_SERIES[] = "Cells (Series)";
|
||||
constexpr char TEXT_CELL_PARALLEL[] = "Cells (Parallel)";
|
||||
constexpr char TEXT_SELECT_CELL_TYPE[] = "Select Cell Type";
|
||||
constexpr char TEXT_SHOW_BATTERY_GRAPH[] = "Battery Graph";
|
||||
constexpr char TEXT_BATTERY_CALIBRATE[] = "Calibrate Voltages";
|
||||
constexpr char TEXT_BATTERY_WHKM[] = "Wh per km";
|
||||
constexpr char TEXT_BATTERY_APPLYCALIB[] = "Apply calibration";
|
||||
@ -78,6 +81,7 @@ BatteryMenu::BatteryMenu()
|
||||
constructMenuItem<makeComponent<MenuItem, TextWithValueHelper<TEXT_CELL_PARALLEL, BatteryParallelCellsAccessor>, SwitchScreenAction<BatteryCellParallelChangeScreen>>>();
|
||||
constructMenuItem<makeComponent<MenuItem, TextWithValueHelper<TEXT_BATTERY_WHKM, BatteryWHperKMAccessor>, SwitchScreenAction<BatteryWHperKMChangeScreen>>>();
|
||||
constructMenuItem<SwitchScreenTypeSafeChangeMenuItem<BatteryCellType, BatteryMenu, TEXT_SELECT_CELL_TYPE>>(&configs.battery.cellType);
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_SHOW_BATTERY_GRAPH>, SwitchScreenAction<BatteryGraphDisplay>, StaticMenuItemIcon<&bobbyicons::graph>>>();
|
||||
constructMenuItem<makeComponent<MenuItem, EmptyText, DummyAction>>();
|
||||
constructMenuItem<makeComponent<MenuItem, WhStatisticsText, DummyAction>>();
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BATTERY_CALIBRATE>, SwitchScreenAction<CalibrateVoltageDisplay>, StaticMenuItemIcon<&bobbyicons::settings>>>();
|
||||
|
@ -330,3 +330,11 @@ std::string get_wifi_security_string(wifi_auth_mode_t authMode)
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
float float_map(float x, float in_min, float in_max, float out_min, float out_max) {
|
||||
const float dividend = out_max - out_min;
|
||||
const float divisor = in_max - in_min;
|
||||
const float delta = x - in_min;
|
||||
|
||||
return (delta * dividend + (divisor / 2.f)) / divisor + out_min;
|
||||
}
|
||||
|
@ -79,3 +79,4 @@ inline CRGB UINT32_TO_CRGB(uint32_t color)
|
||||
}
|
||||
|
||||
std::string get_wifi_security_string(wifi_auth_mode_t authMode);
|
||||
float float_map(float x, float in_min, float in_max, float out_min, float out_max);
|
||||
|
Reference in New Issue
Block a user