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: Solar inverter max increase calculcation is less strict, respects overscaling configuration and more #1487

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
2 changes: 2 additions & 0 deletions include/PowerLimiterInverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class PowerLimiterInverter {
void setTargetPowerState(bool enable) { _oTargetPowerState = enable; }
void setExpectedOutputAcWatts(uint16_t power) { _expectedOutputAcWatts = power; }

static char mpptName(MpptNum_t mppt);

// copied to avoid races with web UI
PowerLimiterInverterConfig _config;

Expand Down
1 change: 0 additions & 1 deletion include/PowerLimiterSolarInverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,4 @@ class PowerLimiterSolarInverter : public PowerLimiterInverter {
private:
uint16_t scaleLimit(uint16_t expectedOutputWatts);
void setAcOutput(uint16_t expectedOutputWatts) final;
static char mpptName(MpptNum_t mppt);
};
40 changes: 40 additions & 0 deletions src/PowerLimiterInverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,44 @@ void PowerLimiterInverter::debug() const
(_oTargetPowerState.has_value()?(*_oTargetPowerState?"production":"standby"):"unchanged"),
getUpdateTimeouts()
);

MessageOutput.printf(" MPPTs AC power:");

auto pStats = _spInverter->Statistics();
float inverterEfficiencyFactor = pStats->getChannelFieldValue(TYPE_INV, CH0, FLD_EFF) / 100;
std::vector<MpptNum_t> dcMppts = _spInverter->getMppts();

for (auto& m : dcMppts) {
float mpptPowerAC = 0.0;
std::vector<ChannelNum_t> mpptChnls = _spInverter->getChannelsDCByMppt(m);

for (auto& c : mpptChnls) {
mpptPowerAC += pStats->getChannelFieldValue(TYPE_DC, c, FLD_PDC) * inverterEfficiencyFactor;
}

MessageOutput.printf(" %c: %.0f W",
mpptName(m), mpptPowerAC);
}

MessageOutput.printf("\r\n");
}

char PowerLimiterInverter::mpptName(MpptNum_t mppt)
{
switch (mppt) {
case MpptNum_t::MPPT_A:
return 'a';

case MpptNum_t::MPPT_B:
return 'b';

case MpptNum_t::MPPT_C:
return 'c';

case MpptNum_t::MPPT_D:
return 'd';

default:
return '?';
}
}
41 changes: 19 additions & 22 deletions src/PowerLimiterSolarInverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,31 @@ uint16_t PowerLimiterSolarInverter::getMaxIncreaseWatts() const
return maxTotalIncrease;
}

// when the current limit is less than 15% of the max power of the inverter
// the output will not match the limit as the inverters are not able to work
// with those low limits. In this case we assume that the inverter is able to
// provide more power and we return the maximum possible increase.
// thanks spcqike for creating a table that can be found here:
// https://github.com/hoylabs/OpenDTU-OnBattery/issues/1087#issuecomment-2216787552
if (getCurrentLimitWatts() < getInverterMaxPowerWatts() * 0.15) { return maxTotalIncrease; }

auto pStats = _spInverter->Statistics();
std::vector<MpptNum_t> dcMppts = _spInverter->getMppts();
size_t dcTotalMppts = dcMppts.size();

float inverterEfficiencyFactor = pStats->getChannelFieldValue(TYPE_INV, CH0, FLD_EFF) / 100;

// 98% of the expected power is good enough
auto expectedAcPowerPerMppt = (getCurrentLimitWatts() / dcTotalMppts) * 0.98;
// with 97% we are a bit less strict than when we scale the limit
auto expectedPowerPercentage = 0.97;

// use the scaling threshold as the expected power percentage if lower,
// but only when overscaling is enabled and the inverter does not support PDL
if (_config.UseOverscaling && !_spInverter->supportsPowerDistributionLogic()) {
expectedPowerPercentage = std::min(expectedPowerPercentage, static_cast<float>(_config.ScalingThreshold) / 100.0);
}

// x% of the expected power is good enough
auto expectedAcPowerPerMppt = (getCurrentLimitWatts() / dcTotalMppts) * expectedPowerPercentage;

size_t dcNonShadedMppts = 0;
auto nonShadedMpptACPowerSum = 0.0;
Expand Down Expand Up @@ -227,23 +244,3 @@ void PowerLimiterSolarInverter::setAcOutput(uint16_t expectedOutputWatts)
setTargetPowerLimitWatts(scaleLimit(expectedOutputWatts));
setTargetPowerState(true);
}

char PowerLimiterSolarInverter::mpptName(MpptNum_t mppt)
{
switch (mppt) {
case MpptNum_t::MPPT_A:
return 'a';

case MpptNum_t::MPPT_B:
return 'b';

case MpptNum_t::MPPT_C:
return 'c';

case MpptNum_t::MPPT_D:
return 'd';

default:
return '?';
}
}
Loading