OpenDTU-old/include/PowerLimiter.h
Bernhard Kirchen 9aeb1583b5 DPL: consider the system stable when reusing the old limit
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.
2023-06-30 21:00:51 +02:00

87 lines
2.9 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "Configuration.h"
#include <espMqttClient.h>
#include <Arduino.h>
#include <Hoymiles.h>
#include <memory>
#define PL_UI_STATE_INACTIVE 0
#define PL_UI_STATE_CHARGING 1
#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
} batDrainStrategy;
class PowerLimiterClass {
public:
enum class Status : unsigned {
Initializing,
DisabledByConfig,
DisabledByMqtt,
PowerMeterDisabled,
PowerMeterTimeout,
PowerMeterPending,
InverterInvalid,
InverterChanged,
InverterOffline,
InverterCommandsDisabled,
InverterLimitPending,
InverterPowerCmdPending,
InverterStatsPending,
UnconditionalSolarPassthrough,
NoVeDirect,
Settling,
Stable,
LowerLimitUndercut
};
void init();
void loop();
uint8_t getPowerLimiterState();
int32_t getLastRequestedPowerLimit();
void setMode(uint8_t mode);
bool getMode();
void calcNextInverterRestart();
private:
int32_t _lastRequestedPowerLimit = 0;
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;
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;
std::string const& getStatusText(Status status);
void announceStatus(Status status);
void shutdown(Status status);
int32_t inverterPowerDcToAc(std::shared_ptr<InverterAbstract> inverter, int32_t dcPower);
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 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);
bool isStopThresholdReached(std::shared_ptr<InverterAbstract> inverter);
bool useFullSolarPassthrough(std::shared_ptr<InverterAbstract> inverter);
};
extern PowerLimiterClass PowerLimiter;