From 36fc00ae3a2a653b6335dec133f2ff32459d5b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bo=CC=88hm?= Date: Mon, 23 Dec 2024 00:09:24 +0100 Subject: [PATCH] Feature: support configuration of the input power threshold for overscaling per inverter --- include/Configuration.h | 1 + include/defaults.h | 1 + src/Configuration.cpp | 2 ++ src/PowerLimiterSolarInverter.cpp | 4 ++-- webapp/src/locales/de.json | 2 ++ webapp/src/locales/en.json | 2 ++ webapp/src/locales/fr.json | 2 ++ webapp/src/types/PowerLimiterConfig.ts | 1 + webapp/src/views/PowerLimiterAdminView.vue | 12 ++++++++++++ 9 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/Configuration.h b/include/Configuration.h index 0990e30a9..42d861418 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -141,6 +141,7 @@ struct POWERLIMITER_INVERTER_CONFIG_T { bool UseOverscaling; uint16_t LowerPowerLimit; uint16_t UpperPowerLimit; + uint8_t ScalingThreshold; }; using PowerLimiterInverterConfig = struct POWERLIMITER_INVERTER_CONFIG_T; diff --git a/include/defaults.h b/include/defaults.h index 0001af41c..7d554e2e9 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -139,6 +139,7 @@ #define POWERLIMITER_LOWER_POWER_LIMIT 10 #define POWERLIMITER_BASE_LOAD_LIMIT 100 #define POWERLIMITER_UPPER_POWER_LIMIT 800 +#define POWERLIMITER_SCALING_THRESHOLD 98 #define POWERLIMITER_IGNORE_SOC true #define POWERLIMITER_BATTERY_SOC_START_THRESHOLD 80 #define POWERLIMITER_BATTERY_SOC_STOP_THRESHOLD 20 diff --git a/src/Configuration.cpp b/src/Configuration.cpp index b74d1d34a..cf3bafd78 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -162,6 +162,7 @@ void ConfigurationClass::serializePowerLimiterConfig(PowerLimiterConfig const& s t["use_overscaling_to_compensate_shading"] = s.UseOverscaling; t["lower_power_limit"] = s.LowerPowerLimit; t["upper_power_limit"] = s.UpperPowerLimit; + t["scaling_threshold"] = s.ScalingThreshold; } } @@ -472,6 +473,7 @@ void ConfigurationClass::deserializePowerLimiterConfig(JsonObject const& source, inv.UseOverscaling = s["use_overscaling_to_compensate_shading"] | POWERLIMITER_USE_OVERSCALING; inv.LowerPowerLimit = s["lower_power_limit"] | POWERLIMITER_LOWER_POWER_LIMIT; inv.UpperPowerLimit = s["upper_power_limit"] | POWERLIMITER_UPPER_POWER_LIMIT; + inv.ScalingThreshold = s["scaling_threshold"] | POWERLIMITER_SCALING_THRESHOLD; } } diff --git a/src/PowerLimiterSolarInverter.cpp b/src/PowerLimiterSolarInverter.cpp index 7dbd088a3..32584e995 100644 --- a/src/PowerLimiterSolarInverter.cpp +++ b/src/PowerLimiterSolarInverter.cpp @@ -152,8 +152,8 @@ uint16_t PowerLimiterSolarInverter::scaleLimit(uint16_t expectedOutputWatts) // is currently not producing (efficiency is zero in that case) inverterEfficiencyFactor = (inverterEfficiencyFactor > 0) ? inverterEfficiencyFactor/100 : 0.967; - // 98% of the expected power is good enough - auto expectedAcPowerPerMppt = (getCurrentLimitWatts() / dcTotalMppts) * 0.98; + auto scalingThreshold = static_cast(_config.ScalingThreshold) / 100.0; + auto expectedAcPowerPerMppt = (getCurrentLimitWatts() / dcTotalMppts) * scalingThreshold; if (_verboseLogging) { MessageOutput.printf("%s expected AC power per MPPT %.0f W\r\n", diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index bc9565253..f5223fbb7 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -710,6 +710,8 @@ "VoltageLoadCorrectionFactor": "Lastkorrekturfaktor", "BatterySocInfo": "Hinweis: Die Batterie State of Charge (SoC) Schwellwerte werden bevorzugt herangezogen. Sie werden allerdings nur benutzt, wenn die Batterie-Kommunikationsschnittstelle innerhalb der letzten Minute gültige Werte verarbeitet hat. Andernfalls werden ersatzweise die Spannungs-Schwellwerte verwendet.", "InverterIsBehindPowerMeter": "Stromzählermessung beinhaltet Wechselrichter", + "ScalingPowerThreshold": "Schwellenwert für Überskalierung", + "ScalingPowerThresholdHint": "Minimale Eingangsleistungsschwelle (%). Eingänge unterhalb dieses Prozentsatzes werden als verschattet/ungenutzt bewertet.", "InverterIsBehindPowerMeterHint": "Aktivieren falls sich der Stromzähler-Messwert um die Ausgangsleistung des Wechselrichters verringert, wenn dieser Strom produziert. Normalerweise ist das zutreffend.", "InverterIsSolarPowered": "Wechselrichter wird von Solarmodulen gespeist", "UseOverscaling": "Verschattetet/Ungenutzte Eingänge ausgleichen", diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 1aba6a997..7f06ed407 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -712,6 +712,8 @@ "VoltageLoadCorrectionFactor": "Load correction factor", "BatterySocInfo": "Hint: The use of battery State of Charge (SoC) thresholds is prioritized. However, SoC thresholds are only used if the battery communication interface has processed valid SoC values in the last minute. Otherwise, the voltage thresholds will be used as fallback.", "InverterIsBehindPowerMeter": "PowerMeter reading includes inverter output", + "ScalingPowerThreshold": "Overscaling input power threshold", + "ScalingPowerThresholdHint": "Set the minimum power input threshold (%). Inputs below this percentage are considered shaded/unused.", "InverterIsBehindPowerMeterHint": "Enable this option if the power meter reading is reduced by the inverter's output when it produces power. This is typically true.", "InverterIsSolarPowered": "Inverter is powered by solar modules", "UseOverscaling": "Compensate shaded or unused inputs", diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index 62aaa1389..63e21e9b6 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -778,6 +778,8 @@ "VoltageLoadCorrectionFactor": "Load correction factor", "BatterySocInfo": "Hint: The use of battery State of Charge (SoC) thresholds is prioritized. However, SoC thresholds are only used if the battery communication interface has processed valid SoC values in the last minute. Otherwise, the voltage thresholds will be used as fallback.", "InverterIsBehindPowerMeter": "PowerMeter reading includes inverter output", + "ScalingPowerThreshold": "Overscaling input power threshold", + "ScalingPowerThresholdHint": "Set the minimum power input threshold (%). Inputs below this percentage are considered shaded/unused.", "InverterIsBehindPowerMeterHint": "Enable this option if the power meter reading is reduced by the inverter's output when it produces power. This is typically true.", "InverterIsSolarPowered": "Inverter is powered by solar modules", "UseOverscaling": "Compensate shaded or unused inputs", diff --git a/webapp/src/types/PowerLimiterConfig.ts b/webapp/src/types/PowerLimiterConfig.ts index 8bdf3a80e..253b001be 100644 --- a/webapp/src/types/PowerLimiterConfig.ts +++ b/webapp/src/types/PowerLimiterConfig.ts @@ -30,6 +30,7 @@ export interface PowerLimiterInverterConfig { use_overscaling_to_compensate_shading: boolean; lower_power_limit: number; upper_power_limit: number; + scaling_threshold: number; } export interface PowerLimiterConfig { diff --git a/webapp/src/views/PowerLimiterAdminView.vue b/webapp/src/views/PowerLimiterAdminView.vue index 840bcb4be..c89a0bf56 100644 --- a/webapp/src/views/PowerLimiterAdminView.vue +++ b/webapp/src/views/PowerLimiterAdminView.vue @@ -140,6 +140,18 @@ wide /> + +