Power limiter fixes (#201)
This commit is contained in:
parent
80f1af32f8
commit
c621f2d3e3
@ -43,6 +43,7 @@ void PowerLimiterClass::loop()
|
|||||||
|| isStopThresholdReached(inverter)) {
|
|| isStopThresholdReached(inverter)) {
|
||||||
if (inverter->isProducing()) {
|
if (inverter->isProducing()) {
|
||||||
MessageOutput.printf("PL initiated inverter shutdown.\r\n");
|
MessageOutput.printf("PL initiated inverter shutdown.\r\n");
|
||||||
|
inverter->sendActivePowerControlRequest(config.PowerLimiter_LowerPowerLimit, PowerLimitControlType::AbsolutNonPersistent);
|
||||||
inverter->sendPowerControlRequest(false);
|
inverter->sendPowerControlRequest(false);
|
||||||
} else {
|
} else {
|
||||||
_plState = SHUTDOWN;
|
_plState = SHUTDOWN;
|
||||||
@ -54,15 +55,26 @@ void PowerLimiterClass::loop()
|
|||||||
if (!config.PowerLimiter_Enabled || _disabled) {
|
if (!config.PowerLimiter_Enabled || _disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety check, return on too old power meter values
|
||||||
|
if (millis() - PowerMeter.getLastPowerMeterUpdate() > (30 * 1000)
|
||||||
|
|| (millis() - inverter->Statistics()->getLastUpdate()) > (config.Dtu_PollInterval * 10 * 1000)) {
|
||||||
|
// If the power meter values are older than 30 seconds,
|
||||||
|
// or the Inverter Stats are older then 10x the poll interval
|
||||||
|
// set the limit to lower power limit for safety reasons.
|
||||||
|
MessageOutput.println("[PowerLimiterClass::loop] Power Meter/Inverter values too old. Using 0W (i.e. disable inverter)");
|
||||||
|
inverter->sendActivePowerControlRequest(config.PowerLimiter_LowerPowerLimit, PowerLimitControlType::AbsolutNonPersistent);
|
||||||
|
inverter->sendPowerControlRequest(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// At this point the PL is enabled but we could still be in the shutdown state
|
// At this point the PL is enabled but we could still be in the shutdown state
|
||||||
_plState = ACTIVE;
|
_plState = ACTIVE;
|
||||||
|
|
||||||
// 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.
|
// 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 after the last set limit
|
// Also give the Power meter 3 seconds time to recognize power changes after the last set limit
|
||||||
// as the Hoymiles MPPT might not react immediately.
|
// as the Hoymiles MPPT might not react immediately.
|
||||||
if ((millis() - inverter->Statistics()->getLastUpdate()) > 10000
|
if (inverter->Statistics()->getLastUpdate() <= _lastLimitSetTime
|
||||||
|| inverter->Statistics()->getLastUpdate() <= _lastLimitSetTime
|
|
||||||
|| PowerMeter.getLastPowerMeterUpdate() <= (_lastLimitSetTime + 3000)) {
|
|| PowerMeter.getLastPowerMeterUpdate() <= (_lastLimitSetTime + 3000)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -74,22 +86,36 @@ void PowerLimiterClass::loop()
|
|||||||
dcVoltage, config.PowerLimiter_VoltageStartThreshold, config.PowerLimiter_VoltageStopThreshold, inverter->isProducing());
|
dcVoltage, config.PowerLimiter_VoltageStartThreshold, config.PowerLimiter_VoltageStopThreshold, inverter->isProducing());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Battery charging cycle conditions
|
// Battery charging cycle conditions
|
||||||
// The battery can only be discharged after a full charge in the
|
// First we always disable discharge if the battery is empty
|
||||||
// EMPTY_WHEN_FULL case
|
|
||||||
if (isStopThresholdReached(inverter)) {
|
if (isStopThresholdReached(inverter)) {
|
||||||
// Disable battery discharge when empty
|
// Disable battery discharge when empty
|
||||||
_batteryDischargeEnabled = false;
|
_batteryDischargeEnabled = false;
|
||||||
} else if (config.PowerLimiter_BatteryDrainStategy == EMPTY_AT_NIGHT) {
|
} else {
|
||||||
// Enable battery discharge when there is no sunshine
|
// UI: Solar Passthrough Enabled -> false
|
||||||
_batteryDischargeEnabled = !canUseDirectSolarPower();
|
// Battery discharge can be enabled when start threshold is reached
|
||||||
|
if (!config.PowerLimiter_SolarPassThroughEnabled && isStartThresholdReached(inverter)) {
|
||||||
|
_batteryDischargeEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This checks if the battery discharge start conditions are met for the EMPTY_WHEN_FULL case
|
// UI: Solar Passthrough Enabled -> true && EMPTY_AT_NIGHT
|
||||||
if (isStartThresholdReached(inverter) && config.PowerLimiter_BatteryDrainStategy == EMPTY_WHEN_FULL) {
|
if (config.PowerLimiter_SolarPassThroughEnabled && config.PowerLimiter_BatteryDrainStategy == EMPTY_AT_NIGHT) {
|
||||||
|
if(isStartThresholdReached(inverter)) {
|
||||||
|
// In this case we should only discharge the battery as long it is above startThreshold
|
||||||
_batteryDischargeEnabled = true;
|
_batteryDischargeEnabled = true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// In this case we should only discharge the battery when there is no sunshine
|
||||||
|
_batteryDischargeEnabled = !canUseDirectSolarPower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI: Solar Passthrough Enabled -> true && EMPTY_WHEN_FULL
|
||||||
|
// Battery discharge can be enabled when start threshold is reached
|
||||||
|
if (config.PowerLimiter_SolarPassThroughEnabled && isStartThresholdReached(inverter) && config.PowerLimiter_BatteryDrainStategy == EMPTY_WHEN_FULL) {
|
||||||
|
_batteryDischargeEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate and set Power Limit
|
// Calculate and set Power Limit
|
||||||
int32_t newPowerLimit = calcPowerLimit(inverter, canUseDirectSolarPower(), _batteryDischargeEnabled);
|
int32_t newPowerLimit = calcPowerLimit(inverter, canUseDirectSolarPower(), _batteryDischargeEnabled);
|
||||||
@ -112,7 +138,7 @@ uint8_t PowerLimiterClass::getPowerLimiterState() {
|
|||||||
return PL_UI_STATE_USE_SOLAR_ONLY;
|
return PL_UI_STATE_USE_SOLAR_ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(VeDirect.veFrame.PPV > 0) {
|
if(!inverter->isProducing()) {
|
||||||
return PL_UI_STATE_CHARGING;
|
return PL_UI_STATE_CHARGING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,16 +188,6 @@ int32_t PowerLimiterClass::calcPowerLimit(std::shared_ptr<InverterAbstract> inve
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety check, return on too old power meter values
|
|
||||||
if (millis() - PowerMeter.getLastPowerMeterUpdate() > (30 * 1000)
|
|
||||||
&& (millis() - inverter->Statistics()->getLastUpdate()) > (config.Dtu_PollInterval * 10 * 1000)) {
|
|
||||||
// If the power meter values are older than 30 seconds,
|
|
||||||
// and the Inverter Stats are older then 10x the poll interval
|
|
||||||
// set the limit to 0W for safety reasons.
|
|
||||||
MessageOutput.println("[PowerLimiterClass::loop] Power Meter/Inverter values too old. Using 0W (i.e. disable inverter)");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.PowerLimiter_IsInverterBehindPowerMeter) {
|
if (config.PowerLimiter_IsInverterBehindPowerMeter) {
|
||||||
// If the inverter the behind the power meter (part of measurement),
|
// If the inverter the behind the power meter (part of measurement),
|
||||||
// the produced power of this inverter has also to be taken into account.
|
// the produced power of this inverter has also to be taken into account.
|
||||||
@ -232,6 +248,7 @@ void PowerLimiterClass::setNewPowerLimit(std::shared_ptr<InverterAbstract> inver
|
|||||||
if (newPowerLimit < config.PowerLimiter_LowerPowerLimit) {
|
if (newPowerLimit < config.PowerLimiter_LowerPowerLimit) {
|
||||||
if (inverter->isProducing()) {
|
if (inverter->isProducing()) {
|
||||||
MessageOutput.println("[PowerLimiterClass::loop] Stopping inverter...");
|
MessageOutput.println("[PowerLimiterClass::loop] Stopping inverter...");
|
||||||
|
inverter->sendActivePowerControlRequest(config.PowerLimiter_LowerPowerLimit, PowerLimitControlType::AbsolutNonPersistent);
|
||||||
inverter->sendPowerControlRequest(false);
|
inverter->sendPowerControlRequest(false);
|
||||||
}
|
}
|
||||||
newPowerLimit = config.PowerLimiter_LowerPowerLimit;
|
newPowerLimit = config.PowerLimiter_LowerPowerLimit;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user