DPL: account for solar passthrough losses (#307)
* fix another fixable "passtrough" typo the typo in the config's identifier is not changed to preserve compatibility while not spending the effort to migrate the setting. * webapp language: prefer SoC over SOC * DPL: implement solar passthrough loss factor in (full) solar passthrough mode, the inverter output power is coupled to the charge controler output power. the inverter efficiency is already accounted for. however, the battery might still be slowly discharged for two reasons: (1) line losses are not accounted for and (2) the inverter outputs a little bit more than permitted by the power limit. this is undesirable since the battery is significantly drained if solar passthrough is active for a longer period of time. also, when using full solar passthrough and a battery communication interface, the SoC will slowly degrade to a value below the threshold value for full solar passthrough. this makes the system switch from charging the battery (potentially rapidly) to discharging the battery slowly. this switch might happen in rather fast succession. that's effectively trickle-charging the battery. instead, this new factor helps to account for line losses between the solar charge controller and the inverter, such that the battery is actually not involved in solar passthrough. the value can be increased until it is observed that the battery is not discharging when solar passthrough is active.
This commit is contained in:
parent
95d7ac7adf
commit
f3297930b5
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -314,7 +314,10 @@ int32_t PowerLimiterClass::inverterPowerDcToAc(std::shared_ptr<InverterAbstract>
|
||||
// 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<float>(config.PowerLimiter_SolarPassThroughLosses)/100;
|
||||
|
||||
return dcPower * inverterEfficiencyFactor * lossesFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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<bool>();
|
||||
PowerLimiter.setMode(PL_MODE_ENABLE_NORMAL_OP); // User input sets PL to normal operation
|
||||
config.PowerLimiter_SolarPassThroughEnabled = root[F("solar_passthrough_enabled")].as<bool>();
|
||||
config.PowerLimiter_SolarPassThroughLosses = root[F("solar_passthrough_losses")].as<uint8_t>();
|
||||
config.PowerLimiter_BatteryDrainStategy= root[F("battery_drain_strategy")].as<uint8_t>();
|
||||
config.PowerLimiter_IsInverterBehindPowerMeter = root[F("is_inverter_behind_powermeter")].as<bool>();
|
||||
config.PowerLimiter_InverterId = root[F("inverter_id")].as<uint8_t>();
|
||||
|
||||
@ -532,6 +532,8 @@
|
||||
"General": "Allgemein",
|
||||
"Enable": "Aktiviert",
|
||||
"EnableSolarPassthrough": "Aktiviere Solar-Passthrough",
|
||||
"SolarPassthroughLosses": "(Full) Solar-Passthrough Verluste:",
|
||||
"SolarPassthroughLossesInfo": "<b>Hinweis:</b> 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",
|
||||
|
||||
@ -536,6 +536,8 @@
|
||||
"General": "General",
|
||||
"Enable": "Enable",
|
||||
"EnableSolarPassthrough": "Enable Solar-Passthrough",
|
||||
"SolarPassthroughLosses": "(Full) Solar Passthrough Losses:",
|
||||
"SolarPassthroughLossesInfo": "<b>Hint:</b> 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",
|
||||
|
||||
@ -555,6 +555,8 @@
|
||||
"General": "General",
|
||||
"Enable": "Enable",
|
||||
"EnableSolarPassthrough": "Enable Solar-Passthrough",
|
||||
"SolarPassthroughLosses": "(Full) Solar Passthrough Losses:",
|
||||
"SolarPassthroughLossesInfo": "<b>Hint:</b> 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",
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -30,6 +30,20 @@
|
||||
|
||||
<div class="alert alert-secondary" v-show="powerLimiterConfigList.enabled" role="alert" v-html="$t('powerlimiteradmin.SolarpassthroughInfo')"></div>
|
||||
|
||||
<div class="row mb-3" v-show="powerLimiterConfigList.enabled && powerLimiterConfigList.solar_passthrough_enabled">
|
||||
<label for="solarPassthroughLosses" class="col-sm-2 col-form-label">{{ $t('powerlimiteradmin.SolarPassthroughLosses') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" id="solarPassthroughLosses"
|
||||
placeholder="3" v-model="powerLimiterConfigList.solar_passthrough_losses"
|
||||
aria-describedby="solarPassthroughLossesDescription" min="0" max="10" required/>
|
||||
<span class="input-group-text" id="solarPassthroughLossesDescription">%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-secondary" role="alert" v-show="powerLimiterConfigList.enabled && powerLimiterConfigList.solar_passthrough_enabled" v-html="$t('powerlimiteradmin.SolarPassthroughLossesInfo')"></div>
|
||||
|
||||
<div class="row mb-3" v-show="powerLimiterConfigList.enabled">
|
||||
<label for="inputTimezone" class="col-sm-2 col-form-label">
|
||||
{{ $t('powerlimiteradmin.InverterId') }}:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user