diff --git a/include/Configuration.h b/include/Configuration.h index 2c588748..25bf284c 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -141,6 +141,7 @@ struct CONFIG_T { bool PowerLimiter_Enabled; bool PowerLimiter_SolarPassThroughEnabled; + uint8_t PowerLimiter_SolarPassThroughLosses; uint8_t PowerLimiter_BatteryDrainStategy; uint32_t PowerLimiter_Interval; bool PowerLimiter_IsInverterBehindPowerMeter; diff --git a/include/defaults.h b/include/defaults.h index c069ca10..4e9ed73e 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -107,7 +107,8 @@ #define POWERLIMITER_ENABLED false -#define POWERLIMITER_SOLAR_PASSTROUGH_ENABLED true +#define POWERLIMITER_SOLAR_PASSTHROUGH_ENABLED true +#define POWERLIMITER_SOLAR_PASSTHROUGH_LOSSES 3 #define POWERLIMITER_BATTERY_DRAIN_STRATEGY 0 #define POWERLIMITER_INTERVAL 10 #define POWERLIMITER_IS_INVERTER_BEHIND_POWER_METER true diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 3924315c..a1d99257 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -151,6 +151,7 @@ bool ConfigurationClass::write() JsonObject powerlimiter = doc.createNestedObject("powerlimiter"); powerlimiter["enabled"] = config.PowerLimiter_Enabled; powerlimiter["solar_passtrough_enabled"] = config.PowerLimiter_SolarPassThroughEnabled; + powerlimiter["solar_passtrough_losses"] = config.PowerLimiter_SolarPassThroughLosses; powerlimiter["battery_drain_strategy"] = config.PowerLimiter_BatteryDrainStategy; powerlimiter["interval"] = config.PowerLimiter_Interval; powerlimiter["is_inverter_behind_powermeter"] = config.PowerLimiter_IsInverterBehindPowerMeter; @@ -358,7 +359,8 @@ bool ConfigurationClass::read() JsonObject powerlimiter = doc["powerlimiter"]; config.PowerLimiter_Enabled = powerlimiter["enabled"] | POWERLIMITER_ENABLED; - config.PowerLimiter_SolarPassThroughEnabled = powerlimiter["solar_passtrough_enabled"] | POWERLIMITER_SOLAR_PASSTROUGH_ENABLED; + config.PowerLimiter_SolarPassThroughEnabled = powerlimiter["solar_passtrough_enabled"] | POWERLIMITER_SOLAR_PASSTHROUGH_ENABLED; + config.PowerLimiter_SolarPassThroughLosses = powerlimiter["solar_passthrough_losses"] | POWERLIMITER_SOLAR_PASSTHROUGH_LOSSES; config.PowerLimiter_BatteryDrainStategy = powerlimiter["battery_drain_strategy"] | POWERLIMITER_BATTERY_DRAIN_STRATEGY; config.PowerLimiter_Interval = powerlimiter["interval"] | POWERLIMITER_INTERVAL; config.PowerLimiter_IsInverterBehindPowerMeter = powerlimiter["is_inverter_behind_powermeter"] | POWERLIMITER_IS_INVERTER_BEHIND_POWER_METER; diff --git a/src/PowerLimiter.cpp b/src/PowerLimiter.cpp index 29a57677..7d5f0652 100644 --- a/src/PowerLimiter.cpp +++ b/src/PowerLimiter.cpp @@ -314,7 +314,10 @@ int32_t PowerLimiterClass::inverterPowerDcToAc(std::shared_ptr // is currently not producing (efficiency is zero in that case) float inverterEfficiencyFactor = (inverterEfficiencyPercent > 0) ? inverterEfficiencyPercent/100 : 0.967; - return dcPower * inverterEfficiencyFactor; + // account for losses between solar charger and inverter (cables, junctions...) + float lossesFactor = 1.00 - static_cast(config.PowerLimiter_SolarPassThroughLosses)/100; + + return dcPower * inverterEfficiencyFactor * lossesFactor; } /** diff --git a/src/WebApi_powerlimiter.cpp b/src/WebApi_powerlimiter.cpp index 38ce954c..edf0b6c6 100644 --- a/src/WebApi_powerlimiter.cpp +++ b/src/WebApi_powerlimiter.cpp @@ -39,6 +39,7 @@ void WebApiPowerLimiterClass::onStatus(AsyncWebServerRequest* request) root[F("enabled")] = config.PowerLimiter_Enabled; root[F("solar_passthrough_enabled")] = config.PowerLimiter_SolarPassThroughEnabled; + root[F("solar_passthrough_losses")] = config.PowerLimiter_SolarPassThroughLosses; root[F("battery_drain_strategy")] = config.PowerLimiter_BatteryDrainStategy; root[F("is_inverter_behind_powermeter")] = config.PowerLimiter_IsInverterBehindPowerMeter; root[F("inverter_id")] = config.PowerLimiter_InverterId; @@ -125,6 +126,7 @@ void WebApiPowerLimiterClass::onAdminPost(AsyncWebServerRequest* request) config.PowerLimiter_Enabled = root[F("enabled")].as(); PowerLimiter.setMode(PL_MODE_ENABLE_NORMAL_OP); // User input sets PL to normal operation config.PowerLimiter_SolarPassThroughEnabled = root[F("solar_passthrough_enabled")].as(); + config.PowerLimiter_SolarPassThroughLosses = root[F("solar_passthrough_losses")].as(); config.PowerLimiter_BatteryDrainStategy= root[F("battery_drain_strategy")].as(); config.PowerLimiter_IsInverterBehindPowerMeter = root[F("is_inverter_behind_powermeter")].as(); config.PowerLimiter_InverterId = root[F("inverter_id")].as(); diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index 86aceb6f..a364d50e 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -532,6 +532,8 @@ "General": "Allgemein", "Enable": "Aktiviert", "EnableSolarPassthrough": "Aktiviere Solar-Passthrough", + "SolarPassthroughLosses": "(Full) Solar-Passthrough Verluste:", + "SolarPassthroughLossesInfo": "Hinweis: Bei der Übertragung von Energie vom Solarladeregler zum Inverter sind Leitungsverluste zu erwarten. Um eine schleichende Entladung der Batterie im (Full) Solar-Passthrough Modus zu unterbinden, können diese Verluste berücksichtigt werden. Das am Inverter einzustellende Power Limit wird nach Berücksichtigung von dessen Effizienz zusätzlich um diesen Faktor verringert.", "BatteryDrainStrategy": "Strategie zur Batterieentleerung", "BatteryDrainWhenFull": "Leeren, wenn voll", "BatteryDrainAtNight": "Leeren zur Nacht", @@ -750,8 +752,8 @@ "Property": "Eigenschaft", "Value": "Wert", "Unit": "Einheit", - "stateOfCharge": "Ladezustand (SOC)", - "stateOfHealth": "Batteriezustand (SOH)", + "stateOfCharge": "Ladezustand (SoC)", + "stateOfHealth": "Batteriezustand (SoH)", "voltage": "Spannung", "current": "Strom", "temperature": "Temperatur", diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 23cd4e6f..65132c2a 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -536,6 +536,8 @@ "General": "General", "Enable": "Enable", "EnableSolarPassthrough": "Enable Solar-Passthrough", + "SolarPassthroughLosses": "(Full) Solar Passthrough Losses:", + "SolarPassthroughLossesInfo": "Hint: Line losses are to be expected when transferring energy from the solar charge controller to the inverter. These losses can be taken into account to prevent the battery from gradually discharging in (full) solar passthrough mode. The power limit to be set on the inverter is additionally reduced by this factor after taking its efficiency into account.", "BatteryDrainStrategy": "Battery drain strategy", "BatteryDrainWhenFull": "Empty when full", "BatteryDrainAtNight": "Empty at night", @@ -557,7 +559,7 @@ "BatterySocStartThreshold": "Battery SOC - Start threshold", "BatterySocStopThreshold": "Battery SOC - Stop threshold", "BatterySocSolarPassthroughStartThreshold": "Battery SOC - Start threshold for full solar passthrough", - "BatterySocSolarPassthroughStartThresholdHint": "Inverter power is set according to Victron MPPT power (minus efficiency factors) if battery SOC is over this limit. Use this if you like to supply excess power to the grid when battery is full", + "BatterySocSolarPassthroughStartThresholdHint": "Inverter power is set according to Victron MPPT power (minus efficiency factors) if battery SoC is over this limit. Use this if you like to supply excess power to the grid when battery is full", "VoltageStartThreshold": "DC Voltage - Start threshold", "VoltageStopThreshold": "DC Voltage - Stop threshold", "VoltageSolarPassthroughStartThreshold": "DC Voltage - Start threshold for full solar passthrough", diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index f739bf8e..b7475b58 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -555,6 +555,8 @@ "General": "General", "Enable": "Enable", "EnableSolarPassthrough": "Enable Solar-Passthrough", + "SolarPassthroughLosses": "(Full) Solar Passthrough Losses:", + "SolarPassthroughLossesInfo": "Hint: Line losses are to be expected when transferring energy from the solar charge controller to the inverter. These losses can be taken into account to prevent the battery from gradually discharging in (full) solar passthrough mode. The power limit to be set on the inverter is additionally reduced by this factor after taking its efficiency into account.", "BatteryDrainStrategy": "Battery drain strategy", "BatteryDrainWhenFull": "Empty when full", "BatteryDrainAtNight": "Empty at night", diff --git a/webapp/src/types/PowerLimiterConfig.ts b/webapp/src/types/PowerLimiterConfig.ts index c7b9bcb3..ff11f313 100644 --- a/webapp/src/types/PowerLimiterConfig.ts +++ b/webapp/src/types/PowerLimiterConfig.ts @@ -1,6 +1,7 @@ export interface PowerLimiterConfig { enabled: boolean; solar_passthrough_enabled: boolean; + solar_passthrough_losses: number; battery_drain_strategy: number; is_inverter_behind_powermeter: boolean; inverter_id: number; diff --git a/webapp/src/views/PowerLimiterAdminView.vue b/webapp/src/views/PowerLimiterAdminView.vue index 4fb99210..90dd522f 100644 --- a/webapp/src/views/PowerLimiterAdminView.vue +++ b/webapp/src/views/PowerLimiterAdminView.vue @@ -30,6 +30,20 @@ +
+ +
+
+ + % +
+
+
+ + +