Skip to content

Commit

Permalink
Use AC power for limit calculation (= Support directly connected PV p…
Browse files Browse the repository at this point in the history
…anels with Power Limiter) (#154)

* Power limiter: Use the actual AC power for limit calculation

instead of the last set limit.

In order support setups without battery connected (sources that don't exhaust the limit)
  • Loading branch information
berni2288 committed Apr 5, 2023
1 parent c0dff1e commit 8ca664a
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 14 deletions.
7 changes: 4 additions & 3 deletions include/PowerLimiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ class PowerLimiterClass {
int32_t getLastRequestedPowewrLimit();

private:
uint32_t _lastCommandSent;
uint32_t _lastLoop;
int32_t _lastRequestedPowerLimit;
uint32_t _lastCommandSent = 0;
uint32_t _lastLoop = 0;
int32_t _lastRequestedPowerLimit = 0;
uint32_t _lastLimitSetTime = 0;
plStates _plState = STATE_DISCOVER;

float _powerMeter1Power;
Expand Down
27 changes: 16 additions & 11 deletions src/PowerLimiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ PowerLimiterClass PowerLimiter;

void PowerLimiterClass::init()
{
_lastCommandSent = 0;
_lastLoop = 0;
_lastRequestedPowerLimit = 0;
}

void PowerLimiterClass::loop()
Expand All @@ -44,10 +41,16 @@ void PowerLimiterClass::loop()
}

float dcVoltage = inverter->Statistics()->getChannelFieldValue(TYPE_DC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_UDC);
float acPower = inverter->Statistics()->getChannelFieldValue(TYPE_AC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_PAC);
float acPower = inverter->Statistics()->getChannelFieldValue(TYPE_AC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_PAC);
float correctedDcVoltage = dcVoltage + (acPower * config.PowerLimiter_VoltageLoadCorrectionFactor);

if ((millis() - inverter->Statistics()->getLastUpdate()) > 10000) {
// If the last inverter update is too old, don't do anything.
// If the last inverter update was before the last limit updated, don't do anything.
// Also give the Power meter 3 seconds time to recognize power changes because of the last set limit
// and also because the Hoymiles MPPT might not react immediately.
if ((millis() - inverter->Statistics()->getLastUpdate()) > 10000
|| inverter->Statistics()->getLastUpdate() <= _lastLimitSetTime
|| PowerMeter.getLastPowerMeterUpdate() <= (_lastLimitSetTime + 3000)) {
return;
}

Expand All @@ -56,7 +59,6 @@ void PowerLimiterClass::loop()
dcVoltage, config.PowerLimiter_VoltageStartThreshold, config.PowerLimiter_VoltageStopThreshold, inverter->isProducing());
}


while(true) {
switch(_plState) {
case STATE_DISCOVER:
Expand Down Expand Up @@ -179,13 +181,14 @@ int32_t PowerLimiterClass::calcPowerLimit(std::shared_ptr<InverterAbstract> inve
victronChargePower, efficency, consumeSolarPowerOnly ? "true" : "false", newPowerLimit);

// Safety check: Are the power meter values not too old?
if (millis() - PowerMeter.getLastPowerMeterUpdate() < (30 * 1000)) {
// Are the reported inverter data not too old?
if (millis() - PowerMeter.getLastPowerMeterUpdate() < (30 * 1000)
&& millis() - inverter->Statistics()->getLastUpdate() < (15 * 1000)) {
if (config.PowerLimiter_IsInverterBehindPowerMeter) {
// If the inverter the behind the power meter (part of measurement),
// the produced power of this inverter has also to be taken into account.
// We don't use FLD_PAC from the statistics, because that
// data might be too old and unrelieable.
newPowerLimit += _lastRequestedPowerLimit;
float acPower = inverter->Statistics()->getChannelFieldValue(TYPE_AC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_PAC);
newPowerLimit += static_cast<int>(acPower);
}

newPowerLimit -= config.PowerLimiter_TargetPowerConsumption;
Expand Down Expand Up @@ -228,6 +231,8 @@ void PowerLimiterClass::setNewPowerLimit(std::shared_ptr<InverterAbstract> inver
MessageOutput.printf("[PowerLimiterClass::loop] Limit Non-Persistent: %d W\r\n", newPowerLimit);
inverter->sendActivePowerControlRequest(Hoymiles.getRadio(), newPowerLimit, PowerLimitControlType::AbsolutNonPersistent);
_lastRequestedPowerLimit = newPowerLimit;
// wait for the next inverter update (+ 3 seconds to make sure the limit got applied)
_lastLimitSetTime = millis();
}
}

Expand All @@ -244,7 +249,7 @@ float PowerLimiterClass::getLoadCorrectedVoltage(std::shared_ptr<InverterAbstrac
{
CONFIG_T& config = Configuration.get();

float acPower = inverter->Statistics()->getChannelFieldValue(TYPE_AC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_PAC);
float acPower = inverter->Statistics()->getChannelFieldValue(TYPE_AC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_PAC);
float dcVoltage = inverter->Statistics()->getChannelFieldValue(TYPE_DC, (ChannelNum_t) config.PowerLimiter_InverterChannelId, FLD_UDC);

if (dcVoltage <= 0.0) {
Expand Down

0 comments on commit 8ca664a

Please sign in to comment.