Browse Source

Merge pull request #3311 from wavexx/temp_runaway_fixes

Ensure THERMAL RUNAWAY / temperature errors stay on-screen
DRracer 2 years ago
parent
commit
1a7a313cbf
6 changed files with 85 additions and 67 deletions
  1. 4 2
      Firmware/Marlin.h
  2. 40 2
      Firmware/Marlin_main.cpp
  3. 13 32
      Firmware/temperature.cpp
  4. 1 1
      Firmware/temperature.h
  5. 17 27
      Firmware/ultralcd.cpp
  6. 10 3
      Firmware/ultralcd.h

+ 4 - 2
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)
 

+ 40 - 2
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; };

+ 13 - 32
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)
-	{
-		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)
+    disable_heater();
+    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;
 

+ 1 - 1
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();
 
 

+ 17 - 27
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()

+ 10 - 3
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);