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.
This commit is contained in:
Yuri D'Elia 2021-12-07 11:11:06 +01:00
parent 57abffda1b
commit a3915b57b9
5 changed files with 59 additions and 48 deletions

View File

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

View File

@ -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; };

View File

@ -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

View File

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

View File

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