fix: PID optimization, correction of default PID settings

This commit is contained in:
Yurii
2024-04-18 00:04:23 +03:00
parent cca8ec58b4
commit d35ea81080
5 changed files with 31 additions and 12 deletions

View File

@@ -623,7 +623,7 @@ public:
doc[FPSTR(HA_NAME)] = F("PID factor I"); doc[FPSTR(HA_NAME)] = F("PID factor I");
doc[FPSTR(HA_ICON)] = F("mdi:alpha-i-circle-outline"); doc[FPSTR(HA_ICON)] = F("mdi:alpha-i-circle-outline");
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings")); doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("settings"));
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.i_factor|float(0)|round(3) }}"); doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.pid.i_factor|float(0)|round(4) }}");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set")); doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("settings/set"));
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"i_factor\" : {{ value }}}}"); doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"pid\": {\"i_factor\" : {{ value }}}}");
doc[FPSTR(HA_MIN)] = 0; doc[FPSTR(HA_MIN)] = 0;

View File

@@ -133,7 +133,7 @@ protected:
prevHeatingTarget = settings.heating.target; prevHeatingTarget = settings.heating.target;
Log.sinfoln(FPSTR(L_REGULATOR), F("New target: %.2f"), settings.heating.target); Log.sinfoln(FPSTR(L_REGULATOR), F("New target: %.2f"), settings.heating.target);
if (settings.equitherm.enable && settings.pid.enable) { if (/*settings.equitherm.enable && */settings.pid.enable) {
pidRegulator.integral = 0; pidRegulator.integral = 0;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset")); Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
} }
@@ -167,6 +167,7 @@ protected:
newTemp += pidResult; newTemp += pidResult;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("New result: %hhd (%.2f)"), (int8_t) round(pidResult), pidResult); Log.sinfoln(FPSTR(L_REGULATOR_PID), F("New result: %hhd (%.2f)"), (int8_t) round(pidResult), pidResult);
Log.straceln(FPSTR(L_REGULATOR_PID), F("Integral: %.2f"), pidRegulator.integral);
} else { } else {
newTemp += prevPidResult; newTemp += prevPidResult;
@@ -174,6 +175,10 @@ protected:
} else { } else {
newTemp += prevPidResult; newTemp += prevPidResult;
} }
} else if (pidRegulator.integral != 0) {
pidRegulator.integral = 0;
Log.sinfoln(FPSTR(L_REGULATOR_PID), F("Integral sum has been reset"));
} }
// default temp, manual mode // default temp, manual mode
@@ -327,9 +332,23 @@ protected:
} }
float getPidTemp(int minTemp, int maxTemp) { float getPidTemp(int minTemp, int maxTemp) {
pidRegulator.Kp = settings.pid.p_factor; if (fabs(pidRegulator.Kp - settings.pid.p_factor) >= 0.0001f) {
pidRegulator.Ki = settings.pid.i_factor; pidRegulator.Kp = settings.pid.p_factor;
pidRegulator.Kd = settings.pid.d_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.setLimits(minTemp, maxTemp);
pidRegulator.setDt(settings.pid.dt * 1000u); pidRegulator.setDt(settings.pid.dt * 1000u);
@@ -342,7 +361,7 @@ protected:
float tuneEquithermN(float ratio, float currentTemp, float setTemp, unsigned int dirtyInterval = 60, unsigned int accurateInterval = 1800, float accurateStep = 0.01, float accurateStepAfter = 1) { float tuneEquithermN(float ratio, float currentTemp, float setTemp, unsigned int dirtyInterval = 60, unsigned int accurateInterval = 1800, float accurateStep = 0.01, float accurateStepAfter = 1) {
static uint32_t _prevIteration = millis(); static uint32_t _prevIteration = millis();
if (abs(currentTemp - setTemp) < accurateStepAfter) { if (fabs(currentTemp - setTemp) < accurateStepAfter) {
if (millis() - _prevIteration < (accurateInterval * 1000)) { if (millis() - _prevIteration < (accurateInterval * 1000)) {
return ratio; return ratio;
} }

View File

@@ -101,9 +101,9 @@ struct Settings {
struct { struct {
bool enable = false; bool enable = false;
float p_factor = 50; float p_factor = 2;
float i_factor = 0.006f; float i_factor = 0.0055f;
float d_factor = 10000; float d_factor = 0;
unsigned short dt = 180; unsigned short dt = 180;
byte minTemp = 0; byte minTemp = 0;
byte maxTemp = DEFAULT_HEATING_MAX_TEMP; byte maxTemp = DEFAULT_HEATING_MAX_TEMP;

View File

@@ -384,7 +384,7 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) {
dst["pid"]["enable"] = src.pid.enable; dst["pid"]["enable"] = src.pid.enable;
dst["pid"]["p_factor"] = roundd(src.pid.p_factor, 3); dst["pid"]["p_factor"] = roundd(src.pid.p_factor, 3);
dst["pid"]["i_factor"] = roundd(src.pid.i_factor, 3); dst["pid"]["i_factor"] = roundd(src.pid.i_factor, 4);
dst["pid"]["d_factor"] = roundd(src.pid.d_factor, 1); dst["pid"]["d_factor"] = roundd(src.pid.d_factor, 1);
dst["pid"]["dt"] = src.pid.dt; dst["pid"]["dt"] = src.pid.dt;
dst["pid"]["minTemp"] = src.pid.minTemp; dst["pid"]["minTemp"] = src.pid.minTemp;
@@ -836,7 +836,7 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false
double value = src["pid"]["i_factor"].as<double>(); double value = src["pid"]["i_factor"].as<double>();
if (value >= 0 && value <= 100) { if (value >= 0 && value <= 100) {
dst.pid.i_factor = roundd(value, 3); dst.pid.i_factor = roundd(value, 4);
changed = true; changed = true;
} }
} }

View File

@@ -315,7 +315,7 @@
<label for="pid-i-factor"> <label for="pid-i-factor">
I factor I factor
<input type="number" inputmode="numeric" id="pid-i-factor" name="pid[i_factor]" min="0" max="100" step="0.001" required> <input type="number" inputmode="numeric" id="pid-i-factor" name="pid[i_factor]" min="0" max="100" step="0.0001" required>
</label> </label>
<label for="pid-d-factor"> <label for="pid-d-factor">