Named indices for Temperature class (#14479)

This commit is contained in:
Scott Lahteine 2019-07-02 08:39:55 -05:00 committed by GitHub
parent 274809aced
commit 720bc7c00b
Signed by: GitHub
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 131 deletions

View file

@ -36,19 +36,18 @@
* U<bool> with a non-zero value will apply the result to current settings * U<bool> with a non-zero value will apply the result to current settings
*/ */
void GcodeSuite::M303() { void GcodeSuite::M303() {
#if ENABLED(PIDTEMPBED)
const int8_t e = parser.intval('E'); #define SI H_BED
#else
if (!WITHIN(e, 0 #define SI H_E0
#if ENABLED(PIDTEMPBED) #endif
-1 #if ENABLED(PIDTEMP)
#endif #define EI HOTENDS - 1
, #else
#if ENABLED(PIDTEMP) #define EI H_BED
HOTENDS #endif
#endif const heater_ind_t e = (heater_ind_t)parser.intval('E');
-1 if (!WITHIN(e, SI, EI)) {
)) {
SERIAL_ECHOLNPGM(MSG_PID_BAD_EXTRUDER_NUM); SERIAL_ECHOLNPGM(MSG_PID_BAD_EXTRUDER_NUM);
return; return;
} }

View file

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

View file

@ -45,6 +45,13 @@
#define E_UNUSED() #define E_UNUSED()
#endif #endif
// Identifiers for other heaters
typedef enum : int8_t {
INDEX_NONE = -4,
H_REDUNDANT, H_CHAMBER, H_BED,
H_E0, H_E1, H_E2, H_E3, H_E4, H_E5
} heater_ind_t;
// PID storage // PID storage
typedef struct { float Kp, Ki, Kd; } PID_t; typedef struct { float Kp, Ki, Kd; } PID_t;
typedef struct { float Kp, Ki, Kd, Kc; } PIDC_t; typedef struct { float Kp, Ki, Kd, Kc; } PIDC_t;
@ -580,33 +587,34 @@ class Temperature {
} }
#if WATCH_HOTENDS #if WATCH_HOTENDS
static void start_watching_heater(const uint8_t e=0); static void start_watching_hotend(const uint8_t e=0);
#else #else
static inline void start_watching_heater(const uint8_t e=0) { UNUSED(e); } static inline void start_watching_hotend(const uint8_t e=0) { UNUSED(e); }
#endif #endif
#if HAS_LCD_MENU #if HAS_LCD_MENU
static inline void start_watching_E0() { start_watching_heater(0); } static inline void start_watching_E0() { start_watching_hotend(0); }
static inline void start_watching_E1() { start_watching_heater(1); } static inline void start_watching_E1() { start_watching_hotend(1); }
static inline void start_watching_E2() { start_watching_heater(2); } static inline void start_watching_E2() { start_watching_hotend(2); }
static inline void start_watching_E3() { start_watching_heater(3); } static inline void start_watching_E3() { start_watching_hotend(3); }
static inline void start_watching_E4() { start_watching_heater(4); } static inline void start_watching_E4() { start_watching_hotend(4); }
static inline void start_watching_E5() { start_watching_heater(5); } static inline void start_watching_E5() { start_watching_hotend(5); }
#endif #endif
static void setTargetHotend(const int16_t celsius, const uint8_t e) { static void setTargetHotend(const int16_t celsius, const uint8_t e) {
E_UNUSED(); E_UNUSED();
const uint8_t ee = HOTEND_INDEX;
#ifdef MILLISECONDS_PREHEAT_TIME #ifdef MILLISECONDS_PREHEAT_TIME
if (celsius == 0) if (celsius == 0)
reset_preheat_time(HOTEND_INDEX); reset_preheat_time(ee);
else if (temp_hotend[HOTEND_INDEX].target == 0) else if (temp_hotend[ee].target == 0)
start_preheat_time(HOTEND_INDEX); start_preheat_time(ee);
#endif #endif
#if ENABLED(AUTO_POWER_CONTROL) #if ENABLED(AUTO_POWER_CONTROL)
powerManager.power_on(); powerManager.power_on();
#endif #endif
temp_hotend[HOTEND_INDEX].target = MIN(celsius, temp_range[HOTEND_INDEX].maxtemp - 15); temp_hotend[ee].target = MIN(celsius, temp_range[ee].maxtemp - 15);
start_watching_heater(HOTEND_INDEX); start_watching_hotend(ee);
} }
#if WATCH_CHAMBER #if WATCH_CHAMBER
@ -705,7 +713,7 @@ class Temperature {
/** /**
* The software PWM power for a heater * The software PWM power for a heater
*/ */
static int16_t getHeaterPower(const int8_t heater); static int16_t getHeaterPower(const heater_ind_t heater);
/** /**
* Switch off all heaters, set all target temperatures to 0 * Switch off all heaters, set all target temperatures to 0
@ -716,7 +724,7 @@ class Temperature {
* Perform auto-tuning for hotend or bed in response to M303 * Perform auto-tuning for hotend or bed in response to M303
*/ */
#if HAS_PID_HEATING #if HAS_PID_HEATING
static void PID_autotune(const float &target, const int8_t hotend, const int8_t ncycles, const bool set_result=false); static void PID_autotune(const float &target, const heater_ind_t hotend, const int8_t ncycles, const bool set_result=false);
#if ENABLED(NO_FAN_SLOWING_IN_PID_TUNING) #if ENABLED(NO_FAN_SLOWING_IN_PID_TUNING)
static bool adaptive_fan_slowing; static bool adaptive_fan_slowing;
@ -747,7 +755,7 @@ class Temperature {
static void reset_heater_idle_timer(const uint8_t e) { static void reset_heater_idle_timer(const uint8_t e) {
E_UNUSED(); E_UNUSED();
hotend_idle[HOTEND_INDEX].reset(); hotend_idle[HOTEND_INDEX].reset();
start_watching_heater(HOTEND_INDEX); start_watching_hotend(HOTEND_INDEX);
} }
#if HAS_HEATED_BED #if HAS_HEATED_BED
@ -806,7 +814,7 @@ class Temperature {
static void checkExtruderAutoFans(); static void checkExtruderAutoFans();
static float get_pid_output(const int8_t e); static float get_pid_output_hotend(const uint8_t e);
#if ENABLED(PIDTEMPBED) #if ENABLED(PIDTEMPBED)
static float get_pid_output_bed(); static float get_pid_output_bed();
@ -816,9 +824,9 @@ class Temperature {
static float get_pid_output_chamber(); static float get_pid_output_chamber();
#endif #endif
static void _temp_error(const int8_t e, PGM_P const serial_msg, PGM_P const lcd_msg); static void _temp_error(const heater_ind_t e, PGM_P const serial_msg, PGM_P const lcd_msg);
static void min_temp_error(const int8_t e); static void min_temp_error(const heater_ind_t e);
static void max_temp_error(const int8_t e); static void max_temp_error(const heater_ind_t e);
#if ENABLED(THERMAL_PROTECTION_HOTENDS) || HAS_THERMALLY_PROTECTED_BED || ENABLED(THERMAL_PROTECTION_CHAMBER) #if ENABLED(THERMAL_PROTECTION_HOTENDS) || HAS_THERMALLY_PROTECTED_BED || ENABLED(THERMAL_PROTECTION_CHAMBER)
@ -839,7 +847,7 @@ class Temperature {
static tr_state_machine_t tr_state_machine_chamber; static tr_state_machine_t tr_state_machine_chamber;
#endif #endif
static void thermal_runaway_protection(tr_state_machine_t &state, const float &current, const float &target, const int8_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc); static void thermal_runaway_protection(tr_state_machine_t &state, const float &current, const float &target, const heater_ind_t heater_id, const uint16_t period_seconds, const uint16_t hysteresis_degc);
#endif // THERMAL_PROTECTION #endif // THERMAL_PROTECTION
}; };