瀏覽代碼

First pass, improving the error recovery.

VintagePC 2 年之前
父節點
當前提交
9a20c85a5d
共有 5 個文件被更改,包括 71 次插入44 次删除
  1. 39 35
      Firmware/mmu2.cpp
  2. 14 4
      Firmware/mmu2.h
  3. 2 1
      Firmware/mmu2_protocol.h
  4. 10 4
      Firmware/mmu2_reporting.cpp
  5. 6 0
      Firmware/mmu2_reporting.h

+ 39 - 35
Firmware/mmu2.cpp

@@ -91,7 +91,7 @@ MMU2::MMU2()
     , resume_hotend_temp(0)
     , logicStepLastStatus(StepStatus::Finished)
     , state(xState::Stopped)
-    , mmu_print_saved(false)
+    , mmu_print_saved(SavedState::None)
     , loadFilamentStarted(false)
     , loadingToNozzle(false)
 {
@@ -458,15 +458,14 @@ void MMU2::Home(uint8_t mode){
 }
 
 void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
-    if (!mmu_print_saved) { // First occurrence. Save current position, park print head, disable nozzle heater.
+    if (mmu_print_saved == SavedState::None) { // First occurrence. Save current position, park print head, disable nozzle heater.
         LogEchoEvent("Saving and parking");
         st_synchronize();
-
-        mmu_print_saved = true;
-
+      
         resume_hotend_temp = degTargetHotend(active_extruder);
 
         if (move_axes){
+            mmu_print_saved |= SavedState::ParkExtruder;
             // save current pos
             for(uint8_t i = 0; i < 3; ++i){
                 resume_position.xyz[i] = current_position[i];
@@ -487,6 +486,7 @@ void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
         }
 
         if (turn_off_nozzle){
+            mmu_print_saved |= SavedState::Cooldown;
             LogEchoEvent("Heater off");
             setAllTargetHotends(0);
         }
@@ -496,35 +496,37 @@ void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
     // gcode.reset_stepper_timeout();
 }
 
-void MMU2::ResumeAndUnPark(bool move_axes, bool turn_off_nozzle) {
-    if (mmu_print_saved) {
-        LogEchoEvent("Resuming print");
-
-        if (turn_off_nozzle && resume_hotend_temp) {
-            MMU2_ECHO_MSG("Restoring hotend temperature ");
-            SERIAL_ECHOLN(resume_hotend_temp);
-            setTargetHotend(resume_hotend_temp, active_extruder);
-            waitForHotendTargetTemp(3000, []{
-                lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature...")); // better report the event and let the GUI do its work somewhere else
-            });
-            LogEchoEvent("Hotend temperature reached");
-            lcd_update_enable(true); // temporary hack to stop this locking the printer...
-        }
+void MMU2::ResumeHotendTemp() {
+    if ((mmu_print_saved & SavedState::Cooldown) && resume_hotend_temp) {
+        LogEchoEvent("Resuming Temp");
+        MMU2_ECHO_MSG("Restoring hotend temperature ");
+        SERIAL_ECHOLN(resume_hotend_temp);
+        setTargetHotend(resume_hotend_temp, active_extruder);
+        lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature...")); // better report the event and let the GUI do its work somewhere else
+        ReportErrorHookSensorLineRender();
+        waitForHotendTargetTemp(1000, []{
+            ReportErrorHookDynamicRender();
+        });
+        LogEchoEvent("Hotend temperature reached");
+        lcd_update_enable(true); // temporary hack to stop this locking the printer...
+    }
+}
 
-        if (move_axes) {
-            LogEchoEvent("Resuming XYZ");
+void MMU2::ResumeUnpark()
+{
+    if (mmu_print_saved & SavedState::ParkExtruder) {
+        LogEchoEvent("Resuming XYZ");
 
-            current_position[X_AXIS] = resume_position.xyz[X_AXIS];
-            current_position[Y_AXIS] = resume_position.xyz[Y_AXIS];
-            plan_buffer_line_curposXYZE(NOZZLE_PARK_XY_FEEDRATE);
-            st_synchronize();
-            
-            current_position[Z_AXIS] = resume_position.xyz[Z_AXIS];
-            plan_buffer_line_curposXYZE(NOZZLE_PARK_Z_FEEDRATE);
-            st_synchronize();
-        } else {
-            LogEchoEvent("NOT resuming XYZ");
-        }
+        current_position[X_AXIS] = resume_position.xyz[X_AXIS];
+        current_position[Y_AXIS] = resume_position.xyz[Y_AXIS];
+        plan_buffer_line_curposXYZE(NOZZLE_PARK_XY_FEEDRATE);
+        st_synchronize();
+        
+        current_position[Z_AXIS] = resume_position.xyz[Z_AXIS];
+        plan_buffer_line_curposXYZE(NOZZLE_PARK_Z_FEEDRATE);
+        st_synchronize();
+    } else {
+        LogEchoEvent("NOT resuming XYZ");
     }
 }
 
@@ -534,6 +536,7 @@ void MMU2::CheckUserInput(){
     case Left:
     case Middle:
     case Right:
+        ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else...
         Button(btn);
         break;
     case RestartMMU:
@@ -559,7 +562,7 @@ void MMU2::CheckUserInput(){
 /// But - in case of an error, the command is not yet finished, but we must react accordingly - move the printhead elsewhere, stop heating, eat a cat or so.
 /// That's what's being done here...
 void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
-    mmu_print_saved = false;
+    mmu_print_saved = SavedState::None;
 
     KEEPALIVE_STATE(PAUSED_FOR_USER);
 
@@ -577,7 +580,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
         case Finished: 
             // command/operation completed, let Marlin continue its work
             // the E may have some more moves to finish - wait for them
-            ResumeAndUnPark(move_axes, turn_off_nozzle); // This is needed here otherwise recovery doesn't work.
+            ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved.
             st_synchronize(); 
             return;
         case VersionMismatch: // this basically means the MMU will be disabled until reconnected
@@ -591,7 +594,8 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
             break;
         case CommunicationRecovered: // @@TODO communication recovered and may be an error recovered as well
             // may be the logic layer can detect the change of state a respond with one "Recovered" to be handled here
-            ResumeAndUnPark(move_axes, turn_off_nozzle);
+            ResumeHotendTemp();
+            ResumeUnpark();
             break;
         case Processing: // wait for the MMU to respond
         default:

+ 14 - 4
Firmware/mmu2.h

@@ -58,6 +58,13 @@ public:
         ResetPin = 1, ///< trigger the reset pin of the MMU
         CutThePower = 2 ///< power off and power on (that includes +5V and +24V power lines)
     };
+
+    /// Saved print state on error.
+    enum SavedState: uint8_t {
+        None = 0, // No state saved. 
+        ParkExtruder = 1, // The extruder was parked. 
+        Cooldown = 2, // The extruder was allowed to cool.
+    };
     
     /// Perform a reset of the MMU
     /// @param level physical form of the reset
@@ -143,7 +150,7 @@ public:
     bool is_mmu_error_monitor_active;
 
     /// Method to read-only mmu_print_saved
-    bool MMU_PRINT_SAVED() const { return mmu_print_saved; }
+    bool MMU_PRINT_SAVED() const { return mmu_print_saved != SavedState::None; }
 
 private:
     /// Perform software self-reset of the MMU (sends an X0 command)
@@ -193,8 +200,11 @@ private:
     /// Save print and park the print head
     void SaveAndPark(bool move_axes, bool turn_off_nozzle);
 
-    /// Resume print (unpark, turn on heating etc.)
-    void ResumeAndUnPark(bool move_axes, bool turn_off_nozzle);
+    /// Resume hotend temperature, if it was cooled. Safe to call if we aren't saved.
+    void ResumeHotendTemp();
+
+    /// Resume position, if the extruder was parked. Safe to all if state was not saved.
+    void ResumeUnpark();
 
     /// Check for any button/user input coming from the printer's UI
     void CheckUserInput();
@@ -220,7 +230,7 @@ private:
     
     enum xState state;
 
-    bool mmu_print_saved;
+    uint8_t mmu_print_saved;
     bool loadFilamentStarted;
     
     friend struct LoadingToNozzleRAII;

+ 2 - 1
Firmware/mmu2_protocol.h

@@ -37,7 +37,8 @@ enum class ResponseMsgParamCodes : uint8_t {
     Error = 'E',
     Finished = 'F',
     Accepted = 'A',
-    Rejected = 'R'
+    Rejected = 'R', 
+    Button = 'B' // the MMU registered a button press and is sending it to the printer for processing
 };
 
 /// A request message - requests are being sent by the printer into the MMU.

+ 10 - 4
Firmware/mmu2_reporting.cpp

@@ -27,7 +27,7 @@ void EndReport(CommandInProgress cip, uint16_t ec) {
  * @brief Renders any characters that will be updated live on the MMU error screen.
  *Currently, this is FINDA and Filament Sensor status and Extruder temperature.
  */
-static void ReportErrorHookDynamicRender(void)
+extern void ReportErrorHookDynamicRender(void)
 {
     lcd_set_cursor(3, 2);
     lcd_printf_P(PSTR("%d"), mmu2.FindaDetectsFilament());
@@ -78,17 +78,23 @@ static void ReportErrorHookStaticRender(uint8_t ei) {
     lcd_update_enable(false);
     lcd_clear();
 
+    ReportErrorHookSensorLineRender();
+
     // Print title and header
     lcd_printf_P(PSTR("%.20S\nprusa3d.com/ERR04%hu"), _T(PrusaErrorTitle(ei)), PrusaErrorCode(ei) );
 
+    // Render the choices
+    lcd_show_choices_prompt_P(two_choices ? LCD_LEFT_BUTTON_CHOICE : LCD_MIDDLE_BUTTON_CHOICE, _T(PrusaErrorButtonTitle(button_op_middle)), _T(two_choices ? PrusaErrorButtonMore() : PrusaErrorButtonTitle(button_op_right)), two_choices ? 10 : 7, two_choices ? nullptr : _T(PrusaErrorButtonMore()));
+}
+
+extern void ReportErrorHookSensorLineRender()
+{
     // Render static characters in third line
     lcd_set_cursor(0, 2);
     lcd_printf_P(PSTR("FI:  FS:    >  %c   %c"), LCD_STR_THERMOMETER[0], LCD_STR_DEGREE[0]);
-
-    // Render the choices
-    lcd_show_choices_prompt_P(two_choices ? LCD_LEFT_BUTTON_CHOICE : LCD_MIDDLE_BUTTON_CHOICE, _T(PrusaErrorButtonTitle(button_op_middle)), _T(two_choices ? PrusaErrorButtonMore() : PrusaErrorButtonTitle(button_op_right)), two_choices ? 10 : 7, two_choices ? nullptr : _T(PrusaErrorButtonMore()));
 }
 
+
 /**
  * @brief Monitors the LCD button selection without blocking MMU communication
  * @param[in] ei Error code index

+ 6 - 0
Firmware/mmu2_reporting.h

@@ -28,6 +28,12 @@ void ReportErrorHook(uint16_t ec);
 /// Called when the MMU sends operation progress update
 void ReportProgressHook(CommandInProgress cip, uint16_t ec);
 
+/// Remders the sensor status line. Also used by the "resume temperature" screen.
+void ReportErrorHookDynamicRender();
+
+/// Renders the static part of the sensor state line. Also used by "resuming temperature screen"
+void ReportErrorHookSensorLineRender();
+
 /// @returns true if the MMU is communicating and available
 /// can change at runtime
 bool MMUAvailable();