diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index c2c5ca933..85c4dae10 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 2d53b1cd9..527df0a7e 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -294,7 +294,7 @@ uint8_t newFanSpeed = 0; bool powersupply = true; #endif -bool cancel_heatup = false ; +bool cancel_heatup = false; int8_t busy_state = NOT_BUSY; static long prev_busy_signal_ms = -1; @@ -6751,7 +6751,7 @@ Sigma_Exit: target_direction = isHeatingBed(); // true if heating, false if cooling KEEPALIVE_STATE(NOT_BUSY); - while ( (target_direction)&&(!cancel_heatup) ? (isHeatingBed()) : (isCoolingBed()&&(CooldownNoWait==false)) ) + while ( (!cancel_heatup) && (target_direction ? (isHeatingBed()) : (isCoolingBed()&&(CooldownNoWait==false))) ) { if(( _millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { @@ -10154,6 +10154,32 @@ 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(); + cancel_heatup = true; + + // 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 +10192,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 3765589b8..87ffc6149 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)"); + 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,16 +1400,16 @@ 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 @@ -1483,13 +1465,12 @@ uint8_t last_alert_sent_to_lcd = LCDALERT_NONE; //! update the current temperature error message //! @param type short error abbreviation (PROGMEM) -//! @param func optional lcd update function (lcd_setalertstatus when first setting the error) -void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*) = lcd_updatestatus) +void temp_update_messagepgm(const char* PROGMEM type) { char msg[LCD_WIDTH]; strcpy_P(msg, PSTR("Err: ")); strcat_P(msg, type); - (*func)(msg); + lcd_setalertstatus(msg, LCD_STATUS_CRITICAL); } //! signal a temperature error on both the lcd and serial @@ -1497,7 +1478,7 @@ void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*) //! @param e optional extruder index for hotend errors void temp_error_messagepgm(const char* PROGMEM type, uint8_t e = EXTRUDERS) { - temp_update_messagepgm(type, lcd_setalertstatus); + temp_update_messagepgm(type); SERIAL_ERROR_START; diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 0bf944724..b0e035d78 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 void updatePID(); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index dfaa04ca3..daac8d71c 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1399,7 +1399,6 @@ static void lcd_cooldown() setAllTargetHotends(0); setTargetBed(0); fanSpeed = 0; - eFilamentAction = FilamentAction::None; lcd_return_to_status(); } @@ -7090,24 +7089,11 @@ static void lcd_sd_updir() void lcd_print_stop() { if (!card.sdprinting) { - SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint + SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint } - 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; + UnconditionalStop(); + // 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 @@ -7118,11 +7104,11 @@ void lcd_print_stop() pause_time = 0; save_statistics(total_filament_used, t); + // reset current command lcd_commands_step = 0; 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); @@ -8604,7 +8590,7 @@ static bool check_file(const char* filename) { cmdqueue_serial_disabled = false; card.printingHasFinished(); - strncpy_P(lcd_status_message, _T(WELCOME_MSG), LCD_WIDTH); + lcd_setstatuspgm(_T(WELCOME_MSG)); lcd_finishstatus(); return result; } @@ -8813,18 +8799,22 @@ void lcd_updatestatus(const char *message){ lcd_draw_update = 1; } -void lcd_setalertstatuspgm(const char* message) +void lcd_setalertstatuspgm(const char* message, uint8_t severity) { - lcd_setstatuspgm(message); - lcd_status_message_level = 1; - lcd_return_to_status(); + if (severity > lcd_status_message_level) { + lcd_updatestatuspgm(message); + lcd_status_message_level = severity; + lcd_return_to_status(); + } } -void lcd_setalertstatus(const char* message) +void lcd_setalertstatus(const char* message, uint8_t severity) { - lcd_setstatus(message); - lcd_status_message_level = 1; - lcd_return_to_status(); + if (severity > lcd_status_message_level) { + lcd_updatestatus(message); + lcd_status_message_level = severity; + lcd_return_to_status(); + } } void lcd_reset_alert_level() diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 68b933d02..e3683576e 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -12,13 +12,20 @@ extern void menu_lcd_lcdupdate_func(void); void ultralcd_init(); void lcd_setstatus(const char* message); void lcd_setstatuspgm(const char* message); + +//! LCD status severities +#define LCD_STATUS_CRITICAL 2 //< Heater failure +#define LCD_STATUS_ALERT 1 //< Other hardware issue +#define LCD_STATUS_NONE 0 //< No alert message set + //! return to the main status screen and display the alert message //! Beware - it has sideeffects: //! - always returns the display to the main status screen //! - always makes lcd_reset (which is slow and causes flicker) -//! - does not update the message if there is already one (i.e. lcd_status_message_level > 0) -void lcd_setalertstatus(const char* message); -void lcd_setalertstatuspgm(const char* message); +//! - does not update the message if there is one with the same (or higher) severity present +void lcd_setalertstatus(const char* message, uint8_t severity = LCD_STATUS_ALERT); +void lcd_setalertstatuspgm(const char* message, uint8_t severity = LCD_STATUS_ALERT); + //! only update the alert message on the main status screen //! has no sideeffects, may be called multiple times void lcd_updatestatus(const char *message);