diff --git a/docs/Battery.md b/docs/Battery.md index 50e546b5d8..c8d7008898 100644 --- a/docs/Battery.md +++ b/docs/Battery.md @@ -61,14 +61,19 @@ Configure min/max cell voltages using the following CLI setting: `vbat_hysteresis` - Sets the hysteresis value for low-battery alarms, in 0.1V units, i.e. 1 = 0.1V -e.g. +`vbat_duration_for_warning` - Period voltage has to sustain before the battery state is set to battery-warning, in 0.1 s, i.e. 60 = 6.0 seconds +`vbat_duration_for_critical` - Period voltage has to sustain before the battery state is set to battery-critical, in 0.1 s, i.e. 21 = 2.1 seconds + +e.g. ``` set vbat_scale = 110 set vbat_max_cell_voltage = 43 set vbat_min_cell_voltage = 33 set vbat_warning_cell_voltage = 34 set vbat_hysteresis = 1 +set vbat_duration_for_warning = 60 +set vbat_duration_for_critical = 20 ``` # Current Monitoring diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c index cedd8368b1..e3eef48e36 100644 --- a/src/main/cli/settings.c +++ b/src/main/cli/settings.c @@ -775,6 +775,8 @@ const clivalue_t valueTable[] = { { "force_battery_cell_count", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 24 }, PG_BATTERY_CONFIG, offsetof(batteryConfig_t, forceBatteryCellCount) }, { "vbat_lpf_period", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, UINT8_MAX }, PG_BATTERY_CONFIG, offsetof(batteryConfig_t, vbatLpfPeriod) }, { "ibat_lpf_period", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, UINT8_MAX }, PG_BATTERY_CONFIG, offsetof(batteryConfig_t, ibatLpfPeriod) }, + { "vbat_duration_for_warning", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, 150 }, PG_BATTERY_CONFIG, offsetof(batteryConfig_t, vbatDurationForWarning) }, + { "vbat_duration_for_critical", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, 150 }, PG_BATTERY_CONFIG, offsetof(batteryConfig_t, vbatDurationForCritical) }, // PG_VOLTAGE_SENSOR_ADC_CONFIG { "vbat_scale", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { VBAT_SCALE_MIN, VBAT_SCALE_MAX }, PG_VOLTAGE_SENSOR_ADC_CONFIG, offsetof(voltageSensorADCConfig_t, vbatscale) }, diff --git a/src/main/cms/cms_menu_osd.c b/src/main/cms/cms_menu_osd.c index 9748a41996..800336a1e4 100644 --- a/src/main/cms/cms_menu_osd.c +++ b/src/main/cms/cms_menu_osd.c @@ -43,6 +43,7 @@ #include "osd/osd.h" #include "osd/osd_elements.h" +#include "sensors/battery.h" #ifdef USE_EXTENDED_CMS_MENUS static uint16_t osdConfig_item_pos[OSD_ITEM_COUNT]; @@ -153,12 +154,16 @@ CMS_Menu menuOsdActiveElems = { static uint8_t osdConfig_rssi_alarm; static uint16_t osdConfig_cap_alarm; static uint16_t osdConfig_alt_alarm; +static uint8_t batteryConfig_vbatDurationForWarning; +static uint8_t batteryConfig_vbatDurationForCritical; static long menuAlarmsOnEnter(void) { osdConfig_rssi_alarm = osdConfig()->rssi_alarm; osdConfig_cap_alarm = osdConfig()->cap_alarm; osdConfig_alt_alarm = osdConfig()->alt_alarm; + batteryConfig_vbatDurationForWarning = batteryConfig()->vbatDurationForWarning; + batteryConfig_vbatDurationForCritical = batteryConfig()->vbatDurationForCritical; return 0; } @@ -170,6 +175,8 @@ static long menuAlarmsOnExit(const OSD_Entry *self) osdConfigMutable()->rssi_alarm = osdConfig_rssi_alarm; osdConfigMutable()->cap_alarm = osdConfig_cap_alarm; osdConfigMutable()->alt_alarm = osdConfig_alt_alarm; + batteryConfigMutable()->vbatDurationForWarning = batteryConfig_vbatDurationForWarning; + batteryConfigMutable()->vbatDurationForCritical = batteryConfig_vbatDurationForCritical; return 0; } @@ -180,6 +187,8 @@ const OSD_Entry menuAlarmsEntries[] = {"RSSI", OME_UINT8, NULL, &(OSD_UINT8_t){&osdConfig_rssi_alarm, 5, 90, 5}, 0}, {"MAIN BAT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_cap_alarm, 50, 30000, 50}, 0}, {"MAX ALT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_alt_alarm, 1, 200, 1}, 0}, + {"VBAT WARN DUR", OME_UINT8, NULL, &(OSD_UINT8_t){ &batteryConfig_vbatDurationForWarning, 0, 200, 1 }, 0 }, + {"VBAT CRIT DUR", OME_UINT8, NULL, &(OSD_UINT8_t){ &batteryConfig_vbatDurationForCritical, 0, 200, 1 }, 0 }, {"BACK", OME_Back, NULL, NULL, 0}, {NULL, OME_END, NULL, NULL, 0} }; diff --git a/src/main/sensors/battery.c b/src/main/sensors/battery.c index 4e72f3c8c7..716cc3faa7 100644 --- a/src/main/sensors/battery.c +++ b/src/main/sensors/battery.c @@ -116,6 +116,8 @@ PG_RESET_TEMPLATE(batteryConfig_t, batteryConfig, .vbatLpfPeriod = 30, .ibatLpfPeriod = 10, + .vbatDurationForWarning = 0, + .vbatDurationForCritical = 0, ); void batteryUpdateVoltage(timeUs_t currentTimeUs) @@ -228,24 +230,35 @@ void batteryUpdatePresence(void) static void batteryUpdateVoltageState(void) { // alerts are currently used by beeper, osd and other subsystems + static uint32_t lastVoltageChangeMs; switch (voltageState) { case BATTERY_OK: if (voltageMeter.filtered <= (batteryWarningVoltage - batteryConfig()->vbathysteresis)) { - voltageState = BATTERY_WARNING; + if (cmp32(millis(), lastVoltageChangeMs) >= batteryConfig()->vbatDurationForWarning * 100) { + voltageState = BATTERY_WARNING; + } + } else { + lastVoltageChangeMs = millis(); } break; case BATTERY_WARNING: if (voltageMeter.filtered <= (batteryCriticalVoltage - batteryConfig()->vbathysteresis)) { - voltageState = BATTERY_CRITICAL; - } else if (voltageMeter.filtered > batteryWarningVoltage) { - voltageState = BATTERY_OK; + if (cmp32(millis(), lastVoltageChangeMs) >= batteryConfig()->vbatDurationForCritical * 100) { + voltageState = BATTERY_CRITICAL; + } + } else { + if (voltageMeter.filtered > batteryWarningVoltage) { + voltageState = BATTERY_OK; + } + lastVoltageChangeMs = millis(); } break; case BATTERY_CRITICAL: if (voltageMeter.filtered > batteryCriticalVoltage) { voltageState = BATTERY_WARNING; + lastVoltageChangeMs = millis(); } break; diff --git a/src/main/sensors/battery.h b/src/main/sensors/battery.h index e59bdc9a8a..9078580619 100644 --- a/src/main/sensors/battery.h +++ b/src/main/sensors/battery.h @@ -63,6 +63,8 @@ typedef struct batteryConfig_s { uint8_t forceBatteryCellCount; // Number of cells in battery, used for overwriting auto-detected cell count if someone has issues with it. uint8_t vbatLpfPeriod; // Period of the cutoff frequency for the Vbat filter (in 0.1 s) uint8_t ibatLpfPeriod; // Period of the cutoff frequency for the Ibat filter (in 0.1 s) + uint8_t vbatDurationForWarning; // Period voltage has to sustain before the battery state is set to BATTERY_WARNING (in 0.1 s) + uint8_t vbatDurationForCritical; // Period voltage has to sustain before the battery state is set to BATTERY_CRIT (in 0.1 s) } batteryConfig_t; PG_DECLARE(batteryConfig_t, batteryConfig);