Fix: Improve DPL nighttime discharging (#1126)

* 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 <andreas@boehm.cx>
This commit is contained in:
Bernhard Kirchen 2024-08-15 20:10:32 +02:00 committed by GitHub
parent 599c5cea7d
commit 5d1d071c8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 14 additions and 8 deletions

View File

@ -75,6 +75,7 @@ private:
Mode _mode = Mode::Normal; Mode _mode = Mode::Normal;
std::shared_ptr<InverterAbstract> _inverter = nullptr; std::shared_ptr<InverterAbstract> _inverter = nullptr;
bool _batteryDischargeEnabled = false; 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 _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 uint32_t _nextCalculateCheck = 5000; // time in millis for next NTP check to calulate restart
bool _fullSolarPassThroughEnabled = false; bool _fullSolarPassThroughEnabled = false;

View File

@ -17,6 +17,7 @@
#include <ctime> #include <ctime>
#include <cmath> #include <cmath>
#include <frozen/map.h> #include <frozen/map.h>
#include "SunPosition.h"
PowerLimiterClass PowerLimiter; PowerLimiterClass PowerLimiter;
@ -239,19 +240,23 @@ void PowerLimiterClass::loop()
auto getBatteryPower = [this,&config]() -> bool { auto getBatteryPower = [this,&config]() -> bool {
if (config.PowerLimiter.IsInverterSolarPowered) { return false; } 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 (isStopThresholdReached()) { return false; }
if (isStartThresholdReached()) { return true; } 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 && if (config.PowerLimiter.SolarPassThroughEnabled &&
config.PowerLimiter.BatteryAlwaysUseAtNight) { config.PowerLimiter.BatteryAlwaysUseAtNight &&
return getSolarPower() == 0; !isDayPeriod &&
!_batteryDischargeEnabled) {
_nighttimeDischarging = true;
return true;
} }
// we are between start and stop threshold and keep the state that was // we are between start and stop threshold and keep the state that was