Skip to content

Commit

Permalink
Fix: DPL: ensure inverter reaches requested state
Browse files Browse the repository at this point in the history
we previously only called commitPowerLimit() if the desired limit
changed such that the change was bigger than the hysteresis. we found
that if the limit update was not received and the desired limit would
not change much, the limit of the inverter was wrong for a long time.

to mitigate this, we introduced re-sending the limit update every 60
seconds, regardless of what the limit reported by the inverter was at
that time.

if the power-up command was not received, we also would repeat it only
once every 60 seconds.

this leads to a new kind of staleness and the actual inverter state was
still not matching the desired state.

this new approach effectively adds an additional control loop at the
start of the DPL loop(). that new function compares the requested
inverter state to the actual reported state. it sends updates (limit
update or power on state) until the desired inverter state is reached,
or until a (hard-coded) timeout occurs.

this approach also allows us to send power-up, power-down, and limit
update commands independent from one another and in a particular order.

this should make sure that the inverter is in the desired state even if
conditions change slowly and commands were not received as expected.
  • Loading branch information
schlimmchen committed Mar 2, 2024
1 parent c560d1d commit 8b6e57c
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 107 deletions.
15 changes: 7 additions & 8 deletions include/PowerLimiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Hoymiles.h>
#include <memory>
#include <functional>
#include <optional>
#include <TaskSchedulerDeclarations.h>
#include <frozen/string.h>

Expand All @@ -15,10 +16,6 @@
#define PL_UI_STATE_USE_SOLAR_ONLY 2
#define PL_UI_STATE_USE_SOLAR_AND_BATTERY 3

#define PL_MODE_ENABLE_NORMAL_OP 0
#define PL_MODE_FULL_DISABLE 1
#define PL_MODE_SOLAR_PT_ONLY 2

typedef enum {
EMPTY_WHEN_FULL= 0,
EMPTY_AT_NIGHT
Expand Down Expand Up @@ -51,7 +48,7 @@ class PowerLimiterClass {

void init(Scheduler& scheduler);
uint8_t getPowerLimiterState();
int32_t getLastRequestedPowerLimit();
int32_t getLastRequestedPowerLimit() { return _lastRequestedPowerLimit; }

enum class Mode : unsigned {
Normal = 0,
Expand All @@ -69,8 +66,10 @@ class PowerLimiterClass {
Task _loopTask;

int32_t _lastRequestedPowerLimit = 0;
uint32_t _lastPowerLimitMillis = 0;
uint32_t _shutdownTimeout = 0;
bool _shutdownPending = false;
std::optional<uint32_t> _oUpdateStartMillis = std::nullopt;
std::optional<int32_t> _oTargetPowerLimitWatts = std::nullopt;
std::optional<bool> _oTargetPowerState = std::nullopt;
Status _lastStatus = Status::Initializing;
uint32_t _lastStatusPrinted = 0;
uint32_t _lastCalculation = 0;
Expand All @@ -93,7 +92,7 @@ class PowerLimiterClass {
void unconditionalSolarPassthrough(std::shared_ptr<InverterAbstract> inverter);
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);
bool updateInverter();
bool setNewPowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newPowerLimit);
int32_t getSolarChargePower();
float getLoadCorrectedVoltage();
Expand Down
Loading

0 comments on commit 8b6e57c

Please sign in to comment.