Include the model checker with hard-coded constants

This commit is contained in:
Yuri D'Elia 2022-05-26 19:22:17 +02:00
parent 61575995e0
commit 3eda8b61ee
2 changed files with 101 additions and 3 deletions

View File

@ -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

View File

@ -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
*------------------------------------*/