Handle failures during calibration
Break out of the autotuning if a thermal error condition is detected and attempt to restore a safe initial state irregardless of the error handlers. Also error out if the estimation fails to converge.
This commit is contained in:
parent
cc96a47e7f
commit
47d2e9e61c
1 changed files with 60 additions and 20 deletions
|
@ -2632,23 +2632,33 @@ void waiting_handler()
|
||||||
void wait(unsigned ms)
|
void wait(unsigned ms)
|
||||||
{
|
{
|
||||||
unsigned long mark = _millis() + ms;
|
unsigned long mark = _millis() + ms;
|
||||||
while(_millis() < mark)
|
while(_millis() < mark) {
|
||||||
|
if(temp_error_state.v) break;
|
||||||
waiting_handler();
|
waiting_handler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait_temp()
|
void wait_temp()
|
||||||
{
|
{
|
||||||
while(current_temperature[0] < (target_temperature[0] - TEMP_HYSTERESIS))
|
while(current_temperature[0] < (target_temperature[0] - TEMP_HYSTERESIS)) {
|
||||||
|
if(temp_error_state.v) break;
|
||||||
waiting_handler();
|
waiting_handler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cooldown(float temp)
|
void cooldown(float temp)
|
||||||
{
|
{
|
||||||
float old_speed = fanSpeedSoftPwm;
|
float old_speed = fanSpeedSoftPwm;
|
||||||
fanSpeedSoftPwm = 255;
|
fanSpeedSoftPwm = 255;
|
||||||
while((current_temperature[0] >= temp) &&
|
while(current_temperature[0] >= temp) {
|
||||||
(current_temperature[0] >= (current_temperature_ambient + temp_model::data.Ta_corr + TEMP_HYSTERESIS)))
|
if(temp_error_state.v) break;
|
||||||
|
float ambient = current_temperature_ambient + temp_model::data.Ta_corr;
|
||||||
|
if(current_temperature[0] < (ambient + TEMP_HYSTERESIS)) {
|
||||||
|
// do not get stuck waiting very close to ambient temperature
|
||||||
|
break;
|
||||||
|
}
|
||||||
waiting_handler();
|
waiting_handler();
|
||||||
|
}
|
||||||
fanSpeedSoftPwm = old_speed;
|
fanSpeedSoftPwm = old_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2670,6 +2680,10 @@ uint16_t record(uint16_t samples = REC_BUFFER_SIZE) {
|
||||||
adc_start_cycle();
|
adc_start_cycle();
|
||||||
temp_mgr_isr();
|
temp_mgr_isr();
|
||||||
|
|
||||||
|
// stop recording for an hard error condition
|
||||||
|
if(temp_error_state.v)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// record a new entry
|
// record a new entry
|
||||||
rec_entry& entry = rec_buffer[pos];
|
rec_entry& entry = rec_buffer[pos];
|
||||||
entry.temp = current_temperature_isr[0];
|
entry.temp = current_temperature_isr[0];
|
||||||
|
@ -2723,17 +2737,13 @@ float estimate(uint16_t samples, float* const var, float min, float max, float t
|
||||||
}
|
}
|
||||||
|
|
||||||
SERIAL_ECHOLNPGM("TM estimation did not converge");
|
SERIAL_ECHOLNPGM("TM estimation did not converge");
|
||||||
return e;
|
return NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void autotune(int16_t cal_temp)
|
bool autotune(int16_t cal_temp)
|
||||||
{
|
{
|
||||||
SERIAL_ECHOLNPGM("TM: autotune start");
|
|
||||||
uint16_t samples;
|
uint16_t samples;
|
||||||
|
float e;
|
||||||
// disable the model checking during self-calibration
|
|
||||||
bool was_enabled = temp_model::enabled;
|
|
||||||
temp_model_set_enabled(false);
|
|
||||||
|
|
||||||
// bootstrap C/R values without fan
|
// bootstrap C/R values without fan
|
||||||
fanSpeedSoftPwm = 0;
|
fanSpeedSoftPwm = 0;
|
||||||
|
@ -2755,9 +2765,14 @@ void autotune(int16_t cal_temp)
|
||||||
printf_P(PSTR("TM: %S C estimation\n"), verb);
|
printf_P(PSTR("TM: %S C estimation\n"), verb);
|
||||||
target_temperature[0] = cal_temp;
|
target_temperature[0] = cal_temp;
|
||||||
samples = record();
|
samples = record();
|
||||||
estimate(samples, &temp_model::data.C,
|
if(temp_error_state.v || !samples)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
e = estimate(samples, &temp_model::data.C,
|
||||||
TEMP_MODEL_Cl, TEMP_MODEL_Ch, TEMP_MODEL_C_thr, TEMP_MODEL_C_itr,
|
TEMP_MODEL_Cl, TEMP_MODEL_Ch, TEMP_MODEL_C_thr, TEMP_MODEL_C_itr,
|
||||||
current_temperature_ambient);
|
current_temperature_ambient);
|
||||||
|
if(isnan(e))
|
||||||
|
return true;
|
||||||
|
|
||||||
wait_temp();
|
wait_temp();
|
||||||
if(i) break; // we don't need to refine R
|
if(i) break; // we don't need to refine R
|
||||||
|
@ -2765,9 +2780,14 @@ void autotune(int16_t cal_temp)
|
||||||
|
|
||||||
printf_P(PSTR("TM: %S R estimation @ %dC\n"), verb, cal_temp);
|
printf_P(PSTR("TM: %S R estimation @ %dC\n"), verb, cal_temp);
|
||||||
samples = record();
|
samples = record();
|
||||||
estimate(samples, &temp_model::data.R[0],
|
if(temp_error_state.v || !samples)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
e = estimate(samples, &temp_model::data.R[0],
|
||||||
TEMP_MODEL_Rl, TEMP_MODEL_Rh, TEMP_MODEL_R_thr, TEMP_MODEL_R_itr,
|
TEMP_MODEL_Rl, TEMP_MODEL_Rh, TEMP_MODEL_R_thr, TEMP_MODEL_R_itr,
|
||||||
current_temperature_ambient);
|
current_temperature_ambient);
|
||||||
|
if(isnan(e))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estimate fan losses at regular intervals, starting from full speed to avoid low-speed
|
// Estimate fan losses at regular intervals, starting from full speed to avoid low-speed
|
||||||
|
@ -2783,9 +2803,14 @@ void autotune(int16_t cal_temp)
|
||||||
|
|
||||||
printf_P(PSTR("TM: R[%u] estimation\n"), (unsigned)soft_pwm_fan);
|
printf_P(PSTR("TM: R[%u] estimation\n"), (unsigned)soft_pwm_fan);
|
||||||
samples = record();
|
samples = record();
|
||||||
estimate(samples, &temp_model::data.R[soft_pwm_fan],
|
if(temp_error_state.v || !samples)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
e = estimate(samples, &temp_model::data.R[soft_pwm_fan],
|
||||||
TEMP_MODEL_Rl, temp_model::data.R[0], TEMP_MODEL_R_thr, TEMP_MODEL_R_itr,
|
TEMP_MODEL_Rl, temp_model::data.R[0], TEMP_MODEL_R_thr, TEMP_MODEL_R_itr,
|
||||||
current_temperature_ambient);
|
current_temperature_ambient);
|
||||||
|
if(isnan(e))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// interpolate remaining steps to speed-up calibration
|
// interpolate remaining steps to speed-up calibration
|
||||||
|
@ -2802,10 +2827,7 @@ void autotune(int16_t cal_temp)
|
||||||
temp_model::data.R[i] = temp_model::data.R[prev] + d * f;
|
temp_model::data.R[i] = temp_model::data.R[prev] + d * f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore the initial state
|
return false;
|
||||||
fanSpeedSoftPwm = 0;
|
|
||||||
target_temperature[0] = 0;
|
|
||||||
temp_model_set_enabled(was_enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace temp_model_cal
|
} // namespace temp_model_cal
|
||||||
|
@ -2814,8 +2836,26 @@ void temp_model_autotune(int16_t temp)
|
||||||
{
|
{
|
||||||
// TODO: ensure printer is idle/queue empty/buffer empty
|
// TODO: ensure printer is idle/queue empty/buffer empty
|
||||||
KEEPALIVE_STATE(IN_PROCESS);
|
KEEPALIVE_STATE(IN_PROCESS);
|
||||||
temp_model_cal::autotune(temp > 0 ? temp : TEMP_MODEL_CAL_Th);
|
|
||||||
temp_model_report_settings();
|
// disable the model checking during self-calibration
|
||||||
|
bool was_enabled = temp_model::enabled;
|
||||||
|
temp_model_set_enabled(false);
|
||||||
|
|
||||||
|
SERIAL_ECHOLNPGM("TM: autotune start");
|
||||||
|
bool err = temp_model_cal::autotune(temp > 0 ? temp : TEMP_MODEL_CAL_Th);
|
||||||
|
|
||||||
|
// always reset temperature
|
||||||
|
target_temperature[0] = 0;
|
||||||
|
|
||||||
|
if(err) {
|
||||||
|
SERIAL_ECHOLNPGM("TM: autotune failed");
|
||||||
|
if(temp_error_state.v)
|
||||||
|
fanSpeedSoftPwm = 255;
|
||||||
|
} else {
|
||||||
|
fanSpeedSoftPwm = 0;
|
||||||
|
temp_model_set_enabled(was_enabled);
|
||||||
|
temp_model_report_settings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEMP_MODEL_DEBUG
|
#ifdef TEMP_MODEL_DEBUG
|
||||||
|
|
Loading…
Reference in a new issue