浏览代码

Show an error screen when try-unload fails to push filament into nozzle

This is a prototype implementation of having the ability to show an MMU error screen even for printer's errors (during an MMU operation).
Also, the retry count of unloads after failed load the extruder tube is now limited to ~3 attempts.

Technically, since this very error is not an MMU's one (MMU is just fine at this stage) but a printer's one I tried to hack the existing error-reporting infrastructure to handle such a case.
The original idea of this approach was suggested by @vintagePC
D.R.racer 1 年之前
父节点
当前提交
0a3517e8b2
共有 4 个文件被更改,包括 64 次插入22 次删除
  1. 45 21
      Firmware/mmu2.cpp
  2. 1 0
      Firmware/mmu2/error_codes.h
  3. 2 1
      Firmware/mmu2_protocol_logic.cpp
  4. 16 0
      Firmware/mmu2_protocol_logic.h

+ 45 - 21
Firmware/mmu2.cpp

@@ -275,29 +275,49 @@ bool MMU2::VerifyFilamentEnteredPTFE()
 
 void MMU2::ToolChangeCommon(uint8_t slot){
     for(;;) { // while not successfully fed into extruder's PTFE tube
-        for(;;) {
-            tool_change_extruder = slot;
-            logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in
-            if( manage_response(true, true) )
+        uint8_t retries = 3;
+        for(/*nothing*/; retries; --retries){
+            for(;;) {
+                tool_change_extruder = slot;
+                logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in
+                if( manage_response(true, true) )
+                    break;
+                // otherwise: failed to perform the command - unload first and then let it run again
+                IncrementMMUFails();
+
+                // just in case we stood in an error screen for too long and the hotend got cold
+                ResumeHotendTemp();
+                // if the extruder has been parked, it will get unparked once the ToolChange command finishes OK
+                // - so no ResumeUnpark() at this spot
+
+                unload();
+                // if we run out of retries, we must do something ... may be raise an error screen and allow the user to do something
+                // but honestly - if the MMU restarts during every toolchange,
+                // something else is seriously broken and stopping a print is probably our best option.
+            }
+            // reset current position to whatever the planner thinks it is
+            plan_set_e_position(current_position[E_AXIS]);
+            if (VerifyFilamentEnteredPTFE()){
                 break;
-            // otherwise: failed to perform the command - unload first and then let it run again
-            IncrementMMUFails();
-
-            // just in case we stood in an error screen for too long and the hotend got cold
-            ResumeHotendTemp();
-            // if the extruder has been parked, it will get unparked once the ToolChange command finishes OK
-            // - so no ResumeUnpark() at this spot
-
-            unload();
-            // if we run out of retries, we must do something ... may be raise an error screen and allow the user to do something
-            // but honestly - if the MMU restarts during every toolchange,
-            // something else is seriously broken and stopping a print is probably our best option.
+            } else { // Prepare a retry attempt
+                unload(); // @@TODO cut filament
+                // cut_filament(slot);
+            }
         }
-        // reset current position to whatever the planner thinks it is
-        plan_set_e_position(current_position[E_AXIS]);
-        if (VerifyFilamentEnteredPTFE()) break;
-        else { // Prepare a retry attempt
-            unload(); // TODO cut filament
+        if( retries ){
+            // we were successful in pushing the filament into the nozzle
+            break;
+        } else {
+            // failed autoretry, report an error by forcing a "printer" error into the MMU infrastructure - it is a hack to leverage existing code
+            logic.SetPrinterError(ErrorCode::TRY_LOAD_UNLOAD_FAILED);
+            SaveAndPark(true);
+            SaveHotendTemp(true);
+            // We only have to wait for the user to fix the issue and press "Retry".
+            // @@TODO Do we need to process the return value of manage_response?
+            manage_response(true, true);
+            logic.ClearPrinterError();
+            ResumeHotendTemp();
+            ResumeUnpark();
         }
     }
 
@@ -747,6 +767,7 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
             // now what :D ... big bad ... ramming, unload, retry the whole command originally issued
             return false;
         case VersionMismatch: // this basically means the MMU will be disabled until reconnected
+        case PrinterError:
             CheckUserInput();
             return true;
         case CommandError:
@@ -810,6 +831,9 @@ StepStatus MMU2::LogicStep(bool reportErrors) {
                 StopKeepPowered();
                 ReportError(ErrorCode::VERSION_MISMATCH, ErrorSourcePrinter);
                 break;
+            case PrinterError:
+                ReportError(logic.PrinterError(), ErrorSourcePrinter);
+                break;
             default:
                 break;
             }

+ 1 - 0
Firmware/mmu2/error_codes.h

@@ -56,6 +56,7 @@ enum class ErrorCode : uint_fast16_t {
 
     QUEUE_FULL = 0x802b, ///< E32811 internal logic error - attempt to move with a full queue
 
+    TRY_LOAD_UNLOAD_FAILED = 0x802b, ///< E32811 internal error of the printer - try-load-unload sequence detected missing filament -> failed load into the nozzle
     VERSION_MISMATCH = 0x802c, ///< E32812 internal error of the printer - incompatible version of the MMU FW
     PROTOCOL_ERROR = 0x802d, ///< E32813 internal error of the printer - communication with the MMU got garbled - protocol decoder couldn't decode the incoming messages
     MMU_NOT_RESPONDING = 0x802e, ///< E32814 internal error of the printer - communication with the MMU is not working

+ 2 - 1
Firmware/mmu2_protocol_logic.cpp

@@ -800,7 +800,8 @@ StepStatus ProtocolLogic::Step() {
     default:
         break;
     }
-    return currentStatus;
+    // special handling of explicit printer errors
+    return IsPrinterError() ? StepStatus::PrinterError : currentStatus;
 }
 
 uint8_t ProtocolLogic::CommandInProgress() const {

+ 16 - 0
Firmware/mmu2_protocol_logic.h

@@ -40,6 +40,7 @@ enum StepStatus : uint_fast8_t {
     CommandRejected,      ///< the MMU rejected the command due to some other command in progress, may be the user is operating the MMU locally (button commands)
     CommandError,         ///< the command in progress stopped due to unrecoverable error, user interaction required
     VersionMismatch,      ///< the MMU reports its firmware version incompatible with our implementation
+    PrinterError,         ///< printer's explicit error - MMU is fine, but the printer was unable to complete the requested operation
     CommunicationRecovered,
     ButtonPushed, ///< The MMU reported the user pushed one of its three buttons.
 };
@@ -141,6 +142,19 @@ public:
     inline uint8_t MmuFwVersionRevision() const {
         return mmuFwVersion[2];
     }
+
+    inline void SetPrinterError(ErrorCode ec){
+        explicitPrinterError = ec;
+    }
+    inline void ClearPrinterError(){
+        explicitPrinterError = ErrorCode::OK;
+    }
+    inline bool IsPrinterError()const {
+        return explicitPrinterError != ErrorCode::OK;
+    }
+    inline ErrorCode PrinterError() const {
+        return explicitPrinterError;
+    }
 #ifndef UNITTEST
 private:
 #endif
@@ -162,6 +176,8 @@ private:
     StepStatus SwitchFromIdleToCommand();
     void SwitchFromStartToIdle();
 
+    ErrorCode explicitPrinterError;
+
     enum class State : uint_fast8_t {
         Stopped,      ///< stopped for whatever reason
         InitSequence, ///< initial sequence running