|
|
@ -94,12 +94,12 @@ Temperature thermalManager; |
|
|
|
*/ |
|
|
|
|
|
|
|
#if HAS_HEATED_BED |
|
|
|
#define _BED_PSTR(M,E) (E) == -1 ? PSTR(M) : |
|
|
|
#define _BED_PSTR(M,E) (E) == H_BED ? PSTR(M) : |
|
|
|
#else |
|
|
|
#define _BED_PSTR(M,E) |
|
|
|
#endif |
|
|
|
#if HAS_HEATED_CHAMBER |
|
|
|
#define _CHAMBER_PSTR(M,E) (E) == -2 ? PSTR(M) : |
|
|
|
#define _CHAMBER_PSTR(M,E) (E) == H_CHAMBER ? PSTR(M) : |
|
|
|
#else |
|
|
|
#define _CHAMBER_PSTR(M,E) |
|
|
|
#endif |
|
|
@ -345,7 +345,7 @@ temp_range_t Temperature::temp_range[HOTENDS] = ARRAY_BY_HOTENDS(sensor_heater_0 |
|
|
|
* Needs sufficient heater power to make some overshoot at target |
|
|
|
* temperature to succeed. |
|
|
|
*/ |
|
|
|
void Temperature::PID_autotune(const float &target, const int8_t heater, const int8_t ncycles, const bool set_result/*=false*/) { |
|
|
|
void Temperature::PID_autotune(const float &target, const heater_ind_t heater, const int8_t ncycles, const bool set_result/*=false*/) { |
|
|
|
float current = 0.0; |
|
|
|
int cycles = 0; |
|
|
|
bool heating = true; |
|
|
@ -357,7 +357,7 @@ temp_range_t Temperature::temp_range[HOTENDS] = ARRAY_BY_HOTENDS(sensor_heater_0 |
|
|
|
PID_t tune_pid = { 0, 0, 0 }; |
|
|
|
float max = 0, min = 10000; |
|
|
|
|
|
|
|
const bool isbed = (heater < 0); |
|
|
|
const bool isbed = (heater == H_BED); |
|
|
|
|
|
|
|
#if HAS_PID_FOR_BOTH |
|
|
|
#define GHV(B,H) (isbed ? (B) : (H)) |
|
|
@ -618,26 +618,16 @@ temp_range_t Temperature::temp_range[HOTENDS] = ARRAY_BY_HOTENDS(sensor_heater_0 |
|
|
|
|
|
|
|
Temperature::Temperature() { } |
|
|
|
|
|
|
|
int16_t Temperature::getHeaterPower(const int8_t heater) { |
|
|
|
return ( |
|
|
|
#if HAS_HEATED_CHAMBER |
|
|
|
#if HAS_HEATED_BED |
|
|
|
heater == -2 |
|
|
|
#else |
|
|
|
heater < 0 |
|
|
|
#endif |
|
|
|
? temp_chamber.soft_pwm_amount : |
|
|
|
#endif |
|
|
|
int16_t Temperature::getHeaterPower(const heater_ind_t heater_id) { |
|
|
|
switch (heater_id) { |
|
|
|
default: return temp_hotend[heater_id].soft_pwm_amount; |
|
|
|
#if HAS_HEATED_BED |
|
|
|
#if HAS_HEATED_CHAMBER |
|
|
|
heater == -1 |
|
|
|
#else |
|
|
|
heater < 0 |
|
|
|
#endif |
|
|
|
? temp_bed.soft_pwm_amount : |
|
|
|
case H_BED: return temp_bed.soft_pwm_amount; |
|
|
|
#endif |
|
|
|
#if HAS_HEATED_CHAMBER |
|
|
|
case H_CHAMBER: return temp_chamber.soft_pwm_amount; |
|
|
|
#endif |
|
|
|
temp_hotend[heater].soft_pwm_amount |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#if HAS_AUTO_FAN |
|
|
@ -756,7 +746,7 @@ int16_t Temperature::getHeaterPower(const int8_t heater) { |
|
|
|
//
|
|
|
|
// Temperature Error Handlers
|
|
|
|
//
|
|
|
|
void Temperature::_temp_error(const int8_t heater, PGM_P const serial_msg, PGM_P const lcd_msg) { |
|
|
|
void Temperature::_temp_error(const heater_ind_t heater, PGM_P const serial_msg, PGM_P const lcd_msg) { |
|
|
|
static bool killed = false; |
|
|
|
if (IsRunning()) { |
|
|
|
SERIAL_ERROR_START(); |
|
|
@ -764,7 +754,7 @@ void Temperature::_temp_error(const int8_t heater, PGM_P const serial_msg, PGM_P |
|
|
|
SERIAL_ECHOPGM(MSG_STOPPED_HEATER); |
|
|
|
if (heater >= 0) SERIAL_ECHO((int)heater); |
|
|
|
#if HAS_HEATED_CHAMBER |
|
|
|
else if (heater == -2) SERIAL_ECHOPGM(MSG_HEATER_CHAMBER); |
|
|
|
else if (heater == H_CHAMBER) SERIAL_ECHOPGM(MSG_HEATER_CHAMBER); |
|
|
|
#endif |
|
|
|
else SERIAL_ECHOPGM(MSG_HEATER_BED); |
|
|
|
SERIAL_EOL(); |
|
|
@ -794,21 +784,22 @@ void Temperature::_temp_error(const int8_t heater, PGM_P const serial_msg, PGM_P |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void Temperature::max_temp_error(const int8_t heater) { |
|
|
|
void Temperature::max_temp_error(const heater_ind_t heater) { |
|
|
|
_temp_error(heater, PSTR(MSG_T_MAXTEMP), TEMP_ERR_PSTR(MSG_ERR_MAXTEMP, heater)); |
|
|
|
} |
|
|
|
|
|
|
|
void Temperature::min_temp_error(const int8_t heater) { |
|
|
|
void Temperature::min_temp_error(const heater_ind_t heater) { |
|
|
|
_temp_error(heater, PSTR(MSG_T_MINTEMP), TEMP_ERR_PSTR(MSG_ERR_MINTEMP, heater)); |
|
|
|
} |
|
|
|
|
|
|
|
float Temperature::get_pid_output(const int8_t e) { |
|
|
|
float Temperature::get_pid_output_hotend(const uint8_t e) { |
|
|
|
#if HOTENDS == 1 |
|
|
|
#define _HOTEND_TEST true |
|
|
|
#else |
|
|
|
#define _HOTEND_TEST (e == active_extruder) |
|
|
|
#endif |
|
|
|
E_UNUSED(); |
|
|
|
const uint8_t ee = HOTEND_INDEX; |
|
|
|
float pid_output; |
|
|
|
#if ENABLED(PIDTEMP) |
|
|
|
#if DISABLED(PID_OPENLOOP) |
|
|
@ -816,38 +807,38 @@ float Temperature::get_pid_output(const int8_t e) { |
|
|
|
static float temp_iState[HOTENDS] = { 0 }, |
|
|
|
temp_dState[HOTENDS] = { 0 }; |
|
|
|
static bool pid_reset[HOTENDS] = { false }; |
|
|
|
const float pid_error = temp_hotend[HOTEND_INDEX].target - temp_hotend[HOTEND_INDEX].current; |
|
|
|
const float pid_error = temp_hotend[ee].target - temp_hotend[ee].current; |
|
|
|
|
|
|
|
if (temp_hotend[HOTEND_INDEX].target == 0 |
|
|
|
if (temp_hotend[ee].target == 0 |
|
|
|
|| pid_error < -(PID_FUNCTIONAL_RANGE) |
|
|
|
#if HEATER_IDLE_HANDLER |
|
|
|
|| hotend_idle[HOTEND_INDEX].timed_out |
|
|
|
|| hotend_idle[ee].timed_out |
|
|
|
#endif |
|
|
|
) { |
|
|
|
pid_output = 0; |
|
|
|
pid_reset[HOTEND_INDEX] = true; |
|
|
|
pid_reset[ee] = true; |
|
|
|
} |
|
|
|
else if (pid_error > PID_FUNCTIONAL_RANGE) { |
|
|
|
pid_output = BANG_MAX; |
|
|
|
pid_reset[HOTEND_INDEX] = true; |
|
|
|
pid_reset[ee] = true; |
|
|
|
} |
|
|
|
else { |
|
|
|
if (pid_reset[HOTEND_INDEX]) { |
|
|
|
temp_iState[HOTEND_INDEX] = 0.0; |
|
|
|
work_pid[HOTEND_INDEX].Kd = 0.0; |
|
|
|
pid_reset[HOTEND_INDEX] = false; |
|
|
|
if (pid_reset[ee]) { |
|
|
|
temp_iState[ee] = 0.0; |
|
|
|
work_pid[ee].Kd = 0.0; |
|
|
|
pid_reset[ee] = false; |
|
|
|
} |
|
|
|
|
|
|
|
work_pid[HOTEND_INDEX].Kd = work_pid[HOTEND_INDEX].Kd + PID_K2 * (PID_PARAM(Kd, HOTEND_INDEX) * (temp_dState[HOTEND_INDEX] - temp_hotend[HOTEND_INDEX].current) - work_pid[HOTEND_INDEX].Kd); |
|
|
|
const float max_power_over_i_gain = (float)PID_MAX / PID_PARAM(Ki, HOTEND_INDEX); |
|
|
|
temp_iState[HOTEND_INDEX] = constrain(temp_iState[HOTEND_INDEX] + pid_error, 0, max_power_over_i_gain); |
|
|
|
work_pid[HOTEND_INDEX].Kp = PID_PARAM(Kp, HOTEND_INDEX) * pid_error; |
|
|
|
work_pid[HOTEND_INDEX].Ki = PID_PARAM(Ki, HOTEND_INDEX) * temp_iState[HOTEND_INDEX]; |
|
|
|
work_pid[ee].Kd = work_pid[ee].Kd + PID_K2 * (PID_PARAM(Kd, ee) * (temp_dState[ee] - temp_hotend[ee].current) - work_pid[ee].Kd); |
|
|
|
const float max_power_over_i_gain = (float)PID_MAX / PID_PARAM(Ki, ee); |
|
|
|
temp_iState[ee] = constrain(temp_iState[ee] + pid_error, 0, max_power_over_i_gain); |
|
|
|
work_pid[ee].Kp = PID_PARAM(Kp, ee) * pid_error; |
|
|
|
work_pid[ee].Ki = PID_PARAM(Ki, ee) * temp_iState[ee]; |
|
|
|
|
|
|
|
pid_output = work_pid[HOTEND_INDEX].Kp + work_pid[HOTEND_INDEX].Ki + work_pid[HOTEND_INDEX].Kd; |
|
|
|
pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd; |
|
|
|
|
|
|
|
#if ENABLED(PID_EXTRUSION_SCALING) |
|
|
|
work_pid[HOTEND_INDEX].Kc = 0; |
|
|
|
work_pid[ee].Kc = 0; |
|
|
|
if (_HOTEND_TEST) { |
|
|
|
const long e_position = stepper.position(E_AXIS); |
|
|
|
if (e_position > last_e_position) { |
|
|
@ -858,49 +849,51 @@ float Temperature::get_pid_output(const int8_t e) { |
|
|
|
lpq[lpq_ptr] = 0; |
|
|
|
|
|
|
|
if (++lpq_ptr >= lpq_len) lpq_ptr = 0; |
|
|
|
work_pid[HOTEND_INDEX].Kc = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, HOTEND_INDEX); |
|
|
|
pid_output += work_pid[HOTEND_INDEX].Kc; |
|
|
|
work_pid[ee].Kc = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, ee); |
|
|
|
pid_output += work_pid[ee].Kc; |
|
|
|
} |
|
|
|
#endif // PID_EXTRUSION_SCALING
|
|
|
|
|
|
|
|
pid_output = constrain(pid_output, 0, PID_MAX); |
|
|
|
} |
|
|
|
temp_dState[HOTEND_INDEX] = temp_hotend[HOTEND_INDEX].current; |
|
|
|
temp_dState[ee] = temp_hotend[ee].current; |
|
|
|
|
|
|
|
#else // PID_OPENLOOP
|
|
|
|
|
|
|
|
const float pid_output = constrain(temp_hotend[HOTEND_INDEX].target, 0, PID_MAX); |
|
|
|
const float pid_output = constrain(temp_hotend[ee].target, 0, PID_MAX); |
|
|
|
|
|
|
|
#endif // PID_OPENLOOP
|
|
|
|
|
|
|
|
#if ENABLED(PID_DEBUG) |
|
|
|
SERIAL_ECHO_START(); |
|
|
|
SERIAL_ECHOPAIR( |
|
|
|
MSG_PID_DEBUG, HOTEND_INDEX, |
|
|
|
MSG_PID_DEBUG_INPUT, temp_hotend[HOTEND_INDEX].current, |
|
|
|
MSG_PID_DEBUG, ee, |
|
|
|
MSG_PID_DEBUG_INPUT, temp_hotend[ee].current, |
|
|
|
MSG_PID_DEBUG_OUTPUT, pid_output |
|
|
|
); |
|
|
|
#if DISABLED(PID_OPENLOOP) |
|
|
|
SERIAL_ECHOPAIR( |
|
|
|
MSG_PID_DEBUG_PTERM, work_pid[HOTEND_INDEX].Kp, |
|
|
|
MSG_PID_DEBUG_ITERM, work_pid[HOTEND_INDEX].Ki, |
|
|
|
MSG_PID_DEBUG_DTERM, work_pid[HOTEND_INDEX].Kd |
|
|
|
MSG_PID_DEBUG_PTERM, work_pid[ee].Kp, |
|
|
|
MSG_PID_DEBUG_ITERM, work_pid[ee].Ki, |
|
|
|
MSG_PID_DEBUG_DTERM, work_pid[ee].Kd |
|
|
|
#if ENABLED(PID_EXTRUSION_SCALING) |
|
|
|
, MSG_PID_DEBUG_CTERM, work_pid[HOTEND_INDEX].Kc |
|
|
|
, MSG_PID_DEBUG_CTERM, work_pid[ee].Kc |
|
|
|
#endif |
|
|
|
); |
|
|
|
#endif |
|
|
|
SERIAL_EOL(); |
|
|
|
#endif // PID_DEBUG
|
|
|
|
|
|
|
|
#else /* PID off */ |
|
|
|
#else // No PID enabled
|
|
|
|
|
|
|
|
#if HEATER_IDLE_HANDLER |
|
|
|
#define _TIMED_OUT_TEST hotend_idle[HOTEND_INDEX].timed_out |
|
|
|
#define _TIMED_OUT_TEST hotend_idle[ee].timed_out |
|
|
|
#else |
|
|
|
#define _TIMED_OUT_TEST false |
|
|
|
#endif |
|
|
|
pid_output = (!_TIMED_OUT_TEST && temp_hotend[HOTEND_INDEX].current < temp_hotend[HOTEND_INDEX].target) ? BANG_MAX : 0; |
|
|
|
pid_output = (!_TIMED_OUT_TEST && temp_hotend[ee].current < temp_hotend[ee].target) ? BANG_MAX : 0; |
|
|
|
#undef _TIMED_OUT_TEST |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return pid_output; |
|
|
@ -983,13 +976,13 @@ void Temperature::manage_heater() { |
|
|
|
updateTemperaturesFromRawValues(); // also resets the watchdog
|
|
|
|
|
|
|
|
#if ENABLED(HEATER_0_USES_MAX6675) |
|
|
|
if (temp_hotend[0].current > MIN(HEATER_0_MAXTEMP, HEATER_0_MAX6675_TMAX - 1.0)) max_temp_error(0); |
|
|
|
if (temp_hotend[0].current < MAX(HEATER_0_MINTEMP, HEATER_0_MAX6675_TMIN + .01)) min_temp_error(0); |
|
|
|
if (temp_hotend[0].current > MIN(HEATER_0_MAXTEMP, HEATER_0_MAX6675_TMAX - 1.0)) max_temp_error(H_E0); |
|
|
|
if (temp_hotend[0].current < MAX(HEATER_0_MINTEMP, HEATER_0_MAX6675_TMIN + .01)) min_temp_error(H_E0); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if ENABLED(HEATER_1_USES_MAX6675) |
|
|
|
if (temp_hotend[1].current > MIN(HEATER_1_MAXTEMP, HEATER_1_MAX6675_TMAX - 1.0)) max_temp_error(1); |
|
|
|
if (temp_hotend[1].current < MAX(HEATER_1_MINTEMP, HEATER_1_MAX6675_TMIN + .01)) min_temp_error(1); |
|
|
|
if (temp_hotend[1].current > MIN(HEATER_1_MAXTEMP, HEATER_1_MAX6675_TMAX - 1.0)) max_temp_error(H_E1); |
|
|
|
if (temp_hotend[1].current < MAX(HEATER_1_MINTEMP, HEATER_1_MAX6675_TMIN + .01)) min_temp_error(H_E1); |
|
|
|
#endif |
|
|
|
|
|
|
|
#define HAS_THERMAL_PROTECTION (ENABLED(THERMAL_PROTECTION_HOTENDS) || HAS_THERMALLY_PROTECTED_BED || ENABLED(THERMAL_PROTECTION_CHAMBER)) |
|
|
@ -1010,7 +1003,7 @@ void Temperature::manage_heater() { |
|
|
|
HOTEND_LOOP() { |
|
|
|
#if ENABLED(THERMAL_PROTECTION_HOTENDS) |
|
|
|
if (!grace_period && degHotend(e) > temp_range[e].maxtemp) |
|
|
|
_temp_error(e, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, e)); |
|
|
|
_temp_error((heater_ind_t)e, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, e)); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if HEATER_IDLE_HANDLER |
|
|
@ -1019,25 +1012,25 @@ void Temperature::manage_heater() { |
|
|
|
|
|
|
|
#if ENABLED(THERMAL_PROTECTION_HOTENDS) |
|
|
|
// Check for thermal runaway
|
|
|
|
thermal_runaway_protection(tr_state_machine[e], temp_hotend[e].current, temp_hotend[e].target, e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS); |
|
|
|
thermal_runaway_protection(tr_state_machine[e], temp_hotend[e].current, temp_hotend[e].target, (heater_ind_t)e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS); |
|
|
|
#endif |
|
|
|
|
|
|
|
temp_hotend[e].soft_pwm_amount = (temp_hotend[e].current > temp_range[e].mintemp || is_preheating(e)) && temp_hotend[e].current < temp_range[e].maxtemp ? (int)get_pid_output(e) >> 1 : 0; |
|
|
|
temp_hotend[e].soft_pwm_amount = (temp_hotend[e].current > temp_range[e].mintemp || is_preheating(e)) && temp_hotend[e].current < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0; |
|
|
|
|
|
|
|
#if WATCH_HOTENDS |
|
|
|
// Make sure temperature is increasing
|
|
|
|
if (watch_hotend[e].next_ms && ELAPSED(ms, watch_hotend[e].next_ms)) { // Time to check this extruder?
|
|
|
|
if (degHotend(e) < watch_hotend[e].target) // Failed to increase enough?
|
|
|
|
_temp_error(e, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e)); |
|
|
|
_temp_error((heater_ind_t)e, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e)); |
|
|
|
else // Start again if the target is still far off
|
|
|
|
start_watching_heater(e); |
|
|
|
start_watching_hotend(e); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) |
|
|
|
// Make sure measured temperatures are close together
|
|
|
|
if (ABS(temp_hotend[0].current - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF) |
|
|
|
_temp_error(0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP)); |
|
|
|
_temp_error(H_E0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP)); |
|
|
|
#endif |
|
|
|
|
|
|
|
} // HOTEND_LOOP
|
|
|
@ -1066,14 +1059,14 @@ void Temperature::manage_heater() { |
|
|
|
|
|
|
|
#if ENABLED(THERMAL_PROTECTION_BED) |
|
|
|
if (!grace_period && degBed() > BED_MAXTEMP) |
|
|
|
_temp_error(-1, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, -1)); |
|
|
|
_temp_error(H_BED, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, H_BED)); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if WATCH_BED |
|
|
|
// Make sure temperature is increasing
|
|
|
|
if (watch_bed.elapsed(ms)) { // Time to check the bed?
|
|
|
|
if (degBed() < watch_bed.target) // Failed to increase enough?
|
|
|
|
_temp_error(-1, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, -1)); |
|
|
|
_temp_error(H_BED, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, H_BED)); |
|
|
|
else // Start again if the target is still far off
|
|
|
|
start_watching_bed(); |
|
|
|
} |
|
|
@ -1098,7 +1091,7 @@ void Temperature::manage_heater() { |
|
|
|
#endif |
|
|
|
|
|
|
|
#if HAS_THERMALLY_PROTECTED_BED |
|
|
|
thermal_runaway_protection(tr_state_machine_bed, temp_bed.current, temp_bed.target, -1, THERMAL_PROTECTION_BED_PERIOD, THERMAL_PROTECTION_BED_HYSTERESIS); |
|
|
|
thermal_runaway_protection(tr_state_machine_bed, temp_bed.current, temp_bed.target, H_BED, THERMAL_PROTECTION_BED_PERIOD, THERMAL_PROTECTION_BED_HYSTERESIS); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if HEATER_IDLE_HANDLER |
|
|
@ -1144,14 +1137,14 @@ void Temperature::manage_heater() { |
|
|
|
|
|
|
|
#if ENABLED(THERMAL_PROTECTION_CHAMBER) |
|
|
|
if (!grace_period && degChamber() > CHAMBER_MAXTEMP) |
|
|
|
_temp_error(-2, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, -2)); |
|
|
|
_temp_error(H_CHAMBER, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, H_CHAMBER)); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if WATCH_CHAMBER |
|
|
|
// Make sure temperature is increasing
|
|
|
|
if (watch_chamber.elapsed(ms)) { // Time to check the chamber?
|
|
|
|
if (degChamber() < watch_chamber.target) // Failed to increase enough?
|
|
|
|
_temp_error(-2, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, -2)); |
|
|
|
_temp_error(H_CHAMBER, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, H_CHAMBER)); |
|
|
|
else |
|
|
|
start_watching_chamber(); // Start again if the target is still far off
|
|
|
|
} |
|
|
@ -1176,7 +1169,7 @@ void Temperature::manage_heater() { |
|
|
|
} |
|
|
|
|
|
|
|
#if ENABLED(THERMAL_PROTECTION_CHAMBER) |
|
|
|
thermal_runaway_protection(tr_state_machine_chamber, temp_chamber.current, temp_chamber.target, -2, THERMAL_PROTECTION_CHAMBER_PERIOD, THERMAL_PROTECTION_CHAMBER_HYSTERESIS); |
|
|
|
thermal_runaway_protection(tr_state_machine_chamber, temp_chamber.current, temp_chamber.target, H_CHAMBER, THERMAL_PROTECTION_CHAMBER_PERIOD, THERMAL_PROTECTION_CHAMBER_HYSTERESIS); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
@ -1782,14 +1775,15 @@ void Temperature::init() { |
|
|
|
* their target temperature by a configurable margin. |
|
|
|
* This is called when the temperature is set. (M104, M109) |
|
|
|
*/ |
|
|
|
void Temperature::start_watching_heater(const uint8_t e) { |
|
|
|
void Temperature::start_watching_hotend(const uint8_t e) { |
|
|
|
E_UNUSED(); |
|
|
|
if (degTargetHotend(HOTEND_INDEX) && degHotend(HOTEND_INDEX) < degTargetHotend(HOTEND_INDEX) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) { |
|
|
|
watch_hotend[HOTEND_INDEX].target = degHotend(HOTEND_INDEX) + WATCH_TEMP_INCREASE; |
|
|
|
watch_hotend[HOTEND_INDEX].next_ms = millis() + (WATCH_TEMP_PERIOD) * 1000UL; |
|
|
|
const uint8_t ee = HOTEND_INDEX; |
|
|
|
if (degTargetHotend(ee) && degHotend(ee) < degTargetHotend(ee) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) { |
|
|
|
watch_hotend[ee].target = degHotend(ee) + WATCH_TEMP_INCREASE; |
|
|
|
watch_hotend[ee].next_ms = millis() + (WATCH_TEMP_PERIOD) * 1000UL; |
|
|
|
} |
|
|
|
else |
|
|
|
watch_hotend[HOTEND_INDEX].next_ms = 0; |
|
|
|
watch_hotend[ee].next_ms = 0; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
@ -1837,14 +1831,14 @@ void Temperature::init() { |
|
|
|
Temperature::tr_state_machine_t Temperature::tr_state_machine_chamber; // = { TRInactive, 0 };
|
|
|
|
#endif |
|
|
|
|
|
|
|
void Temperature::thermal_runaway_protection(Temperature::tr_state_machine_t &sm, const float ¤t, const float &target, const int8_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc) { |
|
|
|
void Temperature::thermal_runaway_protection(Temperature::tr_state_machine_t &sm, const float ¤t, const float &target, const heater_ind_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc) { |
|
|
|
|
|
|
|
static float tr_target_temperature[HOTENDS + 1] = { 0.0 }; |
|
|
|
|
|
|
|
/**
|
|
|
|
SERIAL_ECHO_START(); |
|
|
|
SERIAL_ECHOPGM("Thermal Thermal Runaway Running. Heater ID: "); |
|
|
|
if (heater_id == -2) SERIAL_ECHOPGM("chamber"); |
|
|
|
if (heater_id == H_CHAMBER) SERIAL_ECHOPGM("chamber"); |
|
|
|
if (heater_id < 0) SERIAL_ECHOPGM("bed"); else SERIAL_ECHO(heater_id); |
|
|
|
SERIAL_ECHOPAIR(" ; State:", sm.state, " ; Timer:", sm.timer, " ; Temperature:", current, " ; Target Temp:", target); |
|
|
|
if (heater_id >= 0) |
|
|
@ -2233,12 +2227,12 @@ void Temperature::readings_ready() { |
|
|
|
|| temp_hotend[e].soft_pwm_amount > 0 |
|
|
|
#endif |
|
|
|
); |
|
|
|
if (rawtemp > temp_range[e].raw_max * tdir) max_temp_error(e); |
|
|
|
if (rawtemp > temp_range[e].raw_max * tdir) max_temp_error((heater_ind_t)e); |
|
|
|
if (heater_on && rawtemp < temp_range[e].raw_min * tdir && !is_preheating(e)) { |
|
|
|
#ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED |
|
|
|
if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED) |
|
|
|
#endif |
|
|
|
min_temp_error(e); |
|
|
|
min_temp_error((heater_ind_t)e); |
|
|
|
} |
|
|
|
#ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED |
|
|
|
else |
|
|
@ -2258,8 +2252,8 @@ void Temperature::readings_ready() { |
|
|
|
|| (temp_bed.soft_pwm_amount > 0) |
|
|
|
#endif |
|
|
|
; |
|
|
|
if (BEDCMP(temp_bed.raw, maxtemp_raw_BED)) max_temp_error(-1); |
|
|
|
if (bed_on && BEDCMP(mintemp_raw_BED, temp_bed.raw)) min_temp_error(-1); |
|
|
|
if (BEDCMP(temp_bed.raw, maxtemp_raw_BED)) max_temp_error(H_BED); |
|
|
|
if (bed_on && BEDCMP(mintemp_raw_BED, temp_bed.raw)) min_temp_error(H_BED); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if HAS_HEATED_CHAMBER |
|
|
@ -2269,8 +2263,8 @@ void Temperature::readings_ready() { |
|
|
|
#define CHAMBERCMP(A,B) ((A)>=(B)) |
|
|
|
#endif |
|
|
|
const bool chamber_on = (temp_chamber.target > 0); |
|
|
|
if (CHAMBERCMP(temp_chamber.raw, maxtemp_raw_CHAMBER)) max_temp_error(-2); |
|
|
|
if (chamber_on && CHAMBERCMP(mintemp_raw_CHAMBER, temp_chamber.raw)) min_temp_error(-2); |
|
|
|
if (CHAMBERCMP(temp_chamber.raw, maxtemp_raw_CHAMBER)) max_temp_error(H_CHAMBER); |
|
|
|
if (chamber_on && CHAMBERCMP(mintemp_raw_CHAMBER, temp_chamber.raw)) min_temp_error(H_CHAMBER); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
@ -2782,20 +2776,20 @@ void Temperature::isr() { |
|
|
|
#if ENABLED(SHOW_TEMP_ADC_VALUES) |
|
|
|
, const float r |
|
|
|
#endif |
|
|
|
, const int8_t e=-3 |
|
|
|
, const heater_ind_t e=INDEX_NONE |
|
|
|
) { |
|
|
|
char k; |
|
|
|
switch (e) { |
|
|
|
#if HAS_TEMP_CHAMBER |
|
|
|
case -2: k = 'C'; break; |
|
|
|
case H_CHAMBER: k = 'C'; break; |
|
|
|
#endif |
|
|
|
#if HAS_TEMP_HOTEND |
|
|
|
default: k = 'T'; break; |
|
|
|
#if HAS_HEATED_BED |
|
|
|
case -1: k = 'B'; break; |
|
|
|
case H_BED: k = 'B'; break; |
|
|
|
#endif |
|
|
|
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) |
|
|
|
case -3: k = 'R'; break; |
|
|
|
case H_REDUNDANT: k = 'R'; break; |
|
|
|
#endif |
|
|
|
#elif HAS_HEATED_BED |
|
|
|
default: k = 'B'; break; |
|
|
@ -2832,7 +2826,7 @@ void Temperature::isr() { |
|
|
|
#if ENABLED(SHOW_TEMP_ADC_VALUES) |
|
|
|
, redundant_temperature_raw |
|
|
|
#endif |
|
|
|
, -3 // REDUNDANT
|
|
|
|
, H_REDUNDANT |
|
|
|
); |
|
|
|
#endif |
|
|
|
#endif |
|
|
@ -2841,7 +2835,7 @@ void Temperature::isr() { |
|
|
|
#if ENABLED(SHOW_TEMP_ADC_VALUES) |
|
|
|
, rawBedTemp() |
|
|
|
#endif |
|
|
|
, -1 // BED
|
|
|
|
, H_BED |
|
|
|
); |
|
|
|
#endif |
|
|
|
#if HAS_TEMP_CHAMBER |
|
|
@ -2854,7 +2848,7 @@ void Temperature::isr() { |
|
|
|
#if ENABLED(SHOW_TEMP_ADC_VALUES) |
|
|
|
, rawChamberTemp() |
|
|
|
#endif |
|
|
|
, -2 // CHAMBER
|
|
|
|
, H_CHAMBER |
|
|
|
); |
|
|
|
#endif // HAS_TEMP_CHAMBER
|
|
|
|
#if HOTENDS > 1 |
|
|
@ -2862,21 +2856,21 @@ void Temperature::isr() { |
|
|
|
#if ENABLED(SHOW_TEMP_ADC_VALUES) |
|
|
|
, rawHotendTemp(e) |
|
|
|
#endif |
|
|
|
, e |
|
|
|
, (heater_ind_t)e |
|
|
|
); |
|
|
|
#endif |
|
|
|
SERIAL_ECHOPAIR(" @:", getHeaterPower(target_extruder)); |
|
|
|
SERIAL_ECHOPAIR(" @:", getHeaterPower((heater_ind_t)target_extruder)); |
|
|
|
#if HAS_HEATED_BED |
|
|
|
SERIAL_ECHOPAIR(" B@:", getHeaterPower(-1)); |
|
|
|
SERIAL_ECHOPAIR(" B@:", getHeaterPower(H_BED)); |
|
|
|
#endif |
|
|
|
#if HAS_HEATED_CHAMBER |
|
|
|
SERIAL_ECHOPAIR(" C@:", getHeaterPower(-2)); |
|
|
|
SERIAL_ECHOPAIR(" C@:", getHeaterPower(H_CHAMBER)); |
|
|
|
#endif |
|
|
|
#if HOTENDS > 1 |
|
|
|
HOTEND_LOOP() { |
|
|
|
SERIAL_ECHOPAIR(" @", e); |
|
|
|
SERIAL_CHAR(':'); |
|
|
|
SERIAL_ECHO(getHeaterPower(e)); |
|
|
|
SERIAL_ECHO(getHeaterPower((heater_ind_t)e)); |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|