pi without the d
This commit is contained in:
@@ -11,10 +11,11 @@
|
||||
|
||||
class ThermalController {
|
||||
public:
|
||||
enum class HeaterBlock : uint8_t { None, Cutoff, Corner, Allow, Autotune, StepResp };
|
||||
enum class HeaterBlock : uint8_t { None, Cutoff, Corner, Autotune, StepResp };
|
||||
|
||||
ThermalController()
|
||||
: pid_(PID_KP, PID_KI, PID_KD, 0.0f, 100.0f),
|
||||
: heatPi_(HEAT_PI_KP, HEAT_PI_KI, 0.0f, 0.0f, 100.0f),
|
||||
mixPi_(MIX_PI_KP, MIX_PI_KI, 0.0f, 0.0f, 255.0f),
|
||||
autotuner_(),
|
||||
stepresp_(),
|
||||
targetTempC_(TARGET_TEMP_C),
|
||||
@@ -22,9 +23,9 @@ public:
|
||||
heaterAllowancePercent_(100.0f),
|
||||
cornerSpreadC_(0.0f),
|
||||
lastMaxTempC_(0.0f),
|
||||
fanPwm_(FAN_MAX_PWM),
|
||||
fanMixMax_(FAN_MIX_MAX_PWM),
|
||||
adaptiveEnabled_(false),
|
||||
regulatingFanPwm_(0),
|
||||
fanPwm_(0),
|
||||
tuningLoaded_(false),
|
||||
fanIdleOverride_(false),
|
||||
sensorWarmValid_(false),
|
||||
cutoffActive_(false),
|
||||
@@ -36,7 +37,9 @@ public:
|
||||
heaterBlock_(HeaterBlock::None),
|
||||
fanTestActive_(false),
|
||||
fanTestPwm_(0),
|
||||
fanTestEndMs_(0) {}
|
||||
fanTestEndMs_(0) {
|
||||
mixPi_.setSetpoint(0.0f);
|
||||
}
|
||||
|
||||
void begin() {
|
||||
pinMode(FAN_PIN, OUTPUT);
|
||||
@@ -44,12 +47,12 @@ public:
|
||||
digitalWrite(HEATER_PIN, LOW);
|
||||
writeFan(0);
|
||||
|
||||
pid_.setSetpoint(targetTempC_);
|
||||
pid_.reset();
|
||||
heatPi_.setSetpoint(targetTempC_);
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
heaterCycleStartMs_ = millis();
|
||||
lastHeaterUpdateMs_ = 0;
|
||||
failSafeActive_ = true;
|
||||
fanPwm_ = FAN_MAX_PWM;
|
||||
cornerSpreadC_ = 0.0f;
|
||||
lastMaxTempC_ = 0.0f;
|
||||
sensorWarmValid_ = false;
|
||||
@@ -62,7 +65,7 @@ public:
|
||||
TuningData stored;
|
||||
if (tuningLoad(stored)) {
|
||||
applyTuning(stored);
|
||||
Serial.println(F("Loaded learned PID from EEPROM"));
|
||||
Serial.println(F("Loaded learned PI from EEPROM"));
|
||||
printTuning();
|
||||
}
|
||||
|
||||
@@ -74,46 +77,75 @@ public:
|
||||
}
|
||||
|
||||
void applyTuning(const TuningData &data) {
|
||||
pid_.setTunings(data.kp, data.ki, data.kd);
|
||||
fanMixMax_ = data.fanMixMax;
|
||||
adaptiveEnabled_ = true;
|
||||
heatPi_.setTunings(data.heatKp, data.heatKi, 0.0f);
|
||||
mixPi_.setTunings(data.mixKp, data.mixKi, 0.0f);
|
||||
tuningLoaded_ = true;
|
||||
}
|
||||
|
||||
void clearTuning() {
|
||||
adaptiveEnabled_ = false;
|
||||
fanMixMax_ = FAN_MIX_MAX_PWM;
|
||||
pid_.setTunings(PID_KP, PID_KI, PID_KD);
|
||||
tuningLoaded_ = false;
|
||||
heatPi_.setTunings(HEAT_PI_KP, HEAT_PI_KI, 0.0f);
|
||||
mixPi_.setTunings(MIX_PI_KP, MIX_PI_KI, 0.0f);
|
||||
tuningClear();
|
||||
pid_.reset();
|
||||
Serial.println(F("PID reset to defaults"));
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
Serial.println(F("PI reset to defaults"));
|
||||
}
|
||||
|
||||
void setMixTunings(float kp, float ki) {
|
||||
mixPi_.setTunings(kp, ki, 0.0f);
|
||||
mixPi_.reset();
|
||||
Serial.print(F("Mix PI Kp="));
|
||||
Serial.print(kp, 3);
|
||||
Serial.print(F(" Ki="));
|
||||
Serial.println(ki, 4);
|
||||
}
|
||||
|
||||
void resetMixTunings() {
|
||||
mixPi_.setTunings(MIX_PI_KP, MIX_PI_KI, 0.0f);
|
||||
mixPi_.reset();
|
||||
Serial.println(F("Mix PI reset to defaults"));
|
||||
}
|
||||
|
||||
void printTuning() const {
|
||||
Serial.print(F("PID Kp="));
|
||||
Serial.print(pidKp(), 3);
|
||||
Serial.print(F("Heat PI Kp="));
|
||||
Serial.print(heatPi_.kp(), 3);
|
||||
Serial.print(F(" Ki="));
|
||||
Serial.print(pidKi(), 4);
|
||||
Serial.print(F(" Kd="));
|
||||
Serial.print(pidKd(), 3);
|
||||
Serial.print(F(" fanMixMax="));
|
||||
Serial.print(fanMixMax_);
|
||||
Serial.print(F(" adaptive="));
|
||||
Serial.println(adaptiveEnabled_ ? F("yes") : F("no"));
|
||||
Serial.print(heatPi_.ki(), 4);
|
||||
Serial.print(F(" Mix PI Kp="));
|
||||
Serial.print(mixPi_.kp(), 3);
|
||||
Serial.print(F(" Ki="));
|
||||
Serial.print(mixPi_.ki(), 4);
|
||||
Serial.print(F(" tuned="));
|
||||
Serial.println(tuningLoaded_ ? F("yes") : F("no"));
|
||||
}
|
||||
|
||||
float pidKp() const { return pid_.kp(); }
|
||||
float pidKi() const { return pid_.ki(); }
|
||||
float pidKd() const { return pid_.kd(); }
|
||||
void saveTuningToEeprom() {
|
||||
TuningData data;
|
||||
data.magic = TUNING_MAGIC;
|
||||
data.heatKp = heatPi_.kp();
|
||||
data.heatKi = heatPi_.ki();
|
||||
data.mixKp = mixPi_.kp();
|
||||
data.mixKi = mixPi_.ki();
|
||||
tuningSave(data);
|
||||
tuningLoaded_ = true;
|
||||
Serial.println(F("Saved PI to EEPROM"));
|
||||
}
|
||||
|
||||
bool isAdaptive() const { return adaptiveEnabled_; }
|
||||
float heatKp() const { return heatPi_.kp(); }
|
||||
float heatKi() const { return heatPi_.ki(); }
|
||||
float mixKp() const { return mixPi_.kp(); }
|
||||
float mixKi() const { return mixPi_.ki(); }
|
||||
|
||||
bool isTuningLoaded() const { return tuningLoaded_; }
|
||||
|
||||
bool startAutotune(float setpointC) {
|
||||
if (autotuner_.isActive() || stepresp_.isActive()) {
|
||||
return false;
|
||||
}
|
||||
adaptiveEnabled_ = false;
|
||||
cutoffActive_ = false;
|
||||
pid_.reset();
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
return autotuner_.start(setpointC);
|
||||
}
|
||||
|
||||
@@ -136,9 +168,9 @@ public:
|
||||
return false;
|
||||
}
|
||||
stopFanTest();
|
||||
adaptiveEnabled_ = false;
|
||||
cutoffActive_ = false;
|
||||
pid_.reset();
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
setTarget(targetC, false);
|
||||
if (!stepresp_.start(targetC, heaterPct)) {
|
||||
return false;
|
||||
@@ -176,23 +208,27 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
heatPi_.setTunings(autotuner_.resultKp(), autotuner_.resultKi(), 0.0f);
|
||||
heatPi_.reset();
|
||||
|
||||
TuningData data;
|
||||
data.magic = TUNING_MAGIC;
|
||||
data.kp = autotuner_.resultKp();
|
||||
data.ki = autotuner_.resultKi();
|
||||
data.kd = autotuner_.resultKd();
|
||||
data.fanMixMax = autotuner_.resultFanMixMax();
|
||||
data.heatKp = autotuner_.resultKp();
|
||||
data.heatKi = autotuner_.resultKi();
|
||||
data.mixKp = mixPi_.kp();
|
||||
data.mixKi = mixPi_.ki();
|
||||
tuningSave(data);
|
||||
applyTuning(data);
|
||||
tuningLoaded_ = true;
|
||||
autotuner_.reset();
|
||||
Serial.println(F("Saved learned PID to EEPROM"));
|
||||
Serial.println(F("Saved heat PI to EEPROM (mix PI unchanged)"));
|
||||
return true;
|
||||
}
|
||||
|
||||
void setTarget(float targetC, bool persist = true) {
|
||||
targetTempC_ = targetC;
|
||||
pid_.setSetpoint(targetC);
|
||||
pid_.reset();
|
||||
heatPi_.setSetpoint(targetC);
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
cutoffActive_ = false;
|
||||
if (targetC > 0.0f) {
|
||||
fanIdleOverride_ = false;
|
||||
@@ -280,7 +316,12 @@ public:
|
||||
|
||||
void stopFanTest() { fanTestActive_ = false; }
|
||||
|
||||
float maxHeatStopAt(float avgTempC) const { return maxHeatStopTemp(avgTempC); }
|
||||
float maxHeatStopAt(float avgTempC) const {
|
||||
if (isIdle()) {
|
||||
return INFINITY;
|
||||
}
|
||||
return maxHeatStopTemp(avgTempC);
|
||||
}
|
||||
|
||||
const char *heaterBlockReason() const {
|
||||
switch (heaterBlock_) {
|
||||
@@ -288,8 +329,6 @@ public:
|
||||
return "cutoff";
|
||||
case HeaterBlock::Corner:
|
||||
return "corner";
|
||||
case HeaterBlock::Allow:
|
||||
return "allow";
|
||||
case HeaterBlock::Autotune:
|
||||
return "autotune";
|
||||
case HeaterBlock::StepResp:
|
||||
@@ -299,6 +338,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const char *regulatingModeName() const {
|
||||
return tuningLoaded_ ? "regulating" : "manual";
|
||||
}
|
||||
|
||||
void update(float avgTempC, float maxTempC, float cornerSpreadC, uint32_t nowMs) {
|
||||
failSafeActive_ = false;
|
||||
noteSensorMax(maxTempC);
|
||||
@@ -306,8 +349,8 @@ public:
|
||||
heaterBlock_ = HeaterBlock::None;
|
||||
|
||||
cornerSpreadC_ =
|
||||
SPREAD_EMA_ALPHA * cornerSpreadC +
|
||||
(1.0f - SPREAD_EMA_ALPHA) * cornerSpreadC_;
|
||||
SPREAD_EMA_ALPHA * cornerSpreadC_ +
|
||||
(1.0f - SPREAD_EMA_ALPHA) * cornerSpreadC;
|
||||
|
||||
if (stepresp_.isActive()) {
|
||||
updateStepResponse(avgTempC, maxTempC, nowMs);
|
||||
@@ -322,21 +365,17 @@ public:
|
||||
if (isIdle()) {
|
||||
forceHeaterOff();
|
||||
cutoffActive_ = false;
|
||||
pid_.reset();
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
lastHeaterUpdateMs_ = nowMs;
|
||||
applyFan(nowMs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (adaptiveEnabled_) {
|
||||
updateAdaptive(avgTempC, maxTempC, nowMs);
|
||||
} else {
|
||||
updateLegacy(avgTempC, maxTempC, nowMs);
|
||||
}
|
||||
|
||||
updateRegulating(avgTempC, maxTempC, nowMs);
|
||||
lastHeaterUpdateMs_ = nowMs;
|
||||
applyHeaterBurst(nowMs);
|
||||
applyFan(nowMs);
|
||||
writeFan(regulatingFanPwm_);
|
||||
}
|
||||
|
||||
void enterFailSafe() {
|
||||
@@ -344,7 +383,8 @@ public:
|
||||
cutoffActive_ = false;
|
||||
forceHeaterOff();
|
||||
applyFan(millis());
|
||||
pid_.reset();
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
autotuner_.abort();
|
||||
stepresp_.abort();
|
||||
}
|
||||
@@ -405,7 +445,7 @@ private:
|
||||
|
||||
void updateAutotune(float avgTempC, float maxTempC, uint32_t nowMs) {
|
||||
float duty = 0.0f;
|
||||
uint8_t fan = FAN_HEAT_MIN_PWM;
|
||||
uint8_t fan = AUTOTUNE_PREHEAT_FAN_PWM;
|
||||
autotuner_.update(avgTempC, maxTempC, cornerSpreadC_, nowMs, duty, fan);
|
||||
|
||||
heaterDutyPercent_ = duty;
|
||||
@@ -418,38 +458,33 @@ private:
|
||||
commitAutotuneIfDone();
|
||||
}
|
||||
|
||||
void updateAdaptive(float avgTempC, float maxTempC, uint32_t nowMs) {
|
||||
const float cutoff = cutoffThreshold();
|
||||
|
||||
if (maxTempC >= cutoff) {
|
||||
void updateRegulating(float avgTempC, float maxTempC, uint32_t nowMs) {
|
||||
if (maxTempC >= EMERGENCY_MAX_TEMP_C) {
|
||||
cutoffActive_ = true;
|
||||
heaterDutyPercent_ = 0.0f;
|
||||
heaterAllowancePercent_ = 0.0f;
|
||||
heaterOn_ = false;
|
||||
regulatingFanPwm_ = FAN_MAX_PWM;
|
||||
heaterBlock_ = HeaterBlock::Cutoff;
|
||||
pid_.reset();
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cutoffActive_ && maxTempC <= targetTempC_) {
|
||||
if (cutoffActive_ && maxTempC < EMERGENCY_MAX_TEMP_C - 5.0f) {
|
||||
cutoffActive_ = false;
|
||||
pid_.reset();
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
}
|
||||
|
||||
if (cutoffActive_) {
|
||||
heaterBlock_ = HeaterBlock::Cutoff;
|
||||
regulatingFanPwm_ = FAN_MAX_PWM;
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldLimitMaxCorner(avgTempC) && maxTempC >= maxHeatStopTemp(avgTempC)) {
|
||||
heaterDutyPercent_ = 0.0f;
|
||||
heaterAllowancePercent_ = 0.0f;
|
||||
heaterBlock_ = HeaterBlock::Corner;
|
||||
pid_.reset();
|
||||
return;
|
||||
}
|
||||
heaterAllowancePercent_ = allowanceFromMaxCorner(maxTempC, avgTempC);
|
||||
|
||||
float duty = pid_.compute(avgTempC, nowMs);
|
||||
float duty = heatPi_.compute(avgTempC, nowMs);
|
||||
const float below = targetTempC_ - avgTempC;
|
||||
if (below > 8.0f) {
|
||||
const float floor = below > 15.0f ? 75.0f : 60.0f;
|
||||
@@ -461,51 +496,21 @@ private:
|
||||
if (duty > maxDuty) {
|
||||
duty = maxDuty;
|
||||
}
|
||||
heaterAllowancePercent_ = maxDuty;
|
||||
heaterDutyPercent_ = duty;
|
||||
}
|
||||
|
||||
void updateLegacy(float avgTempC, float maxTempC, uint32_t nowMs) {
|
||||
const float cutoff = cutoffThreshold();
|
||||
|
||||
if (maxTempC >= cutoff) {
|
||||
cutoffActive_ = true;
|
||||
heaterDutyPercent_ = 0.0f;
|
||||
heaterAllowancePercent_ = 0.0f;
|
||||
heaterOn_ = false;
|
||||
heaterBlock_ = HeaterBlock::Cutoff;
|
||||
pid_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cutoffActive_ && maxTempC <= targetTempC_) {
|
||||
cutoffActive_ = false;
|
||||
pid_.reset();
|
||||
}
|
||||
|
||||
if (cutoffActive_) {
|
||||
heaterBlock_ = HeaterBlock::Cutoff;
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldLimitMaxCorner(avgTempC) && maxTempC >= maxHeatStopTemp(avgTempC)) {
|
||||
heaterDutyPercent_ = 0.0f;
|
||||
heaterAllowancePercent_ = 0.0f;
|
||||
heaterBlock_ = HeaterBlock::Corner;
|
||||
pid_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
const float pidOut = pid_.compute(avgTempC, nowMs);
|
||||
heaterAllowancePercent_ = heaterAllowancePercent(avgTempC, maxTempC);
|
||||
float duty = pidOut;
|
||||
if (duty > heaterAllowancePercent_) {
|
||||
duty = heaterAllowancePercent_;
|
||||
}
|
||||
if (duty <= 0.0f && heaterAllowancePercent_ <= 0.0f) {
|
||||
heaterBlock_ = HeaterBlock::Allow;
|
||||
if (heaterAllowancePercent_ < 100.0f) {
|
||||
heaterBlock_ = HeaterBlock::Corner;
|
||||
}
|
||||
}
|
||||
heaterDutyPercent_ = applyHeaterRamp(duty, avgTempC, nowMs);
|
||||
|
||||
const float mixInput = SPREAD_TARGET_C - cornerSpreadC_;
|
||||
float fanOut = mixPi_.compute(mixInput, nowMs);
|
||||
uint8_t fanPwm = static_cast<uint8_t>(fanOut + 0.5f);
|
||||
if (avgTempC < targetTempC_ - HEAT_UP_BAND_C && fanPwm > FAN_COLD_CAP_PWM) {
|
||||
fanPwm = FAN_COLD_CAP_PWM;
|
||||
}
|
||||
regulatingFanPwm_ = fanPwm;
|
||||
}
|
||||
|
||||
static float clampPercent(float value) {
|
||||
@@ -518,8 +523,6 @@ private:
|
||||
return value;
|
||||
}
|
||||
|
||||
bool isBalancedChamber() const { return cornerSpreadC_ <= GOOD_SPREAD_C; }
|
||||
|
||||
bool shouldLimitMaxCorner(float avgTempC) const {
|
||||
return avgTempC >= targetTempC_ - CORNER_LIMIT_BAND_C;
|
||||
}
|
||||
@@ -536,10 +539,6 @@ private:
|
||||
return 100.0f;
|
||||
}
|
||||
|
||||
if (isBalancedChamber() && avgTempC < targetTempC_) {
|
||||
return 100.0f;
|
||||
}
|
||||
|
||||
const float stopAt = maxHeatStopTemp(avgTempC);
|
||||
if (maxTempC >= stopAt) {
|
||||
return 0.0f;
|
||||
@@ -553,19 +552,6 @@ private:
|
||||
return clampPercent((headroom / MAX_TEMP_HEADROOM_C) * 100.0f);
|
||||
}
|
||||
|
||||
float allowanceFromAverage(float avgTempC) const {
|
||||
if (avgTempC >= targetTempC_) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const float below = targetTempC_ - avgTempC;
|
||||
if (below >= APPROACH_BAND_C) {
|
||||
return 100.0f;
|
||||
}
|
||||
|
||||
return clampPercent((below / APPROACH_BAND_C) * 100.0f);
|
||||
}
|
||||
|
||||
float heaterMaxDuty(float avgTempC) const {
|
||||
if (avgTempC >= targetTempC_) {
|
||||
return HEATER_MAX_DUTY_NEAR;
|
||||
@@ -581,17 +567,6 @@ private:
|
||||
return HEATER_MAX_DUTY_NEAR;
|
||||
}
|
||||
|
||||
float heaterAllowancePercent(float avgTempC, float maxTempC) const {
|
||||
const float fromMax = allowanceFromMaxCorner(maxTempC, avgTempC);
|
||||
const float fromAvg = allowanceFromAverage(avgTempC);
|
||||
float allowance = fromMax < fromAvg ? fromMax : fromAvg;
|
||||
const float maxDuty = heaterMaxDuty(avgTempC);
|
||||
if (allowance > maxDuty) {
|
||||
allowance = maxDuty;
|
||||
}
|
||||
return allowance;
|
||||
}
|
||||
|
||||
float applyHeaterRamp(float requestedDuty, float avgTempC, uint32_t nowMs) {
|
||||
const float maxDuty = heaterMaxDuty(avgTempC);
|
||||
if (requestedDuty > maxDuty) {
|
||||
@@ -609,55 +584,6 @@ private:
|
||||
return requestedDuty;
|
||||
}
|
||||
|
||||
uint8_t fanPwmForHeatUp() const {
|
||||
if (heaterDutyPercent_ <= 0.0f) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const float below = targetTempC_ - lastAvgTempC_;
|
||||
uint8_t heatFan = 0;
|
||||
if (below <= FAN_OFF_BELOW_TARGET_C) {
|
||||
const uint8_t span = FAN_HEAT_MAX_PWM - FAN_HEAT_MIN_PWM;
|
||||
heatFan = FAN_HEAT_MIN_PWM +
|
||||
static_cast<uint8_t>((heaterDutyPercent_ / 100.0f) * static_cast<float>(span));
|
||||
} else if (below < FAN_RAMP_BELOW_TARGET_C) {
|
||||
const float spanC = FAN_RAMP_BELOW_TARGET_C - FAN_OFF_BELOW_TARGET_C;
|
||||
const float t = (FAN_RAMP_BELOW_TARGET_C - below) / spanC;
|
||||
heatFan = static_cast<uint8_t>(t * static_cast<float>(FAN_HEAT_MIN_PWM));
|
||||
}
|
||||
|
||||
uint8_t mixFan = 0;
|
||||
if (below <= FAN_OFF_BELOW_TARGET_C || cornerSpreadC_ > GOOD_SPREAD_C) {
|
||||
mixFan = fanPwmForCornerSpread();
|
||||
}
|
||||
|
||||
uint8_t duty = heatFan > mixFan ? heatFan : mixFan;
|
||||
|
||||
if (lastAvgTempC_ >= targetTempC_ - 2.0f && lastMaxTempC_ > targetTempC_ &&
|
||||
duty < FAN_MAX_PWM) {
|
||||
duty = FAN_MAX_PWM;
|
||||
}
|
||||
return duty;
|
||||
}
|
||||
|
||||
uint8_t fanPwmForCornerSpread() const {
|
||||
if (cornerSpreadC_ <= SPREAD_DEADBAND_C) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float spread = cornerSpreadC_;
|
||||
if (spread > SPREAD_FULL_MIX_C) {
|
||||
spread = SPREAD_FULL_MIX_C;
|
||||
}
|
||||
|
||||
const float t =
|
||||
(spread - SPREAD_DEADBAND_C) / (SPREAD_FULL_MIX_C - SPREAD_DEADBAND_C);
|
||||
const uint8_t mixMax = fanMixMax_;
|
||||
const uint8_t mixMin = FAN_MIX_MIN_PWM;
|
||||
const uint8_t span = mixMax > mixMin ? mixMax - mixMin : 0;
|
||||
return mixMin + static_cast<uint8_t>(t * static_cast<float>(span));
|
||||
}
|
||||
|
||||
void applyHeaterBurst(uint32_t nowMs) {
|
||||
if (heaterDutyPercent_ <= 0.0f) {
|
||||
forceHeaterOff();
|
||||
@@ -702,12 +628,10 @@ private:
|
||||
writeFan(FAN_MAX_PWM);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t duty = fanPwmForHeatUp();
|
||||
writeFan(duty);
|
||||
}
|
||||
|
||||
PidController pid_;
|
||||
PidController heatPi_;
|
||||
PidController mixPi_;
|
||||
PidAutotuner autotuner_;
|
||||
FanStepResponse stepresp_;
|
||||
float targetTempC_;
|
||||
@@ -715,9 +639,9 @@ private:
|
||||
float heaterAllowancePercent_;
|
||||
float cornerSpreadC_;
|
||||
float lastMaxTempC_;
|
||||
uint8_t regulatingFanPwm_;
|
||||
uint8_t fanPwm_;
|
||||
uint8_t fanMixMax_;
|
||||
bool adaptiveEnabled_;
|
||||
bool tuningLoaded_;
|
||||
bool fanIdleOverride_;
|
||||
bool sensorWarmValid_;
|
||||
bool cutoffActive_;
|
||||
|
||||
Reference in New Issue
Block a user