From 5d1d071c8a3a0820e96e1e31835faa7a5dbf1b9e Mon Sep 17 00:00:00 2001 From: Bernhard Kirchen Date: Thu, 15 Aug 2024 20:10:32 +0200 Subject: [PATCH] Fix: Improve DPL nighttime discharging (#1126) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: DPL: start discharging at night logic error the switch "always start discharging battery at night" would cause to stop discharging the battery when there was solar power and the battery was discharged below the start threshold. this change introduces a nighttime discharging boolean variable, which is enabled the instant we decide to start a battery discharge cycle due to nighttime havin arrived. we reset this variable as soon as it is daytime (solar power available). in that case, we allow discharging the battery if the start threshold was reached. this can actually be the case if the battery is charged with cheap electricity during the night. removed comments as they merely spell out what the if statement already expresses quite nicely. * use SunPosition.isDayPeriod() to check for daytime --------- Co-authored-by: Andreas Böhm --- include/PowerLimiter.h | 1 + src/PowerLimiter.cpp | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/PowerLimiter.h b/include/PowerLimiter.h index 8da2628f9..db69a303b 100644 --- a/include/PowerLimiter.h +++ b/include/PowerLimiter.h @@ -75,6 +75,7 @@ class PowerLimiterClass { Mode _mode = Mode::Normal; std::shared_ptr _inverter = nullptr; bool _batteryDischargeEnabled = false; + bool _nighttimeDischarging = false; uint32_t _nextInverterRestart = 0; // Values: 0->not calculated / 1->no restart configured / >1->time of next inverter restart in millis() uint32_t _nextCalculateCheck = 5000; // time in millis for next NTP check to calulate restart bool _fullSolarPassThroughEnabled = false; diff --git a/src/PowerLimiter.cpp b/src/PowerLimiter.cpp index 39c9fd6d3..1c471a3dc 100644 --- a/src/PowerLimiter.cpp +++ b/src/PowerLimiter.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "SunPosition.h" PowerLimiterClass PowerLimiter; @@ -239,19 +240,23 @@ void PowerLimiterClass::loop() auto getBatteryPower = [this,&config]() -> bool { if (config.PowerLimiter.IsInverterSolarPowered) { return false; } + auto isDayPeriod = SunPosition.isSunsetAvailable() ? SunPosition.isDayPeriod() : getSolarPower() > 0; + + if (_nighttimeDischarging && isDayPeriod) { + _nighttimeDischarging = false; + return isStartThresholdReached(); + } + if (isStopThresholdReached()) { return false; } if (isStartThresholdReached()) { return true; } - // with solar passthrough, and the respective switch enabled, we - // may start discharging the battery when it is nighttime. we also - // stop the discharge cycle if it becomes daytime again. - // TODO(schlimmchen): should be supported by sunrise and sunset, such - // that a thunderstorm or other events that drastically lower the solar - // power do not cause the start of a discharge cycle during the day. if (config.PowerLimiter.SolarPassThroughEnabled && - config.PowerLimiter.BatteryAlwaysUseAtNight) { - return getSolarPower() == 0; + config.PowerLimiter.BatteryAlwaysUseAtNight && + !isDayPeriod && + !_batteryDischargeEnabled) { + _nighttimeDischarging = true; + return true; } // we are between start and stop threshold and keep the state that was