Browse Source

Refactor ToolChange+LoadToNozzle

Add basic infrastructure for handling of repeated commands until they finish correctly.
D.R.racer 2 years ago
parent
commit
e414413b2e
2 changed files with 50 additions and 66 deletions
  1. 47 66
      Firmware/mmu2.cpp
  2. 3 0
      Firmware/mmu2.h

+ 47 - 66
Firmware/mmu2.cpp

@@ -230,31 +230,26 @@ void MMU2::mmu_loop() {
     avoidRecursion = false;
 }
 
-void __attribute__((noinline)) MMU2::mmu_loop_inner(bool reportErrors)
-{
+void __attribute__((noinline)) MMU2::mmu_loop_inner(bool reportErrors) {
     logicStepLastStatus = LogicStep(reportErrors); // it looks like the mmu_loop doesn't need to be a blocking call
 
-    if (is_mmu_error_monitor_active){
+    if (is_mmu_error_monitor_active) {
         // Call this every iteration to keep the knob rotation responsive
         // This includes when mmu_loop is called within manage_response
         ReportErrorHook((uint16_t)lastErrorCode);
     }
 }
 
-void MMU2::CheckFINDARunout()
-{
+void MMU2::CheckFINDARunout() {
     // Check for FINDA filament runout
     if (!FindaDetectsFilament() && CHECK_FSENSOR) {
         SERIAL_ECHOLNPGM("FINDA filament runout!");
         stop_and_save_print_to_ram(0, 0);
         restore_print_from_ram_and_continue(0);
-        if (SpoolJoin::spooljoin.isSpoolJoinEnabled() && get_current_tool() != (uint8_t)FILAMENT_UNKNOWN) // Can't auto if F=?
-        {
-            enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command
-        }
-        else
-        {
-            enquecommand_front_P(PSTR("M600")); //save print and run M600 command
+        if (SpoolJoin::spooljoin.isSpoolJoinEnabled() && get_current_tool() != (uint8_t)FILAMENT_UNKNOWN){ // Can't auto if F=?
+            enquecommand_front_P(PSTR("M600 AUTO")); // save print and run M600 command
+        } else {
+            enquecommand_front_P(PSTR("M600")); // save print and run M600 command
         }
     }
 }
@@ -303,28 +298,48 @@ void MMU2::ResetRetryAttempts(){
     retryAttempts = MAX_RETRIES;
 }
 
-void MMU2::DecrementRetryAttempts(){
-    if (inAutoRetry && retryAttempts)
-    {
+void MMU2::DecrementRetryAttempts() {
+    if (inAutoRetry && retryAttempts) {
         SERIAL_ECHOLNPGM("DecrementRetryAttempts");
         retryAttempts--;
     }
 }
 
-void MMU2::update_tool_change_counter_eeprom()
-{
-    uint32_t toolchanges = eeprom_read_dword((uint32_t*)EEPROM_TOTAL_TOOLCHANGE_COUNT);
+void MMU2::update_tool_change_counter_eeprom() {
+    uint32_t toolchanges = eeprom_read_dword((uint32_t *)EEPROM_TOTAL_TOOLCHANGE_COUNT);
     eeprom_update_dword((uint32_t *)EEPROM_TOTAL_TOOLCHANGE_COUNT, toolchanges + (uint32_t)read_toolchange_counter());
     reset_toolchange_counter();
 }
 
+void MMU2::MMU2::ToolChangeCommon(uint8_t index){
+    tool_change_extruder = index;
+    do {
+        for(;;) {
+            logic.ToolChange(index); // 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
+            unload();
+        }
+        // reset current position to whatever the planner thinks it is
+        plan_set_e_position(current_position[E_AXIS]);
+    } while (0); // while not successfully fed into etruder's PTFE tube
+
+    extruder = index; //filament change is finished
+    SpoolJoin::spooljoin.setSlot(index);
+
+    // @@TODO really report onto the serial? May be for the Octoprint? Not important now
+    //        SERIAL_ECHO_START();
+    //        SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(extruder));
+    increment_tool_change_counter();
+}
+
 bool MMU2::tool_change(uint8_t index) {
     if( ! WaitForMMUReady())
         return false;
 
     if (index != extruder) {
-        if (!IS_SD_PRINTING && !usb_timer.running())
-        {
+        if (!IS_SD_PRINTING && !usb_timer.running()) {
             // If Tcodes are used manually through the serial
             // we need to unload manually as well
             unload();
@@ -332,25 +347,8 @@ bool MMU2::tool_change(uint8_t index) {
 
         ReportingRAII rep(CommandInProgress::ToolChange);
         FSensorBlockRunout blockRunout;
-
         st_synchronize();
-
-        tool_change_extruder = index;
-        logic.ToolChange(index); // let the MMU pull the filament out and push a new one in
-        if( ! manage_response(true, true) ){
-            // @@TODO failed to perform the command - retry
-            ;
-        }
-        // reset current position to whatever the planner thinks it is
-        plan_set_e_position(current_position[E_AXIS]);
-
-        extruder = index; //filament change is finished
-        SpoolJoin::spooljoin.setSlot(index);
-
-        // @@TODO really report onto the serial? May be for the Octoprint? Not important now
-        //        SERIAL_ECHO_START();
-        //        SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(extruder));
-        increment_tool_change_counter();
+        ToolChangeCommon(index);
     }
     return true;
 }
@@ -437,11 +435,12 @@ bool MMU2::unload() {
         ReportingRAII rep(CommandInProgress::UnloadFilament);
         filament_ramming();
 
-        logic.UnloadFilament();
-        if( ! manage_response(false, true) ){
-            // @@TODO failed to perform the command - retry
-            ;
-        }
+        // we assume the printer managed to relieve filament tip from the gears,
+        // so repeating that part in case of an MMU restart is not necessary
+        do {
+            logic.UnloadFilament();
+        } while( ! manage_response(false, true) );
+
         Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
 
         // no active tool
@@ -489,11 +488,10 @@ bool MMU2::load_filament(uint8_t index) {
     FullScreenMsg(_T(MSG_LOADING_FILAMENT), index);
 
     ReportingRAII rep(CommandInProgress::LoadFilament);
-    logic.LoadFilament(index);
-    if( ! manage_response(false, false) ){
-        // @@TODO failed to perform the command - retry
-        ;
-    }
+    do {
+        logic.LoadFilament(index);
+    } while( ! manage_response(false, false) );
+
     Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
 
     lcd_update_enable(true);
@@ -529,28 +527,11 @@ bool MMU2::load_filament_to_nozzle(uint8_t index) {
             filament_ramming();
         }
 
-        tool_change_extruder = index;
-        logic.ToolChange(index);
-        if( ! manage_response(true, true) ){
-            // @@TODO failed to perform the command - retry
-            ;
-        }
-
-        // The MMU's idler is disengaged at this point
-        // That means the MK3/S now has fully control
-
-        // reset current position to whatever the planner thinks it is
-        st_synchronize();
-        plan_set_e_position(current_position[E_AXIS]);
+        ToolChangeCommon(index);
 
         // Finish loading to the nozzle with finely tuned steps.
         execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, sizeof(load_to_nozzle_sequence) / sizeof (load_to_nozzle_sequence[0]));
-
-        extruder = index;
-        SpoolJoin::spooljoin.setSlot(index);
-
         Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
-        increment_tool_change_counter();
     }
     lcd_update_enable(true);
     return true;

+ 3 - 0
Firmware/mmu2.h

@@ -284,6 +284,9 @@ private:
     /// @returns false if the MMU is not ready to perform the command (for whatever reason)
     bool WaitForMMUReady();
 
+    /// Common processing of pushing filament into the extruder - shared by tool_change, load_to_nozzle and probably others
+    void ToolChangeCommon(uint8_t index);
+
     ProtocolLogic logic; ///< implementation of the protocol logic layer
     uint8_t extruder; ///< currently active slot in the MMU ... somewhat... not sure where to get it from yet
     uint8_t tool_change_extruder; ///< only used for UI purposes