diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index c04e702f0d..8901b6052a 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -217,7 +217,7 @@ uint8_t Temperature::soft_pwm_amount[HOTENDS], #if HAS_PID_HEATING - void Temperature::PID_autotune(float temp, int hotend, int ncycles, bool set_result/*=false*/) { + void Temperature::PID_autotune(const float temp, const int8_t hotend, const int8_t ncycles, const bool set_result/*=false*/) { float input = 0.0; int cycles = 0; bool heating = true; @@ -226,27 +226,59 @@ uint8_t Temperature::soft_pwm_amount[HOTENDS], long t_high = 0, t_low = 0; long bias, d; - float Ku, Tu; - float workKp = 0, workKi = 0, workKd = 0; - float max = 0, min = 10000; + float Ku, Tu, + workKp = 0, workKi = 0, workKd = 0, + max = 0, min = 10000; + + #if WATCH_THE_BED || WATCH_HOTENDS + const float watch_temp_target = temp - + #if ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED) && ENABLED(THERMAL_PROTECTION_HOTENDS) && ENABLED(PIDTEMP) + (hotend < 0 ? (WATCH_BED_TEMP_INCREASE + TEMP_BED_HYSTERESIS + 1) : (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) + #elif ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED) + (WATCH_BED_TEMP_INCREASE + TEMP_BED_HYSTERESIS + 1) + #else + (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1) + #endif + ; + const int8_t watch_temp_period = + #if ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED) && ENABLED(THERMAL_PROTECTION_HOTENDS) && ENABLED(PIDTEMP) + hotend < 0 ? temp - THERMAL_PROTECTION_BED_PERIOD : THERMAL_PROTECTION_PERIOD + #elif ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED) + THERMAL_PROTECTION_BED_PERIOD + #else + THERMAL_PROTECTION_PERIOD + #endif + ; + const int8_t hysteresis = + #if ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED) && ENABLED(THERMAL_PROTECTION_HOTENDS) && ENABLED(PIDTEMP) + hotend < 0 ? TEMP_BED_HYSTERESIS : TEMP_HYSTERESIS + #elif ENABLED(THERMAL_PROTECTION_BED) && ENABLED(PIDTEMPBED) + TEMP_BED_HYSTERESIS + #else + TEMP_HYSTERESIS + #endif + ; + millis_t temp_change_ms = next_temp_ms + watch_temp_period * 1000UL; + float next_watch_temp = 0.0; + bool heated = false; + #endif #if HAS_AUTO_FAN next_auto_fan_check_ms = next_temp_ms + 2500UL; #endif - if (hotend >= - #if ENABLED(PIDTEMP) - HOTENDS - #else - 0 - #endif - || hotend < - #if ENABLED(PIDTEMPBED) - -1 - #else - 0 - #endif - ) { + #if ENABLED(PIDTEMP) + #define _TOP_HOTEND HOTENDS - 1 + #else + #define _TOP_HOTEND -1 + #endif + #if ENABLED(PIDTEMPBED) + #define _BOT_HOTEND -1 + #else + #define _BOT_HOTEND 0 + #endif + + if (!WITHIN(hotend, _BOT_HOTEND, _TOP_HOTEND)) { SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM); return; } @@ -332,7 +364,7 @@ uint8_t Temperature::soft_pwm_amount[HOTENDS], ; bias += (d * (t_high - t_low)) / (t_low + t_high); bias = constrain(bias, 20, max_pow - 20); - d = (bias > max_pow / 2) ? max_pow - 1 - bias : bias; + d = (bias > max_pow >> 1) ? max_pow - 1 - bias : bias; SERIAL_PROTOCOLPAIR(MSG_BIAS, bias); SERIAL_PROTOCOLPAIR(MSG_D, d); @@ -396,6 +428,16 @@ uint8_t Temperature::soft_pwm_amount[HOTENDS], #endif next_temp_ms = ms + 2000UL; + + #if WATCH_THE_BED || WATCH_HOTENDS + if (!heated && input > next_watch_temp) { + if (input > watch_temp_target) heated = true; + next_watch_temp = input + hysteresis; + temp_change_ms = ms + watch_temp_period * 1000UL; + } + else if ((!heated && ELAPSED(ms, temp_change_ms)) || (heated && input < temp - MAX_OVERSHOOT_PID_AUTOTUNE)) + _temp_error(hotend, PSTR(MSG_T_THERMAL_RUNAWAY), PSTR(MSG_THERMAL_RUNAWAY)); + #endif } // every 2 seconds // Timeout after 20 minutes since the last undershoot/overshoot cycle if (((ms - t1) + (ms - t2)) > (20L * 60L * 1000L)) { diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index ad9ff1818f..51a9038d28 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -429,7 +429,7 @@ class Temperature { * Perform auto-tuning for hotend or bed in response to M303 */ #if HAS_PID_HEATING - static void PID_autotune(float temp, int hotend, int ncycles, bool set_result=false); + static void PID_autotune(const float temp, const int8_t hotend, const int8_t ncycles, const bool set_result=false); #endif /**