From f022567239427bca4485240657431f3421475380 Mon Sep 17 00:00:00 2001 From: gudnimg Date: Sat, 27 Jan 2024 11:53:46 +0000 Subject: [PATCH] PFW-1522 Fix an issue where MMU unloads while nozzle is cold if print is stopped In the case of a Fan Error, the print is paused. If the nozzle is allowed to cool for a while before the print is stopped via the LCD, then the MMU will try to unload with a cold nozzle. This can happen with ANY recoverable thermal errors. In this commit I attempt to fix all scenarios. Including PFW-1544 where the nozzle is cooling down when the print has finished normally. PFW-1544 PFW-1552 Change in memory: Flash: +74 bytes SRAM: 0 bytes --- Firmware/Marlin.h | 1 + Firmware/Marlin_main.cpp | 24 +++++++++++++++++++++++- Firmware/ultralcd.cpp | 25 ++++++++++++++++++------- Firmware/ultralcd.h | 6 +++++- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 79c51a639..2bf581356 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -197,6 +197,7 @@ void kill(const char *full_screen_message = NULL); void finishAndDisableSteppers(); void UnconditionalStop(); // Stop heaters, motion and clear current print status +void ConditionalStop(); // Similar to UnconditionalStop, but doesn't disable heaters void ThermalStop(bool allow_pause = false); // Emergency stop used by overtemp functions which allows // recovery (with pause=true) bool IsStopped(); // Returns true if the print has been stopped diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index f5e2fd5a6..2ff58a709 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9755,6 +9755,28 @@ void UnconditionalStop() st_reset_timer(); CRITICAL_SECTION_END; + + // clear paused state immediately + did_pause_print = false; + print_job_timer.stop(); +} + +void ConditionalStop() +{ + CRITICAL_SECTION_START; + + // Clear any saved printing state + cancel_saved_printing(); + + // Abort the planner + planner_abort_hard(); + + // Reset the queue + cmdqueue_reset(); + cmdqueue_serial_disabled = false; + + st_reset_timer(); + CRITICAL_SECTION_END; } // Emergency stop used by overtemp functions which allows recovery @@ -9789,7 +9811,7 @@ void ThermalStop(bool allow_recovery) } } else { // We got a hard thermal error and/or there is no print going on. Just stop. - print_stop(); + print_stop(false, true); } // Report the error on the serial diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 426ab3344..b926d7342 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -5656,6 +5656,7 @@ void retract_for_ooze_prevention() { // continue stopping the print from the main loop after lcd_print_stop() is called void lcd_print_stop_finish() { + print_job_timer.stop(); save_statistics(); // lift Z @@ -5688,26 +5689,40 @@ void lcd_print_stop_finish() if (MMU2::mmu2.Enabled() && MMU2::mmu2.FindaDetectsFilament()) { + // The print was aborted while when the nozzle was cold: + // 1. in a paused state => a partial backup in RAM is always available + // 2. after a recoverable thermal/fan error had paused the print => only extruder temperature is saved to RAM if (printingIsPaused()) { // Restore temperature saved in ram after pausing print restore_extruder_temperature_from_ram(); } - MMU2::mmu2.unload(); // M702 + + // If the pause state was cleared previously or the target temperature is 0°C in the case + // of an unconditional stop. In that scenario we do not want to unload. + if (target_temperature[0] >= extrude_min_temp) { + MMU2::mmu2.unload(); // M702 + } } lcd_cooldown(); //turns off heaters and fan; goes to status screen. finishAndDisableSteppers(); //M84 axis_relative_modes = E_AXIS_MASK; //XYZ absolute, E relative + did_pause_print = false; // Clear pause state in case the print was aborted while paused } -void print_stop(bool interactive) +void print_stop(bool interactive, bool unconditional_stop) { // UnconditionalStop() will internally cause planner_abort_hard(), meaning we _cannot_ plan any // more move in this call! Any further move must happen inside lcd_print_stop_finish(), which is // called by the main loop one iteration later. - UnconditionalStop(); + if (unconditional_stop) { + UnconditionalStop(); + } else { + // Allow lcd_print_stop_finish() to use the heaters when it is safe + ConditionalStop(); + } if (card.sdprinting) { // Reset the sd status @@ -5721,10 +5736,6 @@ void print_stop(bool interactive) mbl.active = false; #endif - // clear any pending paused state immediately - did_pause_print = false; - print_job_timer.stop(); - if (interactive) { // acknowledged by the user from the LCD: resume processing USB commands again Stopped = false; diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index afb4ace77..71caf73ea 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -60,7 +60,11 @@ void lcd_pause_usb_print(); void lcd_send_action_start(); void lcd_resume_print(); void lcd_print_stop(); // interactive print stop -void print_stop(bool interactive=false); + +/// @brief Stop the print immediately +/// @param interactive True if the user acknowledged the action from the LCD: resume processing USB commands again +/// @param unconditional_stop True when the print is stopped by a serious error condition e.g. Thermal Runaway. False otherwise. +void print_stop(bool interactive=false, bool unconditional_stop=false); #ifdef THERMAL_MODEL void lcd_thermal_model_cal(); #endif //THERMAL_MODEL