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,
|
max,
|
||||||
preheat,
|
preheat,
|
||||||
runaway,
|
runaway,
|
||||||
|
model,
|
||||||
};
|
};
|
||||||
|
|
||||||
// error state (updated via set_temp_error from isr context)
|
// error state (updated via set_temp_error from isr context)
|
||||||
|
|
@ -1735,6 +1736,26 @@ void handle_temp_error()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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
|
#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()
|
static void temp_mgr_isr()
|
||||||
{
|
{
|
||||||
|
|
@ -2152,6 +2176,9 @@ static void temp_mgr_isr()
|
||||||
temp_error_state.assert = false;
|
temp_error_state.assert = false;
|
||||||
check_temp_raw(); // check min/max temp using raw values
|
check_temp_raw(); // check min/max temp using raw values
|
||||||
check_temp_runaway(); // classic temperature hysteresis check
|
check_temp_runaway(); // classic temperature hysteresis check
|
||||||
|
#ifdef TEMP_MODEL_CHECK
|
||||||
|
check_temp_model(); // model-based heater check
|
||||||
|
#endif
|
||||||
|
|
||||||
// PID regulation
|
// PID regulation
|
||||||
temp_mgr_pid();
|
temp_mgr_pid();
|
||||||
|
|
@ -2203,7 +2230,7 @@ void disable_heater()
|
||||||
CRITICAL_SECTION_END;
|
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 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)
|
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
|
#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
|
// order is relevant: check_min_temp_raw requires max to be reliable due to
|
||||||
// ambient temperature being used for low handling temperatures
|
// ambient temperature being used for low handling temperatures
|
||||||
check_max_temp_raw();
|
check_max_temp_raw();
|
||||||
check_min_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_HYSTERESIS 15
|
||||||
#define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45
|
#define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45
|
||||||
|
|
||||||
|
// model-based temperature check
|
||||||
|
#define TEMP_MODEL_CHECK 1
|
||||||
|
|
||||||
/*------------------------------------
|
/*------------------------------------
|
||||||
MOTOR CURRENT SETTINGS
|
MOTOR CURRENT SETTINGS
|
||||||
*------------------------------------*/
|
*------------------------------------*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue