Skip to content

Commit

Permalink
DPL: consider the system stable when reusing the old limit
Browse files Browse the repository at this point in the history
a new status is needed to communicate that no update was sent to the
inverter because its power limit is still valid. in this case,
calculating a new power limit is delayed by an exponentially increasing
backoff. the maximum backoff time is ~1s, which is still plenty fast.

the backoff is actually necessary for another reason: at least
currently, a lot of debug messages are printed to the console. printing
all that information in every DPL loop() is too much.
  • Loading branch information
schlimmchen committed Jun 30, 2023
1 parent 461fce8 commit 9aeb158
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
5 changes: 4 additions & 1 deletion include/PowerLimiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class PowerLimiterClass {
UnconditionalSolarPassthrough,
NoVeDirect,
Settling,
Stable,
LowerLimitUndercut
};

Expand All @@ -57,6 +58,8 @@ class PowerLimiterClass {
bool _shutdownInProgress;
Status _lastStatus = Status::Initializing;
uint32_t _lastStatusPrinted = 0;
uint32_t _lastCalculation = 0;
uint32_t _calculationBackoffMs = 0;
uint8_t _mode = PL_MODE_ENABLE_NORMAL_OP;
std::shared_ptr<InverterAbstract> _inverter = nullptr;
bool _batteryDischargeEnabled = false;
Expand All @@ -72,7 +75,7 @@ class PowerLimiterClass {
bool canUseDirectSolarPower();
int32_t calcPowerLimit(std::shared_ptr<InverterAbstract> inverter, bool solarPowerEnabled, bool batteryDischargeEnabled);
void commitPowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t limit, bool enablePowerProduction);
void setNewPowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newPowerLimit);
bool setNewPowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newPowerLimit);
int32_t getSolarChargePower();
float getLoadCorrectedVoltage(std::shared_ptr<InverterAbstract> inverter);
bool isStartThresholdReached(std::shared_ptr<InverterAbstract> inverter);
Expand Down
30 changes: 25 additions & 5 deletions src/PowerLimiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ std::string const& PowerLimiterClass::getStatusText(PowerLimiterClass::Status st
{ Status::UnconditionalSolarPassthrough, "unconditionally passing through all solar power (MQTT override)" },
{ Status::NoVeDirect, "VE.Direct disabled, connection broken, or data outdated" },
{ Status::Settling, "waiting for the system to settle" },
{ Status::Stable, "the system is stable, the last power limit is still valid" },
{ Status::LowerLimitUndercut, "calculated power limit undercuts configured lower limit" }
};

Expand Down Expand Up @@ -184,6 +185,12 @@ void PowerLimiterClass::loop()
return announceStatus(Status::PowerMeterPending);
}

// since _lastCalculation and _calculationBackoffMs are initialized to
// zero, this test is passed the first time the condition is checked.
if (millis() < (_lastCalculation + _calculationBackoffMs)) {
return announceStatus(Status::Stable);
}

#ifdef POWER_LIMITER_DEBUG
MessageOutput.println("[PowerLimiterClass::loop] ******************* ENTER **********************");
#endif
Expand Down Expand Up @@ -248,7 +255,7 @@ void PowerLimiterClass::loop()
}
// Calculate and set Power Limit
int32_t newPowerLimit = calcPowerLimit(_inverter, canUseDirectSolarPower(), _batteryDischargeEnabled);
setNewPowerLimit(_inverter, newPowerLimit);
bool limitUpdated = setNewPowerLimit(_inverter, newPowerLimit);
#ifdef POWER_LIMITER_DEBUG
MessageOutput.printf("[PowerLimiterClass::loop] Status: SolarPT enabled %i, Drain Strategy: %i, canUseDirectSolarPower: %i, Batt discharge: %i\r\n",
config.PowerLimiter_SolarPassThroughEnabled, config.PowerLimiter_BatteryDrainStategy, canUseDirectSolarPower(), _batteryDischargeEnabled);
Expand All @@ -258,6 +265,16 @@ void PowerLimiterClass::loop()
config.Battery_Enabled, Battery.stateOfCharge, config.PowerLimiter_BatterySocStartThreshold, config.PowerLimiter_BatterySocStopThreshold, millis() - Battery.stateOfChargeLastUpdate);
MessageOutput.printf("[PowerLimiterClass::loop] ******************* Leaving PL, PL set to: %i, SP: %i, Batt: %i, PM: %f\r\n", newPowerLimit, canUseDirectSolarPower(), _batteryDischargeEnabled, round(PowerMeter.getPowerTotal()));
#endif

_lastCalculation = millis();

if (!limitUpdated) {
// increase polling backoff if system seems to be stable
_calculationBackoffMs = std::min<uint32_t>(1024, _calculationBackoffMs * 2);
return announceStatus(Status::Stable);
}

_calculationBackoffMs = 128;
}

/**
Expand Down Expand Up @@ -433,15 +450,17 @@ void PowerLimiterClass::commitPowerLimit(std::shared_ptr<InverterAbstract> inver
/**
* enforces limits and a hystersis on the requested power limit, after scaling
* the power limit to the ratio of total and producing inverter channels.
* commits the sanitized power limit.
* commits the sanitized power limit. returns true if a limit update was
* committed, false otherwise.
*/
void PowerLimiterClass::setNewPowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newPowerLimit)
bool PowerLimiterClass::setNewPowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newPowerLimit)
{
CONFIG_T& config = Configuration.get();

// Stop the inverter if limit is below threshold.
if (newPowerLimit < config.PowerLimiter_LowerPowerLimit) {
return shutdown(Status::LowerLimitUndercut);
shutdown(Status::LowerLimitUndercut);
return true;
}

// enforce configured upper power limit
Expand Down Expand Up @@ -473,13 +492,14 @@ void PowerLimiterClass::setNewPowerLimit(std::shared_ptr<InverterAbstract> inver
if ( diff < config.PowerLimiter_TargetPowerConsumptionHysteresis) {
MessageOutput.printf("[PowerLimiterClass::setNewPowerLimit] reusing old limit: %d W, diff: %d, hysteresis: %d\r\n",
_lastRequestedPowerLimit, diff, config.PowerLimiter_TargetPowerConsumptionHysteresis);
return;
return false;
}

MessageOutput.printf("[PowerLimiterClass::setNewPowerLimit] using new limit: %d W, requested power limit: %d\r\n",
effPowerLimit, newPowerLimit);

commitPowerLimit(inverter, effPowerLimit, true);
return true;
}

int32_t PowerLimiterClass::getSolarChargePower()
Expand Down

0 comments on commit 9aeb158

Please sign in to comment.