From 820891222c8375260e4fe38f79456895ea5423ac Mon Sep 17 00:00:00 2001 From: Tobias Diedrich Date: Sat, 28 Sep 2024 16:40:34 +0200 Subject: [PATCH] Feature: add SoC & voltage thresholds for battery current limit This changes the custom current limit so the custom limit is only applied when any of: - SoC is valid and not ignored and SoC < threshold - Voltage is valid and Voltage < threshold - Voltage is invalid Independently, if "Use Battery-Reported limit" is enabled and valid, it is applied (unless a lower custom limit already was applied). --- include/Configuration.h | 2 ++ include/defaults.h | 2 ++ src/Battery.cpp | 20 ++++++++++++++++---- src/Configuration.cpp | 4 ++++ webapp/src/locales/de.json | 4 ++++ webapp/src/locales/en.json | 4 ++++ webapp/src/types/BatteryConfig.ts | 2 ++ webapp/src/views/BatteryAdminView.vue | 22 ++++++++++++++++++++++ 8 files changed, 56 insertions(+), 4 deletions(-) diff --git a/include/Configuration.h b/include/Configuration.h index 3b99c38bb..49b1c60cc 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -145,6 +145,8 @@ struct BATTERY_CONFIG_T { BatteryVoltageUnit MqttVoltageUnit; bool EnableDischargeCurrentLimit; float DischargeCurrentLimit; + float DischargeCurrentLimitBelowSoc; + float DischargeCurrentLimitBelowVoltage; bool UseBatteryReportedDischargeCurrentLimit; char MqttDischargeCurrentTopic[MQTT_MAX_TOPIC_STRLEN + 1]; char MqttDischargeCurrentJsonPath[BATTERY_JSON_MAX_PATH_STRLEN + 1]; diff --git a/include/defaults.h b/include/defaults.h index 2ab8ec9e8..40ee5af12 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -156,6 +156,8 @@ #define BATTERY_JKBMS_POLLING_INTERVAL 5 #define BATTERY_ENABLE_DISCHARGE_CURRENT_LIMIT false #define BATTERY_DISCHARGE_CURRENT_LIMIT 0.0 +#define BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_SOC 100.0 +#define BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_VOLTAGE 60.0 #define BATTERY_USE_BATTERY_REPORTED_DISCHARGE_CURRENT_LIMIT false #define HUAWEI_ENABLED false diff --git a/src/Battery.cpp b/src/Battery.cpp index 7483c1de4..106888e2b 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -91,14 +91,26 @@ float BatteryClass::getDischargeCurrentLimit() if (!config.Battery.EnableDischargeCurrentLimit) { return FLT_MAX; } auto dischargeCurrentLimit = config.Battery.DischargeCurrentLimit; - auto dischargeCurrentValid = dischargeCurrentLimit > 0.0f; - + auto dischargeCurrentLimitValid = dischargeCurrentLimit > 0.0f; + auto dischargeCurrentLimitBelowSoc = config.Battery.DischargeCurrentLimitBelowSoc; + auto dischargeCurrentLimitBelowVoltage = config.Battery.DischargeCurrentLimitBelowVoltage; + auto statsSoCValid = getStats()->getSoCAgeSeconds() <= 60 && !config.PowerLimiter.IgnoreSoc; + auto statsSoC = statsSoCValid ? getStats()->getSoC() : 100.0; // fail open so we use voltage instead + auto statsVoltageValid = getStats()->getVoltageAgeSeconds() <= 60; + auto statsVoltage = statsVoltageValid ? getStats()->getVoltage() : 0.0; // fail closed auto statsCurrentLimit = getStats()->getDischargeCurrentLimit(); auto statsLimitValid = config.Battery.UseBatteryReportedDischargeCurrentLimit && statsCurrentLimit >= 0.0f && getStats()->getDischargeCurrentLimitAgeSeconds() <= 60; - if (statsLimitValid && dischargeCurrentValid) { + + if (statsSoC > dischargeCurrentLimitBelowSoc && statsVoltage > dischargeCurrentLimitBelowVoltage) { + // Above SoC and Voltage thresholds, ignore custom limit. + // Battery-provided limit will still be applied. + dischargeCurrentLimitValid = false; + } + + if (statsLimitValid && dischargeCurrentLimitValid) { // take the lowest limit return min(statsCurrentLimit, dischargeCurrentLimit); } @@ -107,7 +119,7 @@ float BatteryClass::getDischargeCurrentLimit() return statsCurrentLimit; } - if (dischargeCurrentValid) { + if (dischargeCurrentLimitValid) { return dischargeCurrentLimit; } diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 61ee7758d..b260ccee2 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -88,6 +88,8 @@ void ConfigurationClass::serializeBatteryConfig(BatteryConfig const& source, Jso target["mqtt_voltage_unit"] = config.Battery.MqttVoltageUnit; target["enable_discharge_current_limit"] = config.Battery.EnableDischargeCurrentLimit; target["discharge_current_limit"] = config.Battery.DischargeCurrentLimit; + target["discharge_current_limit_below_soc"] = config.Battery.DischargeCurrentLimitBelowSoc; + target["discharge_current_limit_below_voltage"] = config.Battery.DischargeCurrentLimitBelowVoltage; target["use_battery_reported_discharge_current_limit"] = config.Battery.UseBatteryReportedDischargeCurrentLimit; target["mqtt_discharge_current_topic"] = config.Battery.MqttDischargeCurrentTopic; target["mqtt_discharge_current_json_path"] = config.Battery.MqttDischargeCurrentJsonPath; @@ -383,6 +385,8 @@ void ConfigurationClass::deserializeBatteryConfig(JsonObject const& source, Batt target.MqttVoltageUnit = source["mqtt_voltage_unit"] | BatteryVoltageUnit::Volts; target.EnableDischargeCurrentLimit = source["enable_discharge_current_limit"] | BATTERY_ENABLE_DISCHARGE_CURRENT_LIMIT; target.DischargeCurrentLimit = source["discharge_current_limit"] | BATTERY_DISCHARGE_CURRENT_LIMIT; + target.DischargeCurrentLimitBelowSoc = source["discharge_current_limit_below_soc"] | BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_SOC; + target.DischargeCurrentLimitBelowVoltage = source["discharge_current_limit_below_voltage"] | BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_VOLTAGE; target.UseBatteryReportedDischargeCurrentLimit = source["use_battery_reported_discharge_current_limit"] | BATTERY_USE_BATTERY_REPORTED_DISCHARGE_CURRENT_LIMIT; strlcpy(target.MqttDischargeCurrentTopic, source["mqtt_discharge_current_topic"] | "", sizeof(config.Battery.MqttDischargeCurrentTopic)); strlcpy(target.MqttDischargeCurrentJsonPath, source["mqtt_discharge_current_json_path"] | "", sizeof(config.Battery.MqttDischargeCurrentJsonPath)); diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index 1a16673b3..b2d7de185 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -724,6 +724,10 @@ "DischargeCurrentLimitConfiguration": "Einstellungen Entladestromlimit", "LimitDischargeCurrent": "Entladestrom limitieren", "DischargeCurrentLimit": "max. Entladestrom", + "DischargeCurrentLimitBelowSoc": "Limitieren unter SoC", + "DischargeCurrentLimitBelowSocInfo": "Das Entladestromlimit wird nur unter dieser SoC-Schwelle angewendet (nicht verwendet falls 'Batterie SoC ignorieren' aktiviert ist).", + "DischargeCurrentLimitBelowVoltage": "Limitieren unter Spannung", + "DischargeCurrentLimitBelowVoltageInfo": "Das Entladestromlimit wird nur unter dieser Spannungs-Schwelle angewendet (wenn SoC ignoriert oder nicht verfügbar).", "UseBatteryReportedDischargeCurrentLimit": "Von der Batterie übermitteltes Limit verwenden", "BatteryReportedDischargeCurrentLimitInfo": "Hinweis: Das niedrigste Limit wird angewendet, wobei das von der Batterie übermittelte Entladestromlimit nur verwendet wird, wenn in der letzten Minute ein Update eingegangen ist; andernfalls dient das zuvor festgelegte Limit als Fallback.", "MqttDischargeCurrentTopic": "Topic für Entladestromlimit", diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 69a288778..425ad9972 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -727,6 +727,10 @@ "DischargeCurrentLimitConfiguration": "Discharge Current Limit Settings", "LimitDischargeCurrent": "Limit Discharge Current", "DischargeCurrentLimit": "max. Discharge Current", + "DischargeCurrentLimitBelowSoc": "Apply limit below SoC", + "DischargeCurrentLimitBelowSocInfo": "The discharge current limit is not applied above this SoC (not used if 'Ignore Battery SoC' is enabled).", + "DischargeCurrentLimitBelowVoltage": "Apply limit below voltage", + "DischargeCurrentLimitBelowVoltageInfo": "The discharge current limit is not applied above this voltage (used if SoC ignored or unavailable).", "UseBatteryReportedDischargeCurrentLimit": "Use Battery-Reported limit", "BatteryReportedDischargeCurrentLimitInfo": "Hint: The lowest limit will be applied, with the battery-reported discharge current limit used only if an update was received in the last minute; otherwise, the previously specified limit will act as a fallback.", "MqttDischargeCurrentTopic": "Discharge Current Limit Value Topic", diff --git a/webapp/src/types/BatteryConfig.ts b/webapp/src/types/BatteryConfig.ts index a781b74a0..67792a710 100644 --- a/webapp/src/types/BatteryConfig.ts +++ b/webapp/src/types/BatteryConfig.ts @@ -11,6 +11,8 @@ export interface BatteryConfig { mqtt_voltage_unit: number; enable_discharge_current_limit: boolean; discharge_current_limit: number; + discharge_current_limit_below_soc: number; + discharge_current_limit_below_voltage: number; use_battery_reported_discharge_current_limit: boolean; mqtt_discharge_current_topic: string; mqtt_discharge_current_json_path: string; diff --git a/webapp/src/views/BatteryAdminView.vue b/webapp/src/views/BatteryAdminView.vue index 4a07357c7..b55b88e51 100644 --- a/webapp/src/views/BatteryAdminView.vue +++ b/webapp/src/views/BatteryAdminView.vue @@ -141,6 +141,28 @@ postfix="A" /> + + + +