Files
bobbycar-boardcomputer-firm…/main/battery.cpp
T

313 lines
8.0 KiB
C++
Raw Normal View History

2021-11-02 01:43:58 +01:00
#include "battery.h"
2021-11-07 13:04:19 +01:00
2021-11-21 01:36:44 +01:00
// 3rdparty lib includes
#include <fmt/core.h>
#include <cpputils.h>
// local includes
#include "drivingstatistics.h"
#include "globals.h"
2022-01-03 01:31:48 +01:00
#include "newsettings.h"
2021-11-21 01:36:44 +01:00
2021-11-07 13:04:19 +01:00
float getBatteryPercentage(float batVoltage, BatteryCellType cellType)
{
2022-04-29 22:40:49 +02:00
const float cellVoltage = batVoltage / configs.battery.cellsSeries.value();
2021-11-07 13:04:19 +01:00
switch (cellType)
{
case BatteryCellType::_22P:
{
2022-02-28 00:26:17 +01:00
const float expected_ah = BAT_MIN_AH_22P;
2022-06-12 17:51:31 +02:00
if (cellVoltage > 4.15f)
return 100.f;
2022-02-28 00:26:17 +01:00
BAT_CURVE_22P(PERCENTAGE);
2021-11-07 13:04:19 +01:00
break;
}
case BatteryCellType::MH1:
{
2022-02-28 00:26:17 +01:00
const float expected_ah = BAT_MIN_AH_MH1;
2022-06-12 17:51:31 +02:00
if (cellVoltage > 4.15f)
return 100.f;
2022-02-28 00:26:17 +01:00
BAT_CURVE_MH1(PERCENTAGE);
2021-11-07 13:04:19 +01:00
break;
}
case BatteryCellType::HG2:
{
2022-02-28 00:26:17 +01:00
const float expected_ah = BAT_MIN_AH_HG2;
2022-06-12 17:51:31 +02:00
if (cellVoltage > 4.15f)
return 100.f;
2022-02-28 00:26:17 +01:00
BAT_CURVE_HG2(PERCENTAGE);
2021-11-07 13:04:19 +01:00
break;
}
case BatteryCellType::VTC5:
{
2022-02-28 00:26:17 +01:00
const float expected_ah = BAT_MIN_AH_VTC5;
2022-06-12 17:51:31 +02:00
if (cellVoltage > 4.15f)
return 100.f;
2022-02-28 00:26:17 +01:00
BAT_CURVE_VTC5(PERCENTAGE);
2021-11-07 13:04:19 +01:00
break;
}
2021-11-12 20:04:31 +01:00
case BatteryCellType::BAK_25R:
{
2022-02-28 00:26:17 +01:00
const float expected_ah = BAT_MIN_AH_BAK_25R;
2022-06-12 17:51:31 +02:00
if(cellVoltage > 4.15f){
return 100.f;
2021-11-12 20:04:31 +01:00
}
2022-02-28 00:26:17 +01:00
BAT_CURVE_25R(PERCENTAGE);
2021-11-12 20:04:31 +01:00
break;
}
2022-02-06 17:38:02 +01:00
case BatteryCellType::HE4:
{
2022-02-28 00:26:17 +01:00
const float expected_ah = BAT_MIN_AH_HE4;
2022-06-12 17:51:31 +02:00
if(cellVoltage > 4.15f){
return 100.f;
2022-02-06 17:38:02 +01:00
}
2022-02-28 00:26:17 +01:00
BAT_CURVE_HE4(PERCENTAGE);
2022-02-06 17:38:02 +01:00
break;
}
2021-11-07 13:04:19 +01:00
}
return 0.f;
}
float getRemainingWattHours()
{
2021-11-18 01:13:16 +01:00
float target_mah = getTarget_mAh();
2021-11-07 13:04:19 +01:00
2022-01-27 01:09:52 +01:00
if (const auto avgVoltage = controllers.getAvgVoltage(); avgVoltage)
2021-11-07 13:04:19 +01:00
{
2022-06-12 17:51:31 +02:00
return (target_mah / 1000.f) * 3.7f * configs.battery.cellsParallel.value() * configs.battery.cellsSeries.value() * (getBatteryPercentage(*avgVoltage, BatteryCellType(configs.battery.cellType.value())) / 100);
2021-11-07 13:04:19 +01:00
}
2022-01-27 01:09:52 +01:00
else
2022-06-12 17:51:31 +02:00
return 0.f;
2021-11-07 13:04:19 +01:00
}
2021-11-18 01:13:16 +01:00
float getPercentageByWh(float wh)
{
2022-06-12 17:51:31 +02:00
const float maxWh = (getTarget_mAh() / 1000.f) * 3.7f * configs.battery.cellsParallel.value() * configs.battery.cellsSeries.value();
2021-11-18 01:13:16 +01:00
return maxWh / wh;
}
2022-03-02 15:09:44 +01:00
float getBatteryWattHours()
{
2022-06-12 17:51:31 +02:00
return (getTarget_mAh() / 1000.f) * 3.7f * configs.battery.cellsParallel.value() * configs.battery.cellsSeries.value();
2022-03-02 15:09:44 +01:00
}
2021-11-18 01:13:16 +01:00
float getTarget_mAh()
{
float target_mah = 2000; //default
2022-04-29 22:40:49 +02:00
if(BatteryCellType(configs.battery.cellType.value()) == BatteryCellType::_22P) target_mah = 2200;
if(BatteryCellType(configs.battery.cellType.value()) == BatteryCellType::HG2) target_mah = 3000;
if(BatteryCellType(configs.battery.cellType.value()) == BatteryCellType::MH1) target_mah = 3200;
if(BatteryCellType(configs.battery.cellType.value()) == BatteryCellType::VTC5) target_mah = 2600;
if(BatteryCellType(configs.battery.cellType.value()) == BatteryCellType::BAK_25R) target_mah = 2500;
if(BatteryCellType(configs.battery.cellType.value()) == BatteryCellType::HE4) target_mah = 2300;
2021-11-18 01:13:16 +01:00
return target_mah;
}
2021-11-07 13:04:19 +01:00
std::string getBatteryPercentageString()
{
2022-01-27 01:09:52 +01:00
if (const auto avgVoltage = controllers.getAvgVoltage(); avgVoltage)
2021-11-07 13:04:19 +01:00
{
2022-04-29 22:40:49 +02:00
std::string output = fmt::format("Battery: {:.1f}%", getBatteryPercentage(*avgVoltage, BatteryCellType(configs.battery.cellType.value())));
2022-01-27 01:09:52 +01:00
return output;
2021-11-07 13:04:19 +01:00
}
2022-01-27 01:09:52 +01:00
else
return "No Battery.";
2021-11-07 13:04:19 +01:00
}
2021-11-18 01:13:16 +01:00
std::string getBatteryAdvancedPercentageString()
{
std::string output = fmt::format("Battery: {:.1f}%", getPercentageByWh(drivingStatistics.batteryWhEstimate));
return output;
}
2021-11-07 13:04:19 +01:00
std::string getBatteryRemainingWattHoursString()
{
return fmt::format("{:.1f}Wh", getRemainingWattHours());
2021-11-07 13:04:19 +01:00
}
std::string getRemainingRangeString()
{
2022-04-29 22:40:49 +02:00
return fmt::format("{:.1f} km", getRemainingWattHours() / configs.battery.watthoursPerKilometer.value());
2021-11-07 13:04:19 +01:00
}
std::string getBatteryDebugString()
{
2022-01-27 01:09:52 +01:00
if (const auto avgVoltage = controllers.getAvgVoltage(); avgVoltage)
{
2022-01-27 01:09:52 +01:00
return fmt::format("{:.1f}V {}A", *avgVoltage, sumCurrent);
}
2022-01-27 01:09:52 +01:00
return "No Battery";
}
2021-12-11 05:05:46 +01:00
2022-03-04 21:30:13 +01:00
float getMinBatCellVoltage(BatteryCellType cellType) {
float minimumVoltage = std::numeric_limits<float>::max();
2022-02-28 00:26:17 +01:00
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;
}
2022-03-04 21:30:13 +01:00
default:
return 0.f;
2022-02-28 00:26:17 +01:00
}
2022-03-04 21:30:13 +01:00
return minimumVoltage;
2022-02-28 00:26:17 +01:00
}
2022-03-04 21:30:13 +01:00
float getMaxBatCellVoltage(BatteryCellType cellType)
2022-02-28 00:26:17 +01:00
{
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);
2022-02-28 21:59:28 +01:00
break;
}
case BatteryCellType::HG2:
{
BAT_CURVE_HG2(COUNT_CURVE_POINTS);
2022-02-28 21:59:28 +01:00
break;
}
case BatteryCellType::MH1:
{
BAT_CURVE_MH1(COUNT_CURVE_POINTS);
2022-02-28 21:59:28 +01:00
break;
}
case BatteryCellType::VTC5:
{
BAT_CURVE_VTC5(COUNT_CURVE_POINTS);
2022-02-28 21:59:28 +01:00
break;
}
case BatteryCellType::BAK_25R:
{
BAT_CURVE_25R(COUNT_CURVE_POINTS);
2022-02-28 21:59:28 +01:00
break;
}
case BatteryCellType::HE4:
{
BAT_CURVE_HE4(COUNT_CURVE_POINTS);
2022-02-28 21:59:28 +01:00
break;
}
}
return count;
}
2022-02-28 01:08:13 +01:00
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;
switch (cellType)
{
case BatteryCellType::_22P:
{
BAT_CURVE_22P(GET_POINT_N_VOLTAGES);
2022-02-28 21:59:28 +01:00
break;
2022-02-28 01:08:13 +01:00
}
case BatteryCellType::HG2:
{
BAT_CURVE_HG2(GET_POINT_N_VOLTAGES);
2022-02-28 21:59:28 +01:00
break;
2022-02-28 01:08:13 +01:00
}
case BatteryCellType::MH1:
{
BAT_CURVE_MH1(GET_POINT_N_VOLTAGES);
2022-02-28 21:59:28 +01:00
break;
2022-02-28 01:08:13 +01:00
}
case BatteryCellType::VTC5:
{
BAT_CURVE_VTC5(GET_POINT_N_VOLTAGES);
2022-02-28 21:59:28 +01:00
break;
2022-02-28 01:08:13 +01:00
}
case BatteryCellType::BAK_25R:
{
BAT_CURVE_25R(GET_POINT_N_VOLTAGES);
2022-02-28 21:59:28 +01:00
break;
2022-02-28 01:08:13 +01:00
}
case BatteryCellType::HE4:
{
BAT_CURVE_HE4(GET_POINT_N_VOLTAGES);
2022-02-28 21:59:28 +01:00
break;
2022-02-28 01:08:13 +01:00
}
}
return std::nullopt;
}
2021-12-11 05:05:46 +01:00
namespace battery {
2022-01-03 23:47:55 +01:00
std::optional<float> bootBatPercentage;
2022-01-04 21:16:33 +01:00
std::optional<float> bootBatWh;
2021-12-11 05:05:46 +01:00
}