From a3915b57b9f7984164876a7ba70c1c8196b7556f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 7 Dec 2021 11:11:06 +0100 Subject: [PATCH] Improve temp_runaway_stop robustness Remove most of the duplicated code inside temp_runaway_stop(), making it identical to the other temperature handlers. Move the lower-level functions required to stop the entirety of the machine into UnconditionalStop(). Reuse this function inside lcd_print_stop(). Set the LCD alert message before calling Stop(), as done in other safety handlers, so that the error is visible while the printer is stopping. This also avoids other temporary status messages to appear before the real issue is shown and/or STEALING the first CRITICAL alert level before we do. --- Firmware/Marlin.h | 6 ++++-- Firmware/Marlin_main.cpp | 37 +++++++++++++++++++++++++++++++++++++ Firmware/temperature.cpp | 37 ++++++++++--------------------------- Firmware/temperature.h | 2 +- Firmware/ultralcd.cpp | 25 +++++++------------------ 5 files changed, 59 insertions(+), 48 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index c2c5ca93..85c4dae1 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -236,10 +236,12 @@ void update_currents(); void get_coordinates(); void prepare_move(); void kill(const char *full_screen_message = NULL, unsigned char id = 0); -void Stop(); -bool IsStopped(); void finishAndDisableSteppers(); +void UnconditionalStop(); // Stop heaters, motion and clear current print status +void Stop(); // Emergency stop used by overtemp functions which allows recovery +bool IsStopped(); // Returns true if the print has been stopped + //put an ASCII command at the end of the current buffer, read from flash #define enquecommand_P(cmd) enquecommand(cmd, true) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 2d53b1cd..5fb82577 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -10154,6 +10154,31 @@ void kill(const char *full_screen_message, unsigned char id) } // Wait for reset } +void UnconditionalStop() +{ + CRITICAL_SECTION_START; + + // Disable all heaters and unroll the temperature wait loop stack + disable_heater(); + + // Clear any saved printing state + cancel_saved_printing(); + + // Abort the planner + planner_abort_hard(); + + // Reset the queue + cmdqueue_reset(); + cmdqueue_serial_disabled = false; + + // Reset the sd status + card.sdprinting = false; + card.closefile(); + + st_reset_timer(); + CRITICAL_SECTION_END; +} + // Stop: Emergency stop used by overtemp functions which allows recovery // // In addition to stopping the print, this prevents subsequent G[0-3] commands to be @@ -10166,15 +10191,27 @@ void kill(const char *full_screen_message, unsigned char id) // the addition of disabling the headers) could allow true recovery in the future. void Stop() { + // Keep disabling heaters disable_heater(); + + // Call the regular stop function if that's the first time during a new print if(Stopped == false) { Stopped = true; lcd_print_stop(); Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart + + // Eventually report the stopped status (though this is usually overridden by a + // higher-priority alert status message) SERIAL_ERROR_START; SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED); LCD_MESSAGERPGM(_T(MSG_STOPPED)); } + + // Return to the status screen to stop any pending menu action which could have been + // started by the user while stuck in the Stopped state. This also ensures the NEW + // error is immediately shown. + if (menu_menu != lcd_status_screen) + lcd_return_to_status(); } bool IsStopped() { return Stopped; }; diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index c753db19..f84d966e 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1381,33 +1381,15 @@ void temp_runaway_check(int _heater_id, float _target_temperature, float _curren void temp_runaway_stop(bool isPreheat, bool isBed) { - cancel_heatup = true; - quickStop(); - if (card.sdprinting) + disable_heater(); + Sound_MakeCustom(200,0,true); + + if (isPreheat) { - card.sdprinting = false; - card.closefile(); - } - // Clean the input command queue - // This is necessary, because in command queue there can be commands which would later set heater or bed temperature. - cmdqueue_reset(); - - disable_heater(); - disable_x(); - disable_y(); - disable_e0(); - disable_e1(); - disable_e2(); - manage_heater(); - lcd_update(0); - Sound_MakeCustom(200,0,true); - - if (isPreheat) - { - Stop(); - isBed ? LCD_ALERTMESSAGEPGM("BED PREHEAT ERROR") : LCD_ALERTMESSAGEPGM("PREHEAT ERROR"); + lcd_setalertstatuspgm(isBed? PSTR("BED PREHEAT ERROR") : PSTR("PREHEAT ERROR"), LCD_STATUS_CRITICAL); SERIAL_ERROR_START; isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)"); + #ifdef EXTRUDER_ALTFAN_DETECT altfanStatus.altfanOverride = 1; //full speed #endif //EXTRUDER_ALTFAN_DETECT @@ -1418,22 +1400,23 @@ void temp_runaway_stop(bool isPreheat, bool isBed) #else //FAN_SOFT_PWM analogWrite(FAN_PIN, 255); #endif //FAN_SOFT_PWM - fanSpeed = 255; - delayMicroseconds(2000); } else { - isBed ? LCD_ALERTMESSAGEPGM("BED THERMAL RUNAWAY") : LCD_ALERTMESSAGEPGM("THERMAL RUNAWAY"); + lcd_setalertstatuspgm(isBed? PSTR("BED THERMAL RUNAWAY") : PSTR("THERMAL RUNAWAY"), LCD_STATUS_CRITICAL); SERIAL_ERROR_START; isBed ? SERIAL_ERRORLNPGM(" HEATBED THERMAL RUNAWAY") : SERIAL_ERRORLNPGM(" HOTEND THERMAL RUNAWAY"); } + + Stop(); } #endif void disable_heater() { + cancel_heatup = true; setAllTargetHotends(0); setTargetBed(0); #if defined(TEMP_0_PIN) && TEMP_0_PIN > -1 diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 0bf94472..a2d1db2b 100755 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -220,7 +220,7 @@ FORCE_INLINE bool isCoolingBed() { #define CHECK_ALL_HEATERS (checkAllHotends()||(target_temperature_bed!=0)) int getHeaterPower(int heater); -void disable_heater(); +void disable_heater(); // Disable all heaters and unroll the temperature wait loop stack void updatePID(); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index fcce9b19..782fe7b3 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -7089,25 +7089,15 @@ static void lcd_sd_updir() void lcd_print_stop() { - if (!card.sdprinting) { - SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint + if (!IsStopped()) { + // Stop the print if we didn't already due to an error + if (!card.sdprinting) { + SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint + } + UnconditionalStop(); } - cmdqueue_serial_disabled = false; //for when canceling a print with a fancheck - - CRITICAL_SECTION_START; - - // Clear any saved printing state - cancel_saved_printing(); - - // Abort the planner/queue/sd - planner_abort_hard(); - cmdqueue_reset(); - card.sdprinting = false; - card.closefile(); - st_reset_timer(); - - CRITICAL_SECTION_END; + // TODO: all the following should be moved in the main marlin loop! #ifdef MESH_BED_LEVELING mbl.active = false; //also prevents undoing the mbl compensation a second time in the second planner_abort_hard() #endif @@ -7122,7 +7112,6 @@ void lcd_print_stop() lcd_commands_type = LcdCommands::Idle; lcd_cooldown(); //turns off heaters and fan; goes to status screen. - cancel_heatup = true; //unroll temperature wait loop stack. current_position[Z_AXIS] += 10; //lift Z. plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60);