Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPL: account for solar passthrough losses #307

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion include/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion src/PowerLimiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/WebApi_powerlimiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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>();
Expand Down
6 changes: 4 additions & 2 deletions webapp/src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
4 changes: 3 additions & 1 deletion webapp/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions webapp/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions webapp/src/types/PowerLimiterConfig.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
14 changes: 14 additions & 0 deletions webapp/src/views/PowerLimiterAdminView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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') }}:
Expand Down