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);