Ver código fonte

Fixes from tests

- introduce Cut Filament
- limit retries try-unload
- fix waiting in "Load to extruder failed" error screen
- add LOAD_TO_EXTRUDER_FAILED error definition
D.R.racer 1 ano atrás
pai
commit
d4f0f363cd

+ 60 - 44
Firmware/mmu2.cpp

@@ -273,53 +273,53 @@ bool MMU2::VerifyFilamentEnteredPTFE()
     }
 }
 
-void MMU2::ToolChangeCommon(uint8_t slot){
-    for(;;) { // while not successfully fed into extruder's PTFE tube
-        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()){
+bool MMU2::ToolChangeCommonOnce(uint8_t slot){
+    static_assert(MAX_RETRIES > 1); // need >1 retries to do the cut in the last attempt
+    for(uint8_t retries = MAX_RETRIES; 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;
-            } else { // Prepare a retry attempt
-                unload(); // @@TODO cut filament
-                // cut_filament(slot);
-            }
-        }
-        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::LOAD_TO_EXTRUDER_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();
+            // 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();
-            ResumeUnpark();
+            // 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()){
+            return true; // success
+        } else { // Prepare a retry attempt
+            unload();
+            if( retries == 1 && eeprom_read_byte((uint8_t*)EEPROM_MMU_CUTTER_ENABLED) == EEPROM_MMU_CUTTER_ENABLED_enabled){
+                cut_filament(slot); // try cutting filament tip at the last attempt
+            }
         }
     }
