remove fan-controls
This commit is contained in:
@@ -29,16 +29,12 @@ static const float TARGET_MAX_C = 80.0f;
|
||||
static const float EMERGENCY_MAX_TEMP_C = 70.0f;
|
||||
static const float CORNER_STOP_MARGIN_C = 3.0f;
|
||||
|
||||
// Dual PI — heat on avg, mix on spread (no D term)
|
||||
// Heat PI on average temp (no D term)
|
||||
static const float HEAT_PI_KP = 4.0f;
|
||||
static const float HEAT_PI_KI = 0.05f;
|
||||
static const float MIX_PI_KP = 40.0f;
|
||||
static const float MIX_PI_KI = 2.0f;
|
||||
static const float SPREAD_TARGET_C = 0.5f;
|
||||
static const float HEAT_UP_BAND_C = 8.0f;
|
||||
// Mix PI only at/above target; below target use minimum stir only (no mix PI).
|
||||
// Cap mix fan — high airflow often increases spread / heat loss rather than fixing it.
|
||||
static const uint8_t FAN_MIX_MAX_PWM = 140;
|
||||
|
||||
// Fixed circulation fan (~70%, fanchars winner); override with "fan <pwm>" when regulating
|
||||
static const uint8_t FAN_STIR_PWM = 178;
|
||||
|
||||
// Legacy aliases for autotuner relay math only
|
||||
static const float PID_KP = HEAT_PI_KP;
|
||||
@@ -81,7 +77,7 @@ static const uint32_t AUTOTUNE_RELAY_PERIOD_MAX_MS = 2400000UL;
|
||||
static const float FANCHARS_MAX_CORNER_C = 60.0f;
|
||||
static const float FANCHARS_COOL_AVG_C = 40.0f;
|
||||
static const float FANCHARS_PRECOOL_MARGIN_C = 2.0f;
|
||||
static const float FANCHARS_HEATER_PCT = 85.0f;
|
||||
static const float FANCHARS_HEATER_PCT = 100.0f;
|
||||
// Coarse sweep order: 30%, 100%, 60%, 80% fan
|
||||
static const uint8_t FANCHARS_COARSE_PWM[] = {77, 255, 153, 204};
|
||||
static const uint8_t FANCHARS_COARSE_COUNT =
|
||||
|
||||
@@ -271,7 +271,7 @@ private:
|
||||
Serial.print(resultKp_, 3);
|
||||
Serial.print(F(" Ki="));
|
||||
Serial.println(resultKi_, 4);
|
||||
Serial.println(F(" tune mix PI separately: mixpi <Kp> <Ki>"));
|
||||
Serial.println(F(" tune heat PI: pid save after autotune"));
|
||||
}
|
||||
|
||||
void fail(const __FlashStringHelper *reason) {
|
||||
|
||||
@@ -12,7 +12,7 @@ static const int SETTINGS_EEPROM_ADDR = 16;
|
||||
struct SettingsData {
|
||||
uint16_t magic = 0;
|
||||
float targetC = TARGET_TEMP_C;
|
||||
uint8_t stirFanPwm = 0; // 0 = use FAN_IDLE_PWM (~30%)
|
||||
uint8_t stirFanPwm = 0; // 0 = use FAN_STIR_PWM from config
|
||||
};
|
||||
|
||||
inline uint8_t settingsChecksum(const SettingsData &data) {
|
||||
|
||||
@@ -15,7 +15,6 @@ public:
|
||||
|
||||
ThermalController()
|
||||
: 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_(),
|
||||
fanchars_(),
|
||||
targetTempC_(TARGET_TEMP_C),
|
||||
@@ -24,10 +23,12 @@ public:
|
||||
cornerSpreadC_(0.0f),
|
||||
lastMaxTempC_(0.0f),
|
||||
regulatingFanPwm_(0),
|
||||
stirFanPwm_(FAN_IDLE_PWM),
|
||||
stirFanPwm_(FAN_STIR_PWM),
|
||||
fanManualPwm_(0),
|
||||
fanPwm_(0),
|
||||
tuningLoaded_(false),
|
||||
fanIdleOverride_(false),
|
||||
fanManualActive_(false),
|
||||
sensorWarmValid_(false),
|
||||
cutoffActive_(false),
|
||||
failSafeActive_(true),
|
||||
@@ -38,9 +39,7 @@ public:
|
||||
heaterBlock_(HeaterBlock::None),
|
||||
fanTestActive_(false),
|
||||
fanTestPwm_(0),
|
||||
fanTestEndMs_(0) {
|
||||
mixPi_.setSetpoint(0.0f);
|
||||
}
|
||||
fanTestEndMs_(0) {}
|
||||
|
||||
void begin() {
|
||||
pinMode(FAN_PIN, OUTPUT);
|
||||
@@ -50,7 +49,6 @@ public:
|
||||
|
||||
heatPi_.setSetpoint(targetTempC_);
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
heaterCycleStartMs_ = millis();
|
||||
lastHeaterUpdateMs_ = 0;
|
||||
failSafeActive_ = true;
|
||||
@@ -83,44 +81,22 @@ public:
|
||||
|
||||
void applyTuning(const TuningData &data) {
|
||||
heatPi_.setTunings(data.heatKp, data.heatKi, 0.0f);
|
||||
mixPi_.setTunings(data.mixKp, data.mixKi, 0.0f);
|
||||
tuningLoaded_ = true;
|
||||
}
|
||||
|
||||
void clearTuning() {
|
||||
tuningLoaded_ = false;
|
||||
heatPi_.setTunings(HEAT_PI_KP, HEAT_PI_KI, 0.0f);
|
||||
mixPi_.setTunings(MIX_PI_KP, MIX_PI_KI, 0.0f);
|
||||
tuningClear();
|
||||
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("Heat PI Kp="));
|
||||
Serial.print(heatPi_.kp(), 3);
|
||||
Serial.print(F(" Ki="));
|
||||
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"));
|
||||
}
|
||||
@@ -130,8 +106,6 @@ public:
|
||||
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"));
|
||||
@@ -139,8 +113,6 @@ public:
|
||||
|
||||
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_; }
|
||||
|
||||
@@ -150,7 +122,6 @@ public:
|
||||
}
|
||||
cutoffActive_ = false;
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
return autotuner_.start(setpointC);
|
||||
}
|
||||
|
||||
@@ -175,7 +146,6 @@ public:
|
||||
stopFanTest();
|
||||
cutoffActive_ = false;
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
setTarget(0.0f, false);
|
||||
return fanchars_.start(maxCornerC, avgTempC);
|
||||
}
|
||||
@@ -204,6 +174,32 @@ public:
|
||||
|
||||
uint8_t stirFanPwm() const { return stirFanPwm_; }
|
||||
|
||||
bool isFanManualOverride() const { return fanManualActive_ && !isIdle(); }
|
||||
|
||||
bool setRegulatingFanManual(uint8_t pwm) {
|
||||
if (isIdle()) {
|
||||
return false;
|
||||
}
|
||||
fanManualPwm_ = pwm;
|
||||
fanManualActive_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void clearRegulatingFanManual() {
|
||||
fanManualActive_ = false;
|
||||
}
|
||||
|
||||
bool setStirFanPwm(uint8_t pwm, bool persist = true) {
|
||||
if (pwm == 0) {
|
||||
return false;
|
||||
}
|
||||
stirFanPwm_ = pwm;
|
||||
if (persist) {
|
||||
settingsSaveStirFan(pwm);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void logFanCharacterizeIfDue(const float *sensorTemps, const bool *sensorValid, uint8_t sensorCount,
|
||||
float avgTempC, float minTempC, float maxTempC, float spreadC,
|
||||
uint32_t nowMs) {
|
||||
@@ -239,12 +235,10 @@ public:
|
||||
data.magic = TUNING_MAGIC;
|
||||
data.heatKp = autotuner_.resultKp();
|
||||
data.heatKi = autotuner_.resultKi();
|
||||
data.mixKp = mixPi_.kp();
|
||||
data.mixKi = mixPi_.ki();
|
||||
tuningSave(data);
|
||||
tuningLoaded_ = true;
|
||||
autotuner_.reset();
|
||||
Serial.println(F("Saved heat PI to EEPROM (mix PI unchanged)"));
|
||||
Serial.println(F("Saved heat PI to EEPROM"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -252,7 +246,7 @@ public:
|
||||
targetTempC_ = targetC;
|
||||
heatPi_.setSetpoint(targetC);
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
fanManualActive_ = false;
|
||||
cutoffActive_ = false;
|
||||
if (targetC > 0.0f) {
|
||||
fanIdleOverride_ = false;
|
||||
@@ -390,7 +384,6 @@ public:
|
||||
forceHeaterOff();
|
||||
cutoffActive_ = false;
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
lastHeaterUpdateMs_ = nowMs;
|
||||
applyFan(nowMs);
|
||||
return;
|
||||
@@ -408,7 +401,6 @@ public:
|
||||
forceHeaterOff();
|
||||
applyFan(millis());
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
autotuner_.abort();
|
||||
fanchars_.abort();
|
||||
}
|
||||
@@ -485,14 +477,12 @@ private:
|
||||
regulatingFanPwm_ = FAN_MAX_PWM;
|
||||
heaterBlock_ = HeaterBlock::Cutoff;
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cutoffActive_ && maxTempC < EMERGENCY_MAX_TEMP_C - 5.0f) {
|
||||
cutoffActive_ = false;
|
||||
heatPi_.reset();
|
||||
mixPi_.reset();
|
||||
}
|
||||
|
||||
if (cutoffActive_) {
|
||||
@@ -523,17 +513,7 @@ private:
|
||||
}
|
||||
heaterDutyPercent_ = applyHeaterRamp(duty, avgTempC, nowMs);
|
||||
|
||||
uint8_t fanPwm = stirFanPwm_;
|
||||
if (avgTempC < targetTempC_) {
|
||||
mixPi_.reset();
|
||||
} else {
|
||||
const float mixInput = SPREAD_TARGET_C - cornerSpreadC_;
|
||||
float fanOut = mixPi_.compute(mixInput, nowMs);
|
||||
fanPwm = static_cast<uint8_t>(fanOut + 0.5f);
|
||||
if (fanPwm > FAN_MIX_MAX_PWM) {
|
||||
fanPwm = FAN_MIX_MAX_PWM;
|
||||
}
|
||||
}
|
||||
const uint8_t fanPwm = fanManualActive_ ? fanManualPwm_ : stirFanPwm_;
|
||||
regulatingFanPwm_ = fanWithMinStir(avgTempC, fanPwm);
|
||||
}
|
||||
|
||||
@@ -541,9 +521,6 @@ private:
|
||||
if (avgTempC < IDLE_AUTO_FAN_OFF_TEMP_C) {
|
||||
return 0;
|
||||
}
|
||||
if (pwm < stirFanPwm_) {
|
||||
return stirFanPwm_;
|
||||
}
|
||||
return pwm;
|
||||
}
|
||||
|
||||
@@ -665,7 +642,6 @@ private:
|
||||
}
|
||||
|
||||
PidController heatPi_;
|
||||
PidController mixPi_;
|
||||
PidAutotuner autotuner_;
|
||||
FanCharacterize fanchars_;
|
||||
float targetTempC_;
|
||||
@@ -675,9 +651,11 @@ private:
|
||||
float lastMaxTempC_;
|
||||
uint8_t regulatingFanPwm_;
|
||||
uint8_t stirFanPwm_;
|
||||
uint8_t fanManualPwm_;
|
||||
uint8_t fanPwm_;
|
||||
bool tuningLoaded_;
|
||||
bool fanIdleOverride_;
|
||||
bool fanManualActive_;
|
||||
bool sensorWarmValid_;
|
||||
bool cutoffActive_;
|
||||
bool failSafeActive_;
|
||||
|
||||
@@ -5,15 +5,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
static const uint16_t TUNING_MAGIC = 0xDA7B;
|
||||
static const uint16_t TUNING_MAGIC = 0xDA7C;
|
||||
static const int TUNING_EEPROM_ADDR = 0;
|
||||
|
||||
struct TuningData {
|
||||
uint16_t magic = 0;
|
||||
float heatKp = HEAT_PI_KP;
|
||||
float heatKi = HEAT_PI_KI;
|
||||
float mixKp = MIX_PI_KP;
|
||||
float mixKi = MIX_PI_KI;
|
||||
};
|
||||
|
||||
inline uint8_t tuningChecksum(const TuningData &data) {
|
||||
|
||||
Reference in New Issue
Block a user