Fix: Improve overscaling for shaded inputs (#1089)

This commit is contained in:
Andreas Böhm 2024-07-11 15:03:12 +02:00 committed by GitHub
parent d9d0141fde
commit b90da210be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -694,7 +694,7 @@ bool PowerLimiterClass::updateInverter()
* refactoring. currently it only works for inverters that provide one MPPT for * refactoring. currently it only works for inverters that provide one MPPT for
* each input. * each input.
*/ */
static int32_t scalePowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newLimit, int32_t currentLimitWatts) static int32_t scalePowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newLimit, int32_t currentLimitWatts, bool log)
{ {
// prevent scaling if inverter is not producing, as input channels are not // prevent scaling if inverter is not producing, as input channels are not
// producing energy and hence are detected as not-producing, causing // producing energy and hence are detected as not-producing, causing
@ -730,6 +730,11 @@ static int32_t scalePowerLimit(std::shared_ptr<InverterAbstract> inverter, int32
// 98% of the expected power is good enough // 98% of the expected power is good enough
auto expectedAcPowerPerChannel = (currentLimitWatts / dcTotalChnls) * 0.98; auto expectedAcPowerPerChannel = (currentLimitWatts / dcTotalChnls) * 0.98;
if (log) {
MessageOutput.printf("[DPL::scalePowerLimit] expected AC power per channel %f W\r\n",
expectedAcPowerPerChannel);
}
size_t dcShadedChnls = 0; size_t dcShadedChnls = 0;
auto shadedChannelACPowerSum = 0.0; auto shadedChannelACPowerSum = 0.0;
@ -740,19 +745,33 @@ static int32_t scalePowerLimit(std::shared_ptr<InverterAbstract> inverter, int32
dcShadedChnls++; dcShadedChnls++;
shadedChannelACPowerSum += channelPowerAC; shadedChannelACPowerSum += channelPowerAC;
} }
if (log) {
MessageOutput.printf("[DPL::scalePowerLimit] ch %d AC power %f W\r\n",
c, channelPowerAC);
}
} }
// no shading or the shaded channels provide more power than what // no shading or the shaded channels provide more power than what
// we currently need. // we currently need.
if (dcShadedChnls == 0 || shadedChannelACPowerSum >= newLimit) { return newLimit; } if (dcShadedChnls == 0 || shadedChannelACPowerSum >= newLimit) { return newLimit; }
// keep the currentLimit when all channels are shaded and we get the if (dcShadedChnls == dcTotalChnls) {
// expected AC power or less. // keep the currentLimit when:
if (dcShadedChnls == dcTotalChnls && inverterOutputAC <= newLimit) { // - all channels are shaded
// - currentLimit >= newLimit
// - we get the expected AC power or less and
if (currentLimitWatts >= newLimit && inverterOutputAC <= newLimit) {
if (log) {
MessageOutput.printf("[DPL::scalePowerLimit] all channels are shaded, " MessageOutput.printf("[DPL::scalePowerLimit] all channels are shaded, "
"keeping the current limit of %d W\r\n", currentLimitWatts); "keeping the current limit of %d W\r\n", currentLimitWatts);
}
return currentLimitWatts; return currentLimitWatts;
} else {
return newLimit;
}
} }
size_t dcNonShadedChnls = dcTotalChnls - dcShadedChnls; size_t dcNonShadedChnls = dcTotalChnls - dcShadedChnls;
@ -760,8 +779,11 @@ static int32_t scalePowerLimit(std::shared_ptr<InverterAbstract> inverter, int32
if (overScaledLimit <= newLimit) { return newLimit; } if (overScaledLimit <= newLimit) { return newLimit; }
if (log) {
MessageOutput.printf("[DPL::scalePowerLimit] %d/%d channels are shaded, " MessageOutput.printf("[DPL::scalePowerLimit] %d/%d channels are shaded, "
"scaling %d W\r\n", dcShadedChnls, dcTotalChnls, overScaledLimit); "scaling %d W\r\n", dcShadedChnls, dcTotalChnls, overScaledLimit);
}
return overScaledLimit; return overScaledLimit;
} }
@ -819,7 +841,7 @@ bool PowerLimiterClass::setNewPowerLimit(std::shared_ptr<InverterAbstract> inver
float currentLimitPercent = inverter->SystemConfigPara()->getLimitPercent(); float currentLimitPercent = inverter->SystemConfigPara()->getLimitPercent();
auto currentLimitAbs = static_cast<int32_t>(currentLimitPercent * maxPower / 100); auto currentLimitAbs = static_cast<int32_t>(currentLimitPercent * maxPower / 100);
effPowerLimit = scalePowerLimit(inverter, effPowerLimit, currentLimitAbs); effPowerLimit = scalePowerLimit(inverter, effPowerLimit, currentLimitAbs, _verboseLogging);
effPowerLimit = std::min<int32_t>(effPowerLimit, maxPower); effPowerLimit = std::min<int32_t>(effPowerLimit, maxPower);