+    return false; // couldn't accomplish the task
+}
+
+void MMU2::ToolChangeCommon(uint8_t slot){
+    while( ! ToolChangeCommonOnce(slot) ){ // while not successfully fed into extruder's PTFE tube
+        // 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::LOAD_TO_EXTRUDER_FAILED);
+        SaveAndPark(true);
+        SaveHotendTemp(true);
+        // We only have to wait for the user to fix the issue and press "Retry".
+        // Please see CheckUserInput() for details how we "leave" manage_response.
+        // If manage_response returns false at this spot (MMU operation interrupted aka MMU reset)
+        // we can safely continue because the MMU is not doing an operation now.
+        manage_response(true, true);
+    }
 
     extruder = slot; //filament change is finished
     SpoolJoin::spooljoin.setSlot(slot);
@@ -686,6 +686,11 @@ void MMU2::CheckUserInput(){
         SERIAL_ECHOPGM("CheckUserInput-btnLMR ");
         SERIAL_ECHOLN(btn);
         ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else...
+
+        // In case of LOAD_TO_EXTRUDER_FAILED sending a button into the MMU has an interesting side effect
+        // - it triggers the standalone LoadFilament function on the current active slot.
+        // Considering the fact, that we are recovering from a failed load to extruder, this side effect is actually quite beneficial
+        // - it checks if the filament is correctly loaded in the MMU (we assume the user was playing with the filament to recover from the failed load)
         Button(btn);
 
         // A quick hack: for specific error codes move the E-motor every time.
@@ -696,6 +701,13 @@ void MMU2::CheckUserInput(){
         case ErrorCode::FSENSOR_TOO_EARLY:
             HelpUnloadToFinda();
             break;
+        case ErrorCode::LOAD_TO_EXTRUDER_FAILED:
+            // A horrible hack - clear the explicit printer error allowing manage_response to recover on MMU's Finished state
+            // Moreover - if the MMU is currently doing something (like the LoadFilament - see comment above)
+            // we'll actually wait for it automagically in manage_response and after it finishes correctly,
+            // we'll issue another command (like toolchange)
+            logic.ClearPrinterError();
+            break;
         default:
             break;
         }
@@ -767,9 +779,13 @@ 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 PrinterError:
+            CheckUserInput();
+            // if button pressed "Done", return true, otherwise stay within manage_response
+            // Please see CheckUserInput() for details how we "leave" manage_response
+            break;
         case CommandError:
         case CommunicationTimeout:
         case ProtocolError:

+ 1 - 0
Firmware/mmu2.h

@@ -294,6 +294,7 @@ private:
 
     /// Common processing of pushing filament into the extruder - shared by tool_change, load_to_nozzle and probably others
     void ToolChangeCommon(uint8_t slot);
+    bool ToolChangeCommonOnce(uint8_t slot);
 
     void HelpUnloadToFinda();
 

+ 1 - 2
Firmware/mmu2/error_codes.h

@@ -54,9 +54,8 @@ enum class ErrorCode : uint_fast16_t {
     MOVE_IDLER_FAILED = MOVE_FAILED | TMC_IDLER_BIT, ///< E33033 the Idler was unable to move - unused at the time of creation, but added for completeness
     MOVE_PULLEY_FAILED = MOVE_FAILED | TMC_PULLEY_BIT, ///< E32841 the Pulley was unable to move - unused at the time of creation, but added for completeness
 
+    LOAD_TO_EXTRUDER_FAILED = 0x802a, ///< E32811 internal error of the printer - try-load-unload sequence detected missing filament -> failed load into the nozzle
     QUEUE_FULL = 0x802b, ///< E32811 internal logic error - attempt to move with a full queue
-
-    LOAD_TO_EXTRUDER_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

+ 7 - 0
Firmware/mmu2/errors_list.h

@@ -23,6 +23,7 @@ typedef enum : uint16_t {
     ERR_MECHANICAL_PULLEY_CANNOT_MOVE = 105,
     ERR_MECHANICAL_FSENSOR_TOO_EARLY = 106,
     ERR_MECHANICAL_INSPECT_FINDA = 107,
+    ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED = 108,
     ERR_MECHANICAL_SELECTOR_CANNOT_HOME = 115,
     ERR_MECHANICAL_SELECTOR_CANNOT_MOVE = 116,
     ERR_MECHANICAL_IDLER_CANNOT_HOME = 125,
@@ -87,6 +88,7 @@ static const constexpr uint16_t errorCodes[] PROGMEM = {
     ERR_MECHANICAL_PULLEY_CANNOT_MOVE,
     ERR_MECHANICAL_FSENSOR_TOO_EARLY,
     ERR_MECHANICAL_INSPECT_FINDA,
+    ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED,
     ERR_MECHANICAL_SELECTOR_CANNOT_HOME,
     ERR_MECHANICAL_SELECTOR_CANNOT_MOVE,
     ERR_MECHANICAL_IDLER_CANNOT_HOME,
@@ -130,6 +132,7 @@ static const char MSG_TITLE_FSENSOR_DIDNT_GO_OFF[] PROGMEM_I1    = ISTR("FSENSOR
 static const char MSG_TITLE_PULLEY_CANNOT_MOVE[] PROGMEM_I1      = ISTR("PULLEY CANNOT MOVE"); ////MSG_TITLE_PULLEY_CANNOT_MOVE c=20
 static const char MSG_TITLE_FSENSOR_TOO_EARLY[] PROGMEM_I1       = ISTR("FSENSOR TOO EARLY"); ////MSG_TITLE_FSENSOR_TOO_EARLY c=20
 static const char MSG_TITLE_INSPECT_FINDA[] PROGMEM_I1           = ISTR("INSPECT FINDA"); ////MSG_TITLE_INSPECT_FINDA c=20
+static const char MSG_TITLE_LOAD_TO_EXTRUDER_FAILED[] PROGMEM_I1 = ISTR("LOAD TO EXTR. FAILED"); ////MSG_TITLE_LOAD_TO_EXTRUDER_FAILED c=20
 static const char MSG_TITLE_SELECTOR_CANNOT_MOVE[] PROGMEM_I1    = ISTR("SELECTOR CANNOT MOVE"); ////MSG_TITLE_SELECTOR_CANNOT_MOVE c=20
 static const char MSG_TITLE_SELECTOR_CANNOT_HOME[] PROGMEM_I1    = ISTR("SELECTOR CANNOT HOME"); ////MSG_TITLE_SELECTOR_CANNOT_HOME c=20
 static const char MSG_TITLE_IDLER_CANNOT_MOVE[] PROGMEM_I1       = ISTR("IDLER CANNOT MOVE"); ////MSG_TITLE_IDLER_CANNOT_MOVE c=20
@@ -170,6 +173,7 @@ static const char * const errorTitles [] PROGMEM = {
     _R(MSG_TITLE_PULLEY_CANNOT_MOVE),
     _R(MSG_TITLE_FSENSOR_TOO_EARLY),
     _R(MSG_TITLE_INSPECT_FINDA),
+    _R(MSG_TITLE_LOAD_TO_EXTRUDER_FAILED),
     _R(MSG_TITLE_SELECTOR_CANNOT_HOME),
     _R(MSG_TITLE_SELECTOR_CANNOT_MOVE),
     _R(MSG_TITLE_IDLER_CANNOT_HOME),
@@ -214,6 +218,7 @@ static const char MSG_DESC_FSENSOR_DIDNT_GO_OFF[] PROGMEM_I1 = ISTR("Filament se
 static const char MSG_DESC_PULLEY_STALLED[] PROGMEM_I1 = ISTR("Pulley motor stalled. Ensure the pulley can move and check the wiring."); ////MSG_DESC_PULLEY_STALLED c=20 r=8
 static const char MSG_DESC_FSENSOR_TOO_EARLY[] PROGMEM_I1 = ISTR("Filament sensor triggered too early while loading to extruder. Check there isn't anything stuck in PTFE tube. Check that sensor reads properly."); ////MSG_DESC_FSENSOR_TOO_EARLY c=20 r=8
 static const char MSG_DESC_INSPECT_FINDA[] PROGMEM_I1 = ISTR("Selector can't move due to FINDA detecting a filament. Make sure no filament is in selector and FINDA works properly."); ////MSG_DESC_INSPECT_FINDA c=20 r=8
+static const char MSG_DESC_LOAD_TO_EXTRUDER_FAILED[] PROGMEM_I1 = ISTR("@@TODO - load to extruder failed."); ////MSG_DESC_LOAD_TO_EXTRUDER_FAILED c=20 r=8
 static const char MSG_DESC_SELECTOR_CANNOT_HOME[] PROGMEM_I1 = ISTR("The Selector cannot home properly. Check for anything blocking its movement."); ////MSG_DESC_SELECTOR_CANNOT_HOME c=20 r=8
 static const char MSG_DESC_CANNOT_MOVE[] PROGMEM_I1 = ISTR("Can't move Selector or Idler."); /////MSG_DESC_CANNOT_MOVE c=20 r=4
 //static const char MSG_DESC_SELECTOR_CANNOT_MOVE[] PROGMEM_I1 = ISTR("The Selector cannot move. Check for anything blocking its movement. Check the wiring is correct.");
@@ -255,6 +260,7 @@ static const char * const errorDescs[] PROGMEM = {
     _R(MSG_DESC_PULLEY_STALLED),
     _R(MSG_DESC_FSENSOR_TOO_EARLY),
     _R(MSG_DESC_INSPECT_FINDA),
+    _R(MSG_DESC_LOAD_TO_EXTRUDER_FAILED),
     _R(MSG_DESC_SELECTOR_CANNOT_HOME),
     _R(MSG_DESC_CANNOT_MOVE),
     _R(MSG_DESC_IDLER_CANNOT_HOME),
@@ -332,6 +338,7 @@ static const uint8_t errorButtons[] PROGMEM = {
     Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//PULLEY_STALLED
     Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//FSENSOR_TOO_EARLY
     Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//INSPECT_FINDA
+    Btns(ButtonOperations::Continue, ButtonOperations::NoOperation),//LOAD_TO_EXTRUDER_FAILED
     Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//SELECTOR_CANNOT_HOME
     Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//SELECTOR_CANNOT_MOVE
     Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//IDLER_CANNOT_HOME

+ 10 - 1
Firmware/mmu2_error_converter.cpp

@@ -49,6 +49,8 @@ uint8_t PrusaErrorCodeIndex(uint16_t ec) {
         return FindErrorIndex(ERR_MECHANICAL_FSENSOR_TOO_EARLY);
     case (uint16_t)ErrorCode::FINDA_FLICKERS:
         return FindErrorIndex(ERR_MECHANICAL_INSPECT_FINDA);
+    case (uint16_t)ErrorCode::LOAD_TO_EXTRUDER_FAILED:
+        return FindErrorIndex(ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED);
 
     case (uint16_t)ErrorCode::STALLED_PULLEY:
     case (uint16_t)ErrorCode::MOVE_PULLEY_FAILED:
@@ -222,7 +224,14 @@ Buttons ButtonAvailable(uint16_t ec) {
             break;
         }
         break;
-        
+    case ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED:
+        switch (buttonSelectedOperation) {
+        case ButtonOperations::Continue: // User solved the serious mechanical problem by hand - there is no other way around
+            return Middle;
+        default:
+            break;
+        }
+        break;
     case ERR_TEMPERATURE_PULLEY_WARNING_TMC_TOO_HOT:
     case ERR_TEMPERATURE_SELECTOR_WARNING_TMC_TOO_HOT:
     case ERR_TEMPERATURE_IDLER_WARNING_TMC_TOO_HOT:

+ 2 - 1
Firmware/mmu2_protocol_logic.cpp

@@ -496,7 +496,8 @@ StepStatus ProtocolLogic::IdleStep() {
 }
 
 ProtocolLogic::ProtocolLogic(MMU2Serial *uart, uint8_t extraLoadDistance)
-    : currentScope(Scope::Stopped)
+    : explicitPrinterError(ErrorCode::OK)
+    , currentScope(Scope::Stopped)
     , scopeState(ScopeState::Ready)
     , plannedRq(RequestMsgCodes::unknown, 0)
     , lastUARTActivityMs(0)