refactor: reworked emergency mode; reworked hysteresis algorithm; improved detection of connection state for MANUAL & BOILER type sensors

This commit is contained in:
Yurii
2024-10-31 01:36:21 +03:00
parent 11b1277d79
commit a6e8953807
10 changed files with 245 additions and 451 deletions

View File

@@ -29,27 +29,55 @@ protected:
#endif
void loop() {
float newTemp = vars.parameters.heatingSetpoint;
if (vars.states.emergency) {
if (settings.heating.turbo) {
settings.heating.turbo = false;
Log.sinfoln(FPSTR(L_REGULATOR), F("Turbo mode auto disabled"));
}
newTemp = this->getEmergencyModeTemp();
} else {
if (settings.heating.turbo && (fabs(settings.heating.target - vars.temperatures.indoor) < 1 || !settings.heating.enable || (settings.equitherm.enable && settings.pid.enable))) {
settings.heating.turbo = false;
Log.sinfoln(FPSTR(L_REGULATOR), F("Turbo mode auto disabled"));
}
newTemp = this->getNormalModeTemp();
bool pidIntergralResetted = false;
if (fabs(pidRegulator.Kp - settings.pid.p_factor) >= 0.0001f) {
pidRegulator.Kp = settings.pid.p_factor;
pidRegulator.integral = 0;
pidIntergralResetted = true;
}
if (fabs(pidRegulator.Ki - settings.pid.i_factor) >= 0.0001f) {
pidRegulator.Ki = settings.pid.i_factor;
pidRegulator.integral = 0;
pidIntergralResetted = true;
}
if (fabs(pidRegulator.Kd - settings.pid.d_factor) >= 0.0001f) {
pidRegulator.Kd = settings.pid.d_factor;
pidRegulator.integral = 0;
pidIntergralResetted = true;
}
if (!settings.pid.enable && fabs(pidRegulator.integral) > 0.01f) {
pidRegulator.integral = 0.0f;
pidIntergralResetted = true;
}
if (pidIntergralResetted) {
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
}
if (settings.heating.turbo) {
if (!settings.heating.enable || vars.states.emergency) {
settings.heating.turbo = false;
} else if (settings.pid.enable) {
settings.heating.turbo = false; // not implemented
} else if (fabs(settings.heating.target - vars.temperatures.indoor) < 1.0f) {
settings.heating.turbo = false;
}
if (!settings.heating.turbo) {
Log.sinfoln(FPSTR(L_REGULATOR), F("Turbo mode auto disabled"));
}
}
float newTemp = vars.states.emergency
? settings.emergency.target
: this->getNormalModeTemp();
// Limits
newTemp = constrain(
newTemp,
@@ -57,58 +85,12 @@ protected:
!settings.opentherm.nativeHeatingControl ? settings.heating.maxTemp : THERMOSTAT_INDOOR_MAX_TEMP
);
if (fabs(vars.parameters.heatingSetpoint - newTemp) > 0.4999f) {
if (fabs(vars.parameters.heatingSetpoint - newTemp) > 0.09f) {
vars.parameters.heatingSetpoint = newTemp;
}
}
float getEmergencyModeTemp() {
float newTemp = 0;
// if use equitherm
if (settings.emergency.useEquitherm) {
float etResult = getEquithermTemp(settings.heating.minTemp, settings.heating.maxTemp);
if (fabs(prevEtResult - etResult) > 0.4999f) {
prevEtResult = etResult;
newTemp += etResult;
Log.sinfoln(FPSTR(L_REGULATOR_EQUITHERM), F("New emergency result: %.2f"), etResult);
} else {
newTemp += prevEtResult;
}
} else if(settings.emergency.usePid) {
if (vars.parameters.heatingEnabled) {
float pidResult = getPidTemp(
settings.heating.minTemp,
settings.heating.maxTemp
);
if (fabs(prevPidResult - pidResult) > 0.4999f) {
prevPidResult = pidResult;
newTemp += pidResult;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("New emergency result: %.2f"), pidResult);
} else {
newTemp += prevPidResult;
}
} else if (!vars.parameters.heatingEnabled && prevPidResult != 0) {
newTemp += prevPidResult;
}
} else {
// default temp, manual mode
newTemp = settings.emergency.target;
}
return newTemp;
}
float getNormalModeTemp() {
float newTemp = 0;
@@ -116,17 +98,49 @@ protected:
prevHeatingTarget = settings.heating.target;
Log.sinfoln(FPSTR(L_REGULATOR), F("New target: %.2f"), settings.heating.target);
if (/*settings.equitherm.enable && */settings.pid.enable) {
/*if (settings.pid.enable) {
pidRegulator.integral = 0;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
}
}*/
}
// if use equitherm
if (settings.equitherm.enable) {
float etResult = getEquithermTemp(settings.heating.minTemp, settings.heating.maxTemp);
unsigned short minTemp = settings.heating.minTemp;
unsigned short maxTemp = settings.heating.maxTemp;
float targetTemp = settings.heating.target;
float indoorTemp = vars.temperatures.indoor;
float outdoorTemp = vars.temperatures.outdoor;
if (fabs(prevEtResult - etResult) > 0.4999f) {
if (settings.system.unitSystem == UnitSystem::IMPERIAL) {
minTemp = f2c(minTemp);
maxTemp = f2c(maxTemp);
targetTemp = f2c(targetTemp);
indoorTemp = f2c(indoorTemp);
outdoorTemp = f2c(outdoorTemp);
}
if (!vars.sensors.indoor.connected || settings.pid.enable) {
etRegulator.Kt = 0;
etRegulator.indoorTemp = 0;
} else {
etRegulator.Kt = settings.heating.turbo ? 10.0f : settings.equitherm.t_factor;
etRegulator.indoorTemp = indoorTemp;
}
etRegulator.setLimits(minTemp, maxTemp);
etRegulator.Kn = settings.equitherm.n_factor;
etRegulator.Kk = settings.equitherm.k_factor;
etRegulator.targetTemp = targetTemp;
etRegulator.outdoorTemp = outdoorTemp;
float etResult = etRegulator.getResult();
if (settings.system.unitSystem == UnitSystem::IMPERIAL) {
etResult = c2f(etResult);
}
if (fabs(prevEtResult - etResult) > 0.09f) {
prevEtResult = etResult;
newTemp += etResult;
@@ -140,13 +154,14 @@ protected:
// if use pid
if (settings.pid.enable) {
//if (vars.parameters.heatingEnabled) {
if (settings.heating.enable) {
float pidResult = getPidTemp(
settings.equitherm.enable ? (settings.pid.maxTemp * -1) : settings.pid.minTemp,
settings.pid.maxTemp
);
if (settings.heating.enable && vars.sensors.indoor.connected) {
pidRegulator.setLimits(settings.pid.minTemp, settings.pid.maxTemp);
pidRegulator.setDt(settings.pid.dt * 1000u);
pidRegulator.input = vars.temperatures.indoor;
pidRegulator.setpoint = settings.heating.target;
if (fabs(prevPidResult - pidResult) > 0.4999f) {
float pidResult = pidRegulator.getResultTimer();
if (fabs(prevPidResult - pidResult) > 0.09f) {
prevPidResult = pidResult;
newTemp += pidResult;
@@ -156,13 +171,10 @@ protected:
} else {
newTemp += prevPidResult;
}
} else {
newTemp += prevPidResult;
}
} else if (fabs(pidRegulator.integral) > 0.0001f) {
pidRegulator.integral = 0;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
}
// default temp, manual mode
@@ -172,96 +184,4 @@ protected:
return newTemp;
}
/**
* @brief Get the Equitherm Temp
* Calculations in degrees C, conversion occurs when using F
*
* @param minTemp
* @param maxTemp
* @return float
*/
float getEquithermTemp(int minTemp, int maxTemp) {
float targetTemp = vars.states.emergency ? settings.emergency.target : settings.heating.target;
float indoorTemp = vars.temperatures.indoor;
float outdoorTemp = vars.temperatures.outdoor;
if (settings.system.unitSystem == UnitSystem::IMPERIAL) {
minTemp = f2c(minTemp);
maxTemp = f2c(maxTemp);
targetTemp = f2c(targetTemp);
indoorTemp = f2c(indoorTemp);
outdoorTemp = f2c(outdoorTemp);
}
if (vars.states.emergency) {
if (settings.sensors.indoor.type == SensorType::MANUAL) {
etRegulator.Kt = 0;
etRegulator.indoorTemp = 0;
} else if ((settings.sensors.indoor.type == SensorType::DS18B20 || settings.sensors.indoor.type == SensorType::BLUETOOTH) && !vars.sensors.indoor.connected) {
etRegulator.Kt = 0;
etRegulator.indoorTemp = 0;
} else {
etRegulator.Kt = settings.equitherm.t_factor;
etRegulator.indoorTemp = indoorTemp;
}
etRegulator.outdoorTemp = outdoorTemp;
} else if (settings.pid.enable) {
etRegulator.Kt = 0;
etRegulator.indoorTemp = round(indoorTemp);
etRegulator.outdoorTemp = round(outdoorTemp);
} else {
if (settings.heating.turbo) {
etRegulator.Kt = 10;
} else {
etRegulator.Kt = settings.equitherm.t_factor;
}
etRegulator.indoorTemp = indoorTemp;
etRegulator.outdoorTemp = outdoorTemp;
}
etRegulator.setLimits(minTemp, maxTemp);
etRegulator.Kn = settings.equitherm.n_factor;
etRegulator.Kk = settings.equitherm.k_factor;
etRegulator.targetTemp = targetTemp;
float result = etRegulator.getResult();
if (settings.system.unitSystem == UnitSystem::IMPERIAL) {
result = c2f(result);
}
return result;
}
float getPidTemp(int minTemp, int maxTemp) {
if (fabs(pidRegulator.Kp - settings.pid.p_factor) >= 0.0001f) {
pidRegulator.Kp = settings.pid.p_factor;
pidRegulator.integral = 0;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
}
if (fabs(pidRegulator.Ki - settings.pid.i_factor) >= 0.0001f) {
pidRegulator.Ki = settings.pid.i_factor;
pidRegulator.integral = 0;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
}
if (fabs(pidRegulator.Kd - settings.pid.d_factor) >= 0.0001f) {
pidRegulator.Kd = settings.pid.d_factor;
pidRegulator.integral = 0;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
}
pidRegulator.setLimits(minTemp, maxTemp);
pidRegulator.setDt(settings.pid.dt * 1000u);
pidRegulator.input = vars.temperatures.indoor;
pidRegulator.setpoint = vars.states.emergency ? settings.emergency.target : settings.heating.target;
return pidRegulator.getResultTimer();
}
};