From a2d356dc78508eb91e21bff50657cca82e2a00dc Mon Sep 17 00:00:00 2001 From: Jon Mahoney Date: Mon, 19 Sep 2022 23:36:23 -0400 Subject: [PATCH] Watt Hours Drawn OSD Element and Post Flight Stat The Watt hours used element was added per a feature request to give another way of interpreting the battery usage. It was also added as a post flight stat to show consumption similar to the mAh post flight stat. This once again is just giving pilots another option that some may find useful. --- src/main/cli/settings.c | 1 + src/main/osd/osd.c | 9 +++++++++ src/main/osd/osd.h | 2 ++ src/main/osd/osd_elements.c | 16 ++++++++++++++++ src/main/sensors/battery.c | 24 ++++++++++++++++++++++-- src/main/sensors/battery.h | 1 + src/test/unit/link_quality_unittest.cc | 1 + src/test/unit/osd_unittest.cc | 6 ++++++ 8 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c index 83154c140e..126e5e51a2 100644 --- a/src/main/cli/settings.c +++ b/src/main/cli/settings.c @@ -1360,6 +1360,7 @@ const clivalue_t valueTable[] = { { "osd_ah_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_ARTIFICIAL_HORIZON]) }, { "osd_current_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_CURRENT_DRAW]) }, { "osd_mah_drawn_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_MAH_DRAWN]) }, + { "osd_wh_drawn_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_WATT_HOURS_DRAWN]) }, { "osd_motor_diag_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_MOTOR_DIAG]) }, { "osd_craft_name_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_CRAFT_NAME]) }, { "osd_display_name_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_DISPLAY_NAME]) }, diff --git a/src/main/osd/osd.c b/src/main/osd/osd.c index a5dd7e08e5..495ea98898 100644 --- a/src/main/osd/osd.c +++ b/src/main/osd/osd.c @@ -187,6 +187,7 @@ const osd_stats_e osdStatsDisplayOrder[OSD_STAT_COUNT] = { OSD_STAT_TOTAL_FLIGHTS, OSD_STAT_TOTAL_TIME, OSD_STAT_TOTAL_DIST, + OSD_STAT_WATT_HOURS_DRAWN, }; // Group elements in a number of groups to reduce task scheduling overhead @@ -780,6 +781,14 @@ static bool osdDisplayStat(int statistic, uint8_t displayRow) return true; } break; + + case OSD_STAT_WATT_HOURS_DRAWN: + if (batteryConfig()->currentMeterSource != CURRENT_METER_NONE) { + osdPrintFloat(buff, SYM_NONE, getWhDrawn(), "", 2, true, SYM_NONE); + osdDisplayStatisticLabel(displayRow, "USED WATT HOURS", buff); + return true; + } + break; #ifdef USE_BLACKBOX case OSD_STAT_BLACKBOX: diff --git a/src/main/osd/osd.h b/src/main/osd/osd.h index 734db48542..642c336998 100644 --- a/src/main/osd/osd.h +++ b/src/main/osd/osd.h @@ -161,6 +161,7 @@ typedef enum { OSD_TOTAL_FLIGHTS, OSD_UP_DOWN_REFERENCE, OSD_TX_UPLINK_POWER, + OSD_WATT_HOURS_DRAWN, OSD_ITEM_COUNT // MUST BE LAST } osd_items_e; @@ -200,6 +201,7 @@ typedef enum { OSD_STAT_TOTAL_TIME, OSD_STAT_TOTAL_DIST, OSD_STAT_MIN_RSSI_DBM, + OSD_STAT_WATT_HOURS_DRAWN, OSD_STAT_COUNT // MUST BE LAST } osd_stats_e; diff --git a/src/main/osd/osd_elements.c b/src/main/osd/osd_elements.c index 17a9b64bba..3bbc87bfa1 100644 --- a/src/main/osd/osd_elements.c +++ b/src/main/osd/osd_elements.c @@ -1166,6 +1166,20 @@ static void osdElementMahDrawn(osdElementParms_t *element) tfp_sprintf(element->buff, "%4d%c", getMAhDrawn(), SYM_MAH); } +static void osdElementWattHoursDrawn(osdElementParms_t *element) +{ + const float wattHoursDrawn = getWhDrawn(); + + if (wattHoursDrawn < 1.0f) { + tfp_sprintf(element->buff, "%3dMWH", lrintf(wattHoursDrawn * 1000)); + } else { + int wattHourWholeNumber = (int)wattHoursDrawn; + int wattHourDecimalValue = (int)((wattHoursDrawn - wattHourWholeNumber) * 100); + + tfp_sprintf(element->buff, wattHourDecimalValue >= 10 ? "%3d.%2dWH" : "%3d.0%1dWH", wattHourWholeNumber, wattHourDecimalValue); + } +} + static void osdElementMainBatteryUsage(osdElementParms_t *element) { // Set length of indicator bar @@ -1524,6 +1538,7 @@ static const uint8_t osdElementDisplayOrder[] = { OSD_VTX_CHANNEL, OSD_CURRENT_DRAW, OSD_MAH_DRAWN, + OSD_WATT_HOURS_DRAWN, OSD_CRAFT_NAME, OSD_ALTITUDE, OSD_ROLL_PIDS, @@ -1610,6 +1625,7 @@ const osdElementDrawFn osdElementDrawFunction[OSD_ITEM_COUNT] = { #endif [OSD_CURRENT_DRAW] = osdElementCurrentDraw, [OSD_MAH_DRAWN] = osdElementMahDrawn, + [OSD_WATT_HOURS_DRAWN] = osdElementWattHoursDrawn, #ifdef USE_GPS [OSD_GPS_SPEED] = osdElementGpsSpeed, [OSD_GPS_SATS] = osdElementGpsSats, diff --git a/src/main/sensors/battery.c b/src/main/sensors/battery.c index cc2918f3a3..0331fb6fd8 100644 --- a/src/main/sensors/battery.c +++ b/src/main/sensors/battery.c @@ -75,13 +75,14 @@ static uint16_t batteryCriticalVoltage; static uint16_t batteryWarningHysteresisVoltage; static uint16_t batteryCriticalHysteresisVoltage; static lowVoltageCutoff_t lowVoltageCutoff; -// + static currentMeter_t currentMeter; static voltageMeter_t voltageMeter; static batteryState_e batteryState; static batteryState_e voltageState; static batteryState_e consumptionState; +static float wattHoursDrawn; #ifndef DEFAULT_CURRENT_METER_SOURCE #ifdef USE_VIRTUAL_CURRENT_METER @@ -197,7 +198,6 @@ static bool isVoltageFromBat(void) void batteryUpdatePresence(void) { - if ((voltageState == BATTERY_NOT_PRESENT || voltageState == BATTERY_INIT) && isVoltageFromBat() && isVoltageStable()) { // Battery has just been connected - calculate cells, warning voltages and reset state @@ -232,9 +232,18 @@ void batteryUpdatePresence(void) batteryCriticalVoltage = 0; batteryWarningHysteresisVoltage = 0; batteryCriticalHysteresisVoltage = 0; + wattHoursDrawn = 0.0; } } +void batteryUpdateWhDrawn(void) +{ + static int32_t mAhDrawnPrev = 0; + const int32_t mAhDrawnCurrent = getMAhDrawn(); + wattHoursDrawn += voltageMeter.displayFiltered * (mAhDrawnCurrent - mAhDrawnPrev) / 100000.0f; + mAhDrawnPrev = mAhDrawnCurrent; +} + static void batteryUpdateVoltageState(void) { // alerts are currently used by beeper, osd and other subsystems @@ -317,6 +326,7 @@ void batteryUpdateStates(timeUs_t currentTimeUs) batteryUpdateConsumptionState(); batteryUpdateLVC(currentTimeUs); batteryState = MAX(voltageState, consumptionState); + batteryUpdateWhDrawn(); } const lowVoltageCutoff_t *getLowVoltageCutoff(void) @@ -354,6 +364,11 @@ void batteryInit(void) batteryState = BATTERY_INIT; batteryCellCount = 0; + // + // Consumption + // + wattHoursDrawn = 0; + // // voltage // @@ -565,3 +580,8 @@ void setMAhDrawn(uint32_t mAhDrawn) currentMeter.mAhDrawnOffset = mAhDrawn; } #endif + +float getWhDrawn(void) +{ + return wattHoursDrawn; +} diff --git a/src/main/sensors/battery.h b/src/main/sensors/battery.h index d907412c18..11ac3a4e69 100644 --- a/src/main/sensors/battery.h +++ b/src/main/sensors/battery.h @@ -120,6 +120,7 @@ bool isAmperageConfigured(void); int32_t getAmperage(void); int32_t getAmperageLatest(void); int32_t getMAhDrawn(void); +float getWhDrawn(void); #ifdef USE_BATTERY_CONTINUE bool hasUsedMAh(); void setMAhDrawn(uint32_t mAhDrawn); diff --git a/src/test/unit/link_quality_unittest.cc b/src/test/unit/link_quality_unittest.cc index 87d97b8810..8243974366 100644 --- a/src/test/unit/link_quality_unittest.cc +++ b/src/test/unit/link_quality_unittest.cc @@ -479,6 +479,7 @@ extern "C" { uint16_t getBatteryAverageCellVoltage() { return 420; } int32_t getAmperage() { return 0; } int32_t getMAhDrawn() { return 0; } + float getWhDrawn() { return 0.0; } int32_t getEstimatedAltitudeCm() { return 0; } int32_t getEstimatedVario() { return 0; } int32_t blackboxGetLogNumber() { return 0; } diff --git a/src/test/unit/osd_unittest.cc b/src/test/unit/osd_unittest.cc index 2f28bd6cfe..c60b760e4b 100644 --- a/src/test/unit/osd_unittest.cc +++ b/src/test/unit/osd_unittest.cc @@ -100,6 +100,7 @@ extern "C" { uint16_t simulationBatteryVoltage; uint32_t simulationBatteryAmperage; uint32_t simulationMahDrawn; + float simulationWhDrawn; int32_t simulationAltitude; int32_t simulationVerticalSpeed; uint16_t simulationCoreTemperature; @@ -128,6 +129,7 @@ void setDefaultSimulationState() simulationBatteryVoltage = 1680; simulationBatteryAmperage = 0; simulationMahDrawn = 0; + simulationWhDrawn = 0; simulationAltitude = 0; simulationVerticalSpeed = 0; simulationCoreTemperature = 0; @@ -1324,6 +1326,10 @@ extern "C" { return simulationMahDrawn; } + float getWhDrawn() { + return simulationWhDrawn; + } + int32_t getEstimatedAltitudeCm() { return simulationAltitude; }