Feature: add daily restart for the inverter
Add a configurable restart option for the inverter to set the "YieldDay" values to zero. Signed-off-by: Martin Dummer <martin.dummer@gmx.net>
This commit is contained in:
parent
52af52eb3a
commit
c727e21a49
@ -148,6 +148,7 @@ struct CONFIG_T {
|
||||
float PowerLimiter_VoltageStartThreshold;
|
||||
float PowerLimiter_VoltageStopThreshold;
|
||||
float PowerLimiter_VoltageLoadCorrectionFactor;
|
||||
int8_t PowerLimiter_RestartHour;
|
||||
|
||||
bool Battery_Enabled;
|
||||
bool Huawei_Enabled;
|
||||
|
||||
@ -31,6 +31,7 @@ public:
|
||||
int32_t getLastRequestedPowewrLimit();
|
||||
void setDisable(bool disable);
|
||||
bool getDisable();
|
||||
void calcNextInverterRestart();
|
||||
|
||||
private:
|
||||
uint32_t _lastLoop = 0;
|
||||
@ -39,6 +40,8 @@ private:
|
||||
plStates _plState;
|
||||
bool _disabled = false;
|
||||
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
|
||||
|
||||
float _powerMeter1Power;
|
||||
float _powerMeter2Power;
|
||||
|
||||
@ -121,6 +121,7 @@
|
||||
#define POWERLIMITER_VOLTAGE_START_THRESHOLD 50.0
|
||||
#define POWERLIMITER_VOLTAGE_STOP_THRESHOLD 49.0
|
||||
#define POWERLIMITER_VOLTAGE_LOAD_CORRECTION_FACTOR 0.001
|
||||
#define POWERLIMITER_RESTART_HOUR -1
|
||||
|
||||
#define BATTERY_ENABLED false
|
||||
|
||||
|
||||
@ -161,6 +161,7 @@ bool ConfigurationClass::write()
|
||||
powerlimiter["voltage_start_threshold"] = config.PowerLimiter_VoltageStartThreshold;
|
||||
powerlimiter["voltage_stop_threshold"] = config.PowerLimiter_VoltageStopThreshold;
|
||||
powerlimiter["voltage_load_correction_factor"] = config.PowerLimiter_VoltageLoadCorrectionFactor;
|
||||
powerlimiter["inverter_restart_hour"] = config.PowerLimiter_RestartHour;
|
||||
|
||||
JsonObject battery = doc.createNestedObject("battery");
|
||||
battery["enabled"] = config.Battery_Enabled;
|
||||
@ -356,6 +357,7 @@ bool ConfigurationClass::read()
|
||||
config.PowerLimiter_VoltageStartThreshold = powerlimiter["voltage_start_threshold"] | POWERLIMITER_VOLTAGE_START_THRESHOLD;
|
||||
config.PowerLimiter_VoltageStopThreshold = powerlimiter["voltage_stop_threshold"] | POWERLIMITER_VOLTAGE_STOP_THRESHOLD;
|
||||
config.PowerLimiter_VoltageLoadCorrectionFactor = powerlimiter["voltage_load_correction_factor"] | POWERLIMITER_VOLTAGE_LOAD_CORRECTION_FACTOR;
|
||||
config.PowerLimiter_RestartHour = powerlimiter["inverter_restart_hour"] | POWERLIMITER_RESTART_HOUR;
|
||||
|
||||
JsonObject battery = doc["battery"];
|
||||
config.Battery_Enabled = battery["enabled"] | BATTERY_ENABLED;
|
||||
|
||||
@ -53,6 +53,27 @@ void PowerLimiterClass::loop()
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if next inverter restart time is reached
|
||||
if ((_nextInverterRestart > 1) && (_nextInverterRestart <= millis())) {
|
||||
MessageOutput.println("[PowerLimiterClass::loop] send inverter restart");
|
||||
inverter->sendRestartControlRequest();
|
||||
calcNextInverterRestart();
|
||||
}
|
||||
|
||||
// Check if NTP time is set and next inverter restart not calculated yet
|
||||
if ((config.PowerLimiter_RestartHour >= 0) && (_nextInverterRestart == 0) ) {
|
||||
// check every 5 seconds
|
||||
if (_nextCalculateCheck < millis()) {
|
||||
struct tm timeinfo;
|
||||
if (getLocalTime(&timeinfo, 5)) {
|
||||
calcNextInverterRestart();
|
||||
} else {
|
||||
MessageOutput.println("[PowerLimiterClass::loop] inverter restart calculation: NTP not ready");
|
||||
_nextCalculateCheck += 5000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure inverter is turned off if PL is disabled by user/MQTT
|
||||
if (((!config.PowerLimiter_Enabled || _disabled) && _plState != SHUTDOWN)) {
|
||||
if (inverter->isProducing()) {
|
||||
@ -155,7 +176,7 @@ void PowerLimiterClass::loop()
|
||||
MessageOutput.printf("[PowerLimiterClass::loop] Status Batt: Ena: %i, SOC: %i, StartTH: %i, StopTH: %i, LastUpdate: %li\r\n",
|
||||
config.Battery_Enabled, Battery.stateOfCharge, config.PowerLimiter_BatterySocStartThreshold, config.PowerLimiter_BatterySocStopThreshold, millis() - Battery.stateOfChargeLastUpdate);
|
||||
MessageOutput.printf("[PowerLimiterClass::loop] ******************* Leaving PL, PL set to: %i, SP: %i, Batt: %i, PM: %f\r\n", newPowerLimit, canUseDirectSolarPower(), _batteryDischargeEnabled, round(PowerMeter.getPowerTotal()));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t PowerLimiterClass::getPowerLimiterState() {
|
||||
@ -384,4 +405,44 @@ bool PowerLimiterClass::isStopThresholdReached(std::shared_ptr<InverterAbstract>
|
||||
|
||||
float correctedDcVoltage = getLoadCorrectedVoltage(inverter);
|
||||
return correctedDcVoltage <= config.PowerLimiter_VoltageStopThreshold;
|
||||
}
|
||||
|
||||
/// @brief calculate next inverter restart in millis
|
||||
void PowerLimiterClass::calcNextInverterRestart()
|
||||
{
|
||||
CONFIG_T& config = Configuration.get();
|
||||
|
||||
// first check if restart is configured at all
|
||||
if (config.PowerLimiter_RestartHour < 0) {
|
||||
_nextInverterRestart = 1;
|
||||
MessageOutput.println("[PowerLimiterClass::calcNextInverterRestart] _nextInverterRestart disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
// read time from timeserver, if time is not synced then return
|
||||
struct tm timeinfo;
|
||||
if (getLocalTime(&timeinfo, 5)) {
|
||||
// calculation first step is offset to next restart in minutes
|
||||
uint16_t dayMinutes = timeinfo.tm_hour * 60 + timeinfo.tm_min;
|
||||
uint16_t targetMinutes = config.PowerLimiter_RestartHour * 60;
|
||||
if (config.PowerLimiter_RestartHour > timeinfo.tm_hour) {
|
||||
// next restart is on the same day
|
||||
_nextInverterRestart = targetMinutes - dayMinutes;
|
||||
} else {
|
||||
// next restart is on next day
|
||||
_nextInverterRestart = 1440 - dayMinutes + targetMinutes;
|
||||
}
|
||||
#ifdef POWER_LIMITER_DEBUG
|
||||
MessageOutput.printf("[PowerLimiterClass::calcNextInverterRestart] Localtime read %d %d / configured RestartHour %d\r\n", timeinfo.tm_hour, timeinfo.tm_min, config.PowerLimiter_RestartHour);
|
||||
MessageOutput.printf("[PowerLimiterClass::calcNextInverterRestart] dayMinutes %d / targetMinutes %d\r\n", dayMinutes, targetMinutes);
|
||||
MessageOutput.printf("[PowerLimiterClass::calcNextInverterRestart] next inverter restart in %d minutes\r\n", _nextInverterRestart);
|
||||
#endif
|
||||
// then convert unit for next restart to milliseconds and add current uptime millis()
|
||||
_nextInverterRestart *= 60000;
|
||||
_nextInverterRestart += millis();
|
||||
} else {
|
||||
MessageOutput.println("[PowerLimiterClass::calcNextInverterRestart] getLocalTime not successful, no calculation");
|
||||
_nextInverterRestart = 0;
|
||||
}
|
||||
MessageOutput.printf("[PowerLimiterClass::calcNextInverterRestart] _nextInverterRestart @ %d millis\r\n", _nextInverterRestart);
|
||||
}
|
||||
@ -52,6 +52,7 @@ void WebApiPowerLimiterClass::onStatus(AsyncWebServerRequest* request)
|
||||
root[F("voltage_start_threshold")] = static_cast<int>(config.PowerLimiter_VoltageStartThreshold * 100 +0.5) / 100.0;
|
||||
root[F("voltage_stop_threshold")] = static_cast<int>(config.PowerLimiter_VoltageStopThreshold * 100 +0.5) / 100.0;;
|
||||
root[F("voltage_load_correction_factor")] = config.PowerLimiter_VoltageLoadCorrectionFactor;
|
||||
root[F("inverter_restart_hour")] = config.PowerLimiter_RestartHour;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -136,8 +137,11 @@ void WebApiPowerLimiterClass::onAdminPost(AsyncWebServerRequest* request)
|
||||
config.PowerLimiter_VoltageStopThreshold = root[F("voltage_stop_threshold")].as<float>();
|
||||
config.PowerLimiter_VoltageStopThreshold = static_cast<int>(config.PowerLimiter_VoltageStopThreshold * 100) / 100.0;
|
||||
config.PowerLimiter_VoltageLoadCorrectionFactor = root[F("voltage_load_correction_factor")].as<float>();
|
||||
config.PowerLimiter_RestartHour = root[F("inverter_restart_hour")].as<int8_t>();
|
||||
Configuration.write();
|
||||
|
||||
PowerLimiter.calcNextInverterRestart();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
|
||||
|
||||
@ -541,6 +541,9 @@
|
||||
"InverterIsBehindPowerMeter": "Welchselrichter ist hinter Leistungsmesser",
|
||||
"Battery": "DC / Akku",
|
||||
"VoltageLoadCorrectionInfo": "<b>Hinweis:</b> Wenn Leistung von der Batterie abgegeben wird, bricht normalerweise die Spannung etwas ein. Damit nicht vorzeitig der Wechelrichter ausgeschaltet wird sobald der \"Stop\"-Schwellenwert erreicht wird, wird der hier angegebene Korrekturfaktor mit einberechnet. Korrigierte Spannung = DC Spannung + (Aktuelle Leistung (W) + Korrekturfaktor).",
|
||||
"InverterRestart": "Wechselrichter Neustart",
|
||||
"InverterRestartHour": "Stunde für Neustart",
|
||||
"InverterRestartHint": "Neustart des Wechselrichter einmal täglich um die \"Tagesertrag\" Werte wieder auf Null zu setzen.",
|
||||
"Save": "@:dtuadmin.Save"
|
||||
},
|
||||
"batteryadmin": {
|
||||
|
||||
@ -545,6 +545,9 @@
|
||||
"InverterIsBehindPowerMeter": "Inverter is behind Power meter",
|
||||
"Battery": "DC / Battery",
|
||||
"VoltageLoadCorrectionInfo": "<b>Hint:</b> When the power output is higher, the voltage is usually decreasing. In order to not stop the inverter too early (Stop treshold), a power factor can be specified here to correct this. Corrected voltage = DC Voltage + (Current power * correction factor).",
|
||||
"InverterRestart": "Inverter Restart",
|
||||
"InverterRestartHour": "Restart Hour",
|
||||
"InverterRestartHint": "Restart the Inverter once a day to reset the \"YieldDay\" values.",
|
||||
"Save": "@:dtuadmin.Save"
|
||||
},
|
||||
"batteryadmin": {
|
||||
|
||||
@ -14,4 +14,5 @@ export interface PowerLimiterConfig {
|
||||
voltage_start_threshold: number;
|
||||
voltage_stop_threshold: number;
|
||||
voltage_load_correction_factor: number;
|
||||
inverter_restart_hour: number;
|
||||
}
|
||||
|
||||
@ -193,6 +193,24 @@
|
||||
<div class="alert alert-secondary" role="alert" v-html="$t('powerlimiteradmin.VoltageLoadCorrectionInfo')"></div>
|
||||
</CardElement>
|
||||
|
||||
<CardElement :text="$t('powerlimiteradmin.InverterRestart')" textVariant="text-bg-primary" add-space
|
||||
v-show="powerLimiterConfigList.enabled"
|
||||
>
|
||||
<div class="row mb-3" v-show="powerLimiterConfigList.enabled">
|
||||
<label for="inputTimezone" class="col-sm-2 col-form-label">
|
||||
{{ $t('powerlimiteradmin.InverterRestartHour') }}:
|
||||
<BIconInfoCircle v-tooltip :title="$t('powerlimiteradmin.InverterRestartHint')" />
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-select" v-model="powerLimiterConfigList.inverter_restart_hour">
|
||||
<option v-for="hour in restartHourList" :key="hour.key" :value="hour.key">
|
||||
{{ hour.value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</CardElement>
|
||||
|
||||
<button type="submit" class="btn btn-primary mb-3">{{ $t('powerlimiteradmin.Save') }}</button>
|
||||
</form>
|
||||
</BasePage>
|
||||
@ -243,6 +261,33 @@ export default defineComponent({
|
||||
{ key: 0, value: "powerlimiteradmin.BatteryDrainWhenFull"},
|
||||
{ key: 1, value: "powerlimiteradmin.BatteryDrainAtNight" },
|
||||
],
|
||||
restartHourList: [
|
||||
{ key: -1, value: "- - - -" },
|
||||
{ key: 0, value: "0:00" },
|
||||
{ key: 1, value: "1:00" },
|
||||
{ key: 2, value: "2:00" },
|
||||
{ key: 3, value: "3:00" },
|
||||
{ key: 4, value: "4:00" },
|
||||
{ key: 5, value: "5:00" },
|
||||
{ key: 6, value: "6:00" },
|
||||
{ key: 7, value: "7:00" },
|
||||
{ key: 8, value: "8:00" },
|
||||
{ key: 9, value: "9:00" },
|
||||
{ key: 10, value: "10:00" },
|
||||
{ key: 11, value: "11:00" },
|
||||
{ key: 12, value: "12:00" },
|
||||
{ key: 13, value: "13:00" },
|
||||
{ key: 14, value: "14:00" },
|
||||
{ key: 15, value: "15:00" },
|
||||
{ key: 16, value: "16:00" },
|
||||
{ key: 17, value: "17:00" },
|
||||
{ key: 18, value: "18:00" },
|
||||
{ key: 19, value: "19:00" },
|
||||
{ key: 20, value: "20:00" },
|
||||
{ key: 21, value: "21:00" },
|
||||
{ key: 22, value: "22:00" },
|
||||
{ key: 23, value: "23:00" },
|
||||
],
|
||||
alertMessage: "",
|
||||
alertType: "info",
|
||||
showAlert: false,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user