Include the model checker with hard-coded constants
This commit is contained in:
parent
61575995e0
commit
3eda8b61ee
@ -444,6 +444,7 @@ enum class TempErrorType : uint8_t
|
||||
max,
|
||||
preheat,
|
||||
runaway,
|
||||
model,
|
||||
};
|
||||
|
||||
// error state (updated via set_temp_error from isr context)
|
||||
@ -1735,6 +1736,26 @@ void handle_temp_error()
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TempErrorType::model:
|
||||
#ifdef TEMP_MODEL_CHECK
|
||||
static bool is_new = true;
|
||||
static bool beep_on = false;
|
||||
printf_P(PSTR("TM: err:%u ass:%u\n"), (unsigned)temp_error_state.error,
|
||||
(unsigned)temp_error_state.assert);
|
||||
if(is_new) {
|
||||
beep_on = true;
|
||||
is_new = false;
|
||||
}
|
||||
WRITE(BEEPER, beep_on);
|
||||
beep_on = !beep_on;
|
||||
if(!temp_error_state.assert) {
|
||||
printf_P(PSTR("TM: assertion cleared - resetting\n"));
|
||||
temp_error_state.v = 0;
|
||||
WRITE(BEEPER, LOW);
|
||||
is_new = true;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2141,7 +2162,10 @@ static void check_temp_runaway()
|
||||
#endif
|
||||
}
|
||||
|
||||
void check_temp_raw();
|
||||
static void check_temp_raw();
|
||||
#ifdef TEMP_MODEL_CHECK
|
||||
static void check_temp_model();
|
||||
#endif
|
||||
|
||||
static void temp_mgr_isr()
|
||||
{
|
||||
@ -2152,6 +2176,9 @@ static void temp_mgr_isr()
|
||||
temp_error_state.assert = false;
|
||||
check_temp_raw(); // check min/max temp using raw values
|
||||
check_temp_runaway(); // classic temperature hysteresis check
|
||||
#ifdef TEMP_MODEL_CHECK
|
||||
check_temp_model(); // model-based heater check
|
||||
#endif
|
||||
|
||||
// PID regulation
|
||||
temp_mgr_pid();
|
||||
@ -2203,7 +2230,7 @@ void disable_heater()
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
void check_min_temp_raw()
|
||||
static void check_min_temp_raw()
|
||||
{
|
||||
static bool bCheckingOnHeater = false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over heaterMintemp)
|
||||
static bool bCheckingOnBed = false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over bedMintemp)
|
||||
@ -2263,10 +2290,78 @@ void check_min_temp_raw()
|
||||
#endif //AMBIENT_THERMISTOR
|
||||
}
|
||||
|
||||
void check_temp_raw()
|
||||
static void check_temp_raw()
|
||||
{
|
||||
// order is relevant: check_min_temp_raw requires max to be reliable due to
|
||||
// ambient temperature being used for low handling temperatures
|
||||
check_max_temp_raw();
|
||||
check_min_temp_raw();
|
||||
}
|
||||
|
||||
#ifdef TEMP_MODEL_CHECK
|
||||
static const float TM_P = 38.; // heater power (W)
|
||||
static const float TM_C = 11.9; // heatblock capacitance (J/K)
|
||||
static const float TM_R = 27.; // heatblock resistance
|
||||
static const float TM_Rf = -20.; // full-power fan resistance change
|
||||
static const float TM_aC = -5; // ambient temperature correction (K)
|
||||
|
||||
static const float TM_dTl = 2.1; // temperature transport delay
|
||||
static const uint8_t TM_dTs = (TM_dTl / TEMP_MGR_INTV + 0.5); // temperature transport delay (samples)
|
||||
|
||||
static const float TM_fS = 0.065; // simulation (1st-order IIR factor)
|
||||
static const float TM_fE = 0.05; // error (1st-order IIR factor)
|
||||
|
||||
static const float TM_dErr_p = 0.25; // error threshold (K, positive, actively heating)
|
||||
static const float TM_dErr_n = 0.25; // error threshold (K, negative, cooling)
|
||||
|
||||
static float TM_dT_buf[TM_dTs]; // transport delay buffer
|
||||
static uint8_t TM_dT_idx = 0; // transport delay buffer index
|
||||
static float TM_dErr = 0; // last error
|
||||
static float TM_T = 0; // last temperature
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(A, B) (A >= B? A: B)
|
||||
#endif
|
||||
// samples required for settling the model (crude approximation)
|
||||
static uint8_t TM_dT_smp = MAX(TM_dTs, MAX(3/TM_fS, 3/TM_fE));
|
||||
|
||||
static void check_temp_model()
|
||||
{
|
||||
// input values
|
||||
float heater_scale = (float)soft_pwm[0] / ((1 << 7) - 1);
|
||||
float fan_scale = (float)soft_pwm_fan / ((1 << FAN_SOFT_PWM_BITS) - 1);
|
||||
float cur_temp_heater = current_temperature_isr[0];
|
||||
float cur_temp_ambient = current_temperature_ambient_isr + TM_aC;
|
||||
|
||||
// model invariants
|
||||
float C_i = (TEMP_MGR_INTV / TM_C);
|
||||
|
||||
float dP = TM_P * heater_scale; // current power [W]
|
||||
float R = TM_R + TM_Rf * fan_scale; // resistance (constant + fan modulation)
|
||||
float dPl = (cur_temp_heater - cur_temp_ambient) / R; // [W] leakage power
|
||||
float dT = (dP - dPl) * C_i; // expected temperature difference (K)
|
||||
|
||||
// filter and lag dT
|
||||
uint8_t next_dT_idx = (TM_dT_idx == (TM_dTs - 1) ? 0: TM_dT_idx + 1);
|
||||
float lag_dT = TM_dT_buf[next_dT_idx];
|
||||
float prev_dT = TM_dT_buf[TM_dT_idx];
|
||||
float dTf = (prev_dT * (1. - TM_fS)) + (dT * TM_fS);
|
||||
TM_dT_buf[next_dT_idx] = dTf;
|
||||
TM_dT_idx = next_dT_idx;
|
||||
|
||||
// calculate and filter dErr
|
||||
float dErr = (cur_temp_heater - TM_T) - lag_dT;
|
||||
float dErrf = (TM_dErr * (1. - TM_fE)) + (dErr * TM_fE);
|
||||
TM_T = cur_temp_heater;
|
||||
TM_dErr = dErrf;
|
||||
|
||||
// check and trigger errors
|
||||
if(TM_dT_smp) {
|
||||
// model not ready
|
||||
--TM_dT_smp;
|
||||
} else {
|
||||
if(dErrf > TM_dErr_p || dErrf < -TM_dErr_n)
|
||||
set_temp_error(TempErrorSource::hotend, 0, TempErrorType::model);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -417,6 +417,9 @@
|
||||
#define TEMP_RUNAWAY_EXTRUDER_HYSTERESIS 15
|
||||
#define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45
|
||||
|
||||
// model-based temperature check
|
||||
#define TEMP_MODEL_CHECK 1
|
||||
|
||||
/*------------------------------------
|
||||
MOTOR CURRENT SETTINGS
|
||||
*------------------------------------*/
|
||||
|
Loading…
Reference in New Issue
Block a user