diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index f96254b44f..b5adb4add3 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -109,12 +109,7 @@ static bool ensure_safe_temperature(const AdvancedPauseMode mode=ADVANCED_PAUSE_ UNUSED(mode); #endif - wait_for_heatup = true; // M108 will clear this - while (wait_for_heatup && thermalManager.wait_for_heating(active_extruder)) idle(); - const bool status = wait_for_heatup; - wait_for_heatup = false; - - return status; + return thermalManager.wait_for_hotend(active_extruder); } static void do_pause_e_move(const float &length, const float &fr) { diff --git a/Marlin/src/gcode/control/M108_M112_M410.cpp b/Marlin/src/gcode/control/M108_M112_M410.cpp index 7b49951266..e2646a1743 100644 --- a/Marlin/src/gcode/control/M108_M112_M410.cpp +++ b/Marlin/src/gcode/control/M108_M112_M410.cpp @@ -31,6 +31,9 @@ * M108: Stop the waiting for heaters in M109, M190, M303. Does not affect the target temperature. */ void GcodeSuite::M108() { + #if HAS_RESUME_CONTINUE + wait_for_user = false; + #endif wait_for_heatup = false; } diff --git a/Marlin/src/gcode/feature/pause/M701_M702.cpp b/Marlin/src/gcode/feature/pause/M701_M702.cpp index 1203b6bd09..ed074a4123 100644 --- a/Marlin/src/gcode/feature/pause/M701_M702.cpp +++ b/Marlin/src/gcode/feature/pause/M701_M702.cpp @@ -81,7 +81,7 @@ void GcodeSuite::M701() { const float fast_load_length = ABS(parser.seen('L') ? parser.value_axis_units(E_AXIS) : filament_change_load_length[active_extruder]); load_filament(slow_load_length, fast_load_length, ADVANCED_PAUSE_PURGE_LENGTH, FILAMENT_CHANGE_ALERT_BEEPS, - true, thermalManager.wait_for_heating(target_extruder), ADVANCED_PAUSE_MODE_LOAD_FILAMENT + true, thermalManager.still_heating(target_extruder), ADVANCED_PAUSE_MODE_LOAD_FILAMENT #if ENABLED(DUAL_X_CARRIAGE) , target_extruder #endif diff --git a/Marlin/src/gcode/temperature/M104_M109.cpp b/Marlin/src/gcode/temperature/M104_M109.cpp index 07859ca21e..c59cd7038e 100644 --- a/Marlin/src/gcode/temperature/M104_M109.cpp +++ b/Marlin/src/gcode/temperature/M104_M109.cpp @@ -80,14 +80,6 @@ void GcodeSuite::M104() { * M109: Sxxx Wait for extruder(s) to reach temperature. Waits only when heating. * Rxxx Wait for extruder(s) to reach temperature. Waits when heating and cooling. */ - -#ifndef MIN_COOLING_SLOPE_DEG - #define MIN_COOLING_SLOPE_DEG 1.50 -#endif -#ifndef MIN_COOLING_SLOPE_TIME - #define MIN_COOLING_SLOPE_TIME 60 -#endif - void GcodeSuite::M109() { if (get_target_extruder_from_command()) return; @@ -137,110 +129,5 @@ void GcodeSuite::M109() { planner.autotemp_M104_M109(); #endif - #if TEMP_RESIDENCY_TIME > 0 - millis_t residency_start_ms = 0; - // Loop until the temperature has stabilized - #define TEMP_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL)) - #else - // Loop until the temperature is very close target - #define TEMP_CONDITIONS (wants_to_cool ? thermalManager.isCoolingHotend(target_extruder) : thermalManager.isHeatingHotend(target_extruder)) - #endif - - float target_temp = -1.0, old_temp = 9999.0; - bool wants_to_cool = false; - wait_for_heatup = true; - millis_t now, next_temp_ms = 0, next_cool_check_ms = 0; - - #if DISABLED(BUSY_WHILE_HEATING) - KEEPALIVE_STATE(NOT_BUSY); - #endif - - #if ENABLED(PRINTER_EVENT_LEDS) - const float start_temp = thermalManager.degHotend(target_extruder); - uint8_t old_blue = 0; - #endif - - do { - // Target temperature might be changed during the loop - if (target_temp != thermalManager.degTargetHotend(target_extruder)) { - wants_to_cool = thermalManager.isCoolingHotend(target_extruder); - target_temp = thermalManager.degTargetHotend(target_extruder); - - // Exit if S, continue if S, R, or R - if (no_wait_for_cooling && wants_to_cool) break; - } - - now = millis(); - if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting - next_temp_ms = now + 1000UL; - thermalManager.print_heaterstates(); - #if TEMP_RESIDENCY_TIME > 0 - SERIAL_PROTOCOLPGM(" W:"); - if (residency_start_ms) - SERIAL_PROTOCOL(long((((TEMP_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL)); - else - SERIAL_PROTOCOLCHAR('?'); - #endif - SERIAL_EOL(); - } - - idle(); - reset_stepper_timeout(); // Keep steppers powered - - const float temp = thermalManager.degHotend(target_extruder); - - #if ENABLED(PRINTER_EVENT_LEDS) - // Gradually change LED strip from violet to red as nozzle heats up - if (!wants_to_cool) { - const uint8_t blue = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 255, 0); - if (blue != old_blue) { - old_blue = blue; - leds.set_color( - MakeLEDColor(255, 0, blue, 0, pixels.getBrightness()) - #if ENABLED(NEOPIXEL_IS_SEQUENTIAL) - , true - #endif - ); - } - } - #endif - - #if TEMP_RESIDENCY_TIME > 0 - - const float temp_diff = ABS(target_temp - temp); - - if (!residency_start_ms) { - // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time. - if (temp_diff < TEMP_WINDOW) residency_start_ms = now; - } - else if (temp_diff > TEMP_HYSTERESIS) { - // Restart the timer whenever the temperature falls outside the hysteresis. - residency_start_ms = now; - } - - #endif - - // Prevent a wait-forever situation if R is misused i.e. M109 R0 - if (wants_to_cool) { - // break after MIN_COOLING_SLOPE_TIME seconds - // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG - if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { - if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG)) break; - next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME; - old_temp = temp; - } - } - - } while (wait_for_heatup && TEMP_CONDITIONS); - - if (wait_for_heatup) { - lcd_reset_status(); - #if ENABLED(PRINTER_EVENT_LEDS) - leds.set_white(); - #endif - } - - #if DISABLED(BUSY_WHILE_HEATING) - KEEPALIVE_STATE(IN_HANDLER); - #endif + (void)thermalManager.wait_for_hotend(target_extruder, no_wait_for_cooling); } diff --git a/Marlin/src/gcode/temperature/M140_M190.cpp b/Marlin/src/gcode/temperature/M140_M190.cpp index c51c643288..8a42eb85be 100644 --- a/Marlin/src/gcode/temperature/M140_M190.cpp +++ b/Marlin/src/gcode/temperature/M140_M190.cpp @@ -47,13 +47,6 @@ void GcodeSuite::M140() { if (parser.seenval('S')) thermalManager.setTargetBed(parser.value_celsius()); } -#ifndef MIN_COOLING_SLOPE_DEG_BED - #define MIN_COOLING_SLOPE_DEG_BED 1.50 -#endif -#ifndef MIN_COOLING_SLOPE_TIME_BED - #define MIN_COOLING_SLOPE_TIME_BED 60 -#endif - /** * M190: Sxxx Wait for bed current temp to reach target temp. Waits only when heating * Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling @@ -73,108 +66,7 @@ void GcodeSuite::M190() { lcd_setstatusPGM(thermalManager.isHeatingBed() ? PSTR(MSG_BED_HEATING) : PSTR(MSG_BED_COOLING)); - #if TEMP_BED_RESIDENCY_TIME > 0 - millis_t residency_start_ms = 0; - // Loop until the temperature has stabilized - #define TEMP_BED_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_BED_RESIDENCY_TIME) * 1000UL)) - #else - // Loop until the temperature is very close target - #define TEMP_BED_CONDITIONS (wants_to_cool ? thermalManager.isCoolingBed() : thermalManager.isHeatingBed()) - #endif - - float target_temp = -1, old_temp = 9999; - bool wants_to_cool = false; - wait_for_heatup = true; - millis_t now, next_temp_ms = 0, next_cool_check_ms = 0; - - #if DISABLED(BUSY_WHILE_HEATING) - KEEPALIVE_STATE(NOT_BUSY); - #endif - - target_extruder = active_extruder; // for print_heaterstates - - #if ENABLED(PRINTER_EVENT_LEDS) - const float start_temp = thermalManager.degBed(); - uint8_t old_red = 127; - #endif - - do { - // Target temperature might be changed during the loop - if (target_temp != thermalManager.degTargetBed()) { - wants_to_cool = thermalManager.isCoolingBed(); - target_temp = thermalManager.degTargetBed(); - - // Exit if S, continue if S, R, or R - if (no_wait_for_cooling && wants_to_cool) break; - } - - now = millis(); - if (ELAPSED(now, next_temp_ms)) { //Print Temp Reading every 1 second while heating up. - next_temp_ms = now + 1000UL; - thermalManager.print_heaterstates(); - #if TEMP_BED_RESIDENCY_TIME > 0 - SERIAL_PROTOCOLPGM(" W:"); - if (residency_start_ms) - SERIAL_PROTOCOL(long((((TEMP_BED_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL)); - else - SERIAL_PROTOCOLCHAR('?'); - #endif - SERIAL_EOL(); - } - - idle(); - reset_stepper_timeout(); // Keep steppers powered - - const float temp = thermalManager.degBed(); - - #if ENABLED(PRINTER_EVENT_LEDS) - // Gradually change LED strip from blue to violet as bed heats up - if (!wants_to_cool) { - const uint8_t red = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 0, 255); - if (red != old_red) { - old_red = red; - leds.set_color( - MakeLEDColor(red, 0, 255, 0, pixels.getBrightness()) - #if ENABLED(NEOPIXEL_IS_SEQUENTIAL) - , true - #endif - ); - } - } - #endif - - #if TEMP_BED_RESIDENCY_TIME > 0 - - const float temp_diff = ABS(target_temp - temp); - - if (!residency_start_ms) { - // Start the TEMP_BED_RESIDENCY_TIME timer when we reach target temp for the first time. - if (temp_diff < TEMP_BED_WINDOW) residency_start_ms = now; - } - else if (temp_diff > TEMP_BED_HYSTERESIS) { - // Restart the timer whenever the temperature falls outside the hysteresis. - residency_start_ms = now; - } - - #endif // TEMP_BED_RESIDENCY_TIME > 0 - - // Prevent a wait-forever situation if R is misused i.e. M190 R0 - if (wants_to_cool) { - // Break after MIN_COOLING_SLOPE_TIME_BED seconds - // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG_BED - if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { - if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG_BED)) break; - next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME_BED; - old_temp = temp; - } - } - - } while (wait_for_heatup && TEMP_BED_CONDITIONS); - - if (wait_for_heatup) lcd_reset_status(); - #if DISABLED(BUSY_WHILE_HEATING) - KEEPALIVE_STATE(IN_HANDLER); - #endif + thermalManager.wait_for_bed(no_wait_for_cooling); } #endif // HAS_HEATED_BED diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 6a91f8a1b9..890efe82f7 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -51,6 +51,10 @@ #include "../feature/emergency_parser.h" #endif +#if ENABLED(PRINTER_EVENT_LEDS) + #include "../feature/leds/leds.h" +#endif + #if HOTEND_USES_THERMISTOR #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) static void* heater_ttbl_map[2] = { (void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE }; @@ -2412,4 +2416,248 @@ void Temperature::isr() { #endif // AUTO_REPORT_TEMPERATURES + #if HAS_TEMP_HOTEND + + #ifndef MIN_COOLING_SLOPE_DEG + #define MIN_COOLING_SLOPE_DEG 1.50 + #endif + #ifndef MIN_COOLING_SLOPE_TIME + #define MIN_COOLING_SLOPE_TIME 60 + #endif + + bool Temperature::wait_for_hotend(const uint8_t target_extruder, const bool no_wait_for_cooling/*=true*/) { + #if TEMP_RESIDENCY_TIME > 0 + millis_t residency_start_ms = 0; + // Loop until the temperature has stabilized + #define TEMP_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL)) + #else + // Loop until the temperature is very close target + #define TEMP_CONDITIONS (wants_to_cool ? isCoolingHotend(target_extruder) : isHeatingHotend(target_extruder)) + #endif + + #if DISABLED(BUSY_WHILE_HEATING) + #if ENABLED(HOST_KEEPALIVE_FEATURE) + const MarlinBusyState old_busy_state = gcode.busy_state; + #endif + KEEPALIVE_STATE(NOT_BUSY); + #endif + + #if ENABLED(PRINTER_EVENT_LEDS) + const float start_temp = degHotend(target_extruder); + uint8_t old_blue = 0; + #endif + + float target_temp = -1.0, old_temp = 9999.0; + bool wants_to_cool = false; + wait_for_heatup = true; + millis_t now, next_temp_ms = 0, next_cool_check_ms = 0; + do { + // Target temperature might be changed during the loop + if (target_temp != degTargetHotend(target_extruder)) { + wants_to_cool = isCoolingHotend(target_extruder); + target_temp = degTargetHotend(target_extruder); + + // Exit if S, continue if S, R, or R + if (no_wait_for_cooling && wants_to_cool) break; + } + + now = millis(); + if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting + next_temp_ms = now + 1000UL; + print_heaterstates(); + #if TEMP_RESIDENCY_TIME > 0 + SERIAL_PROTOCOLPGM(" W:"); + if (residency_start_ms) + SERIAL_PROTOCOL(long((((TEMP_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL)); + else + SERIAL_PROTOCOLCHAR('?'); + #endif + SERIAL_EOL(); + } + + idle(); + gcode.reset_stepper_timeout(); // Keep steppers powered + + const float temp = degHotend(target_extruder); + + #if ENABLED(PRINTER_EVENT_LEDS) + // Gradually change LED strip from violet to red as nozzle heats up + if (!wants_to_cool) { + const uint8_t blue = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 255, 0); + if (blue != old_blue) { + old_blue = blue; + leds.set_color( + MakeLEDColor(255, 0, blue, 0, pixels.getBrightness()) + #if ENABLED(NEOPIXEL_IS_SEQUENTIAL) + , true + #endif + ); + } + } + #endif + + #if TEMP_RESIDENCY_TIME > 0 + + const float temp_diff = ABS(target_temp - temp); + + if (!residency_start_ms) { + // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time. + if (temp_diff < TEMP_WINDOW) residency_start_ms = now; + } + else if (temp_diff > TEMP_HYSTERESIS) { + // Restart the timer whenever the temperature falls outside the hysteresis. + residency_start_ms = now; + } + + #endif + + // Prevent a wait-forever situation if R is misused i.e. M109 R0 + if (wants_to_cool) { + // break after MIN_COOLING_SLOPE_TIME seconds + // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG + if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { + if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG)) break; + next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME; + old_temp = temp; + } + } + + } while (wait_for_heatup && TEMP_CONDITIONS); + + if (wait_for_heatup) { + lcd_reset_status(); + #if ENABLED(PRINTER_EVENT_LEDS) + leds.set_white(); + #endif + } + + #if DISABLED(BUSY_WHILE_HEATING) && ENABLED(HOST_KEEPALIVE_FEATURE) + gcode.busy_state = old_busy_state; + #endif + + return wait_for_heatup; + } + + #endif // HAS_TEMP_HOTEND + + #if HAS_HEATED_BED + + #ifndef MIN_COOLING_SLOPE_DEG_BED + #define MIN_COOLING_SLOPE_DEG_BED 1.50 + #endif + #ifndef MIN_COOLING_SLOPE_TIME_BED + #define MIN_COOLING_SLOPE_TIME_BED 60 + #endif + + void Temperature::wait_for_bed(const bool no_wait_for_cooling) { + #if TEMP_BED_RESIDENCY_TIME > 0 + millis_t residency_start_ms = 0; + // Loop until the temperature has stabilized + #define TEMP_BED_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_BED_RESIDENCY_TIME) * 1000UL)) + #else + // Loop until the temperature is very close target + #define TEMP_BED_CONDITIONS (wants_to_cool ? isCoolingBed() : isHeatingBed()) + #endif + + float target_temp = -1, old_temp = 9999; + bool wants_to_cool = false; + wait_for_heatup = true; + millis_t now, next_temp_ms = 0, next_cool_check_ms = 0; + + #if DISABLED(BUSY_WHILE_HEATING) + #if ENABLED(HOST_KEEPALIVE_FEATURE) + const MarlinBusyState old_busy_state = gcode.busy_state; + #endif + KEEPALIVE_STATE(NOT_BUSY); + #endif + + gcode.target_extruder = active_extruder; // for print_heaterstates + + #if ENABLED(PRINTER_EVENT_LEDS) + const float start_temp = degBed(); + uint8_t old_red = 127; + #endif + + do { + // Target temperature might be changed during the loop + if (target_temp != degTargetBed()) { + wants_to_cool = isCoolingBed(); + target_temp = degTargetBed(); + + // Exit if S, continue if S, R, or R + if (no_wait_for_cooling && wants_to_cool) break; + } + + now = millis(); + if (ELAPSED(now, next_temp_ms)) { //Print Temp Reading every 1 second while heating up. + next_temp_ms = now + 1000UL; + print_heaterstates(); + #if TEMP_BED_RESIDENCY_TIME > 0 + SERIAL_PROTOCOLPGM(" W:"); + if (residency_start_ms) + SERIAL_PROTOCOL(long((((TEMP_BED_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL)); + else + SERIAL_PROTOCOLCHAR('?'); + #endif + SERIAL_EOL(); + } + + idle(); + gcode.reset_stepper_timeout(); // Keep steppers powered + + const float temp = degBed(); + + #if ENABLED(PRINTER_EVENT_LEDS) + // Gradually change LED strip from blue to violet as bed heats up + if (!wants_to_cool) { + const uint8_t red = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 0, 255); + if (red != old_red) { + old_red = red; + leds.set_color( + MakeLEDColor(red, 0, 255, 0, pixels.getBrightness()) + #if ENABLED(NEOPIXEL_IS_SEQUENTIAL) + , true + #endif + ); + } + } + #endif + + #if TEMP_BED_RESIDENCY_TIME > 0 + + const float temp_diff = ABS(target_temp - temp); + + if (!residency_start_ms) { + // Start the TEMP_BED_RESIDENCY_TIME timer when we reach target temp for the first time. + if (temp_diff < TEMP_BED_WINDOW) residency_start_ms = now; + } + else if (temp_diff > TEMP_BED_HYSTERESIS) { + // Restart the timer whenever the temperature falls outside the hysteresis. + residency_start_ms = now; + } + + #endif // TEMP_BED_RESIDENCY_TIME > 0 + + // Prevent a wait-forever situation if R is misused i.e. M190 R0 + if (wants_to_cool) { + // Break after MIN_COOLING_SLOPE_TIME_BED seconds + // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG_BED + if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { + if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG_BED)) break; + next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME_BED; + old_temp = temp; + } + } + + } while (wait_for_heatup && TEMP_BED_CONDITIONS); + + if (wait_for_heatup) lcd_reset_status(); + + #if DISABLED(BUSY_WHILE_HEATING) && ENABLED(HOST_KEEPALIVE_FEATURE) + gcode.busy_state = old_busy_state; + #endif + } + + #endif // HAS_HEATED_BED + #endif // HAS_TEMP_SENSOR diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index f91de03b57..53cdcdb5ea 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -433,7 +433,12 @@ class Temperature { return target_temperature[HOTEND_INDEX] < current_temperature[HOTEND_INDEX]; } + #if HAS_TEMP_HOTEND + static bool wait_for_hotend(const uint8_t target_extruder, const bool no_wait_for_cooling=true); + #endif + #if HAS_HEATED_BED + #if ENABLED(SHOW_TEMP_ADC_VALUES) FORCE_INLINE static int16_t rawBedTemp() { return current_temperature_bed_raw; } #endif @@ -461,7 +466,10 @@ class Temperature { #if WATCH_THE_BED static void start_watching_bed(); #endif - #endif + + static void wait_for_bed(const bool no_wait_for_cooling); + + #endif // HAS_HEATED_BED #if HAS_TEMP_CHAMBER #if ENABLED(SHOW_TEMP_ADC_VALUES) @@ -470,7 +478,7 @@ class Temperature { FORCE_INLINE static float degChamber() { return current_temperature_chamber; } #endif - FORCE_INLINE static bool wait_for_heating(const uint8_t e) { + FORCE_INLINE static bool still_heating(const uint8_t e) { return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS; }