瀏覽代碼

🐛 Fix Tool Change priming (#21142)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
Robert Brenckman 2 年之前
父節點
當前提交
6ee34331b7
No account linked to committer's email address

+ 9
- 5
Marlin/Configuration_adv.h 查看文件

@@ -2494,12 +2494,16 @@
2494 2494
     #define TOOLCHANGE_FS_FAN_SPEED          255  // 0-255
2495 2495
     #define TOOLCHANGE_FS_FAN_TIME            10  // (seconds)
2496 2496
 
2497
-    // Swap uninitialized extruder (using TOOLCHANGE_FS_PRIME_SPEED feedrate)
2498
-    // (May break filament if not retracted beforehand.)
2499
-    //#define TOOLCHANGE_FS_INIT_BEFORE_SWAP
2497
+    // Use TOOLCHANGE_FS_PRIME_SPEED feedrate the first time each extruder is primed
2498
+    //#define TOOLCHANGE_FS_SLOW_FIRST_PRIME
2500 2499
 
2501
-    // Prime on the first T0 (For other tools use TOOLCHANGE_FS_INIT_BEFORE_SWAP)
2502
-    // Enable with M217 V1 before printing to avoid unwanted priming on host connect
2500
+    /**
2501
+     * Prime T0 the first time T0 is sent to the printer:
2502
+     *  [ Power-On -> T0 { Activate & Prime T0 } -> T1 { Retract T0, Activate & Prime T1 } ]
2503
+     * If disabled, no priming on T0 until switching back to T0 from another extruder:
2504
+     *  [ Power-On -> T0 { T0 Activated } -> T1 { Activate & Prime T1 } -> T0 { Retract T1, Activate & Prime T0 } ]
2505
+     * Enable with M217 V1 before printing to avoid unwanted priming on host connect.
2506
+     */
2503 2507
     //#define TOOLCHANGE_FS_PRIME_FIRST_USED
2504 2508
 
2505 2509
     /**

+ 30
- 30
Marlin/src/gcode/config/M217.cpp 查看文件

@@ -34,31 +34,31 @@
34 34
 #include "../../MarlinCore.h" // for SP_X_STR, etc.
35 35
 
36 36
 /**
37
- * M217 - Set SINGLENOZZLE toolchange parameters
37
+ * M217 - Set toolchange parameters
38 38
  *
39 39
  *  // Tool change command
40 40
  *  Q           Prime active tool and exit
41 41
  *
42 42
  *  // Tool change settings
43
- *  S[linear]   Swap length
44
- *  B[linear]   Extra Swap length
45
- *  E[linear]   Prime length
46
- *  P[linear/m] Prime speed
47
- *  R[linear/m] Retract speed
48
- *  U[linear/m] UnRetract speed
49
- *  V[linear]   0/1 Enable auto prime first extruder used
50
- *  W[linear]   0/1 Enable park & Z Raise
51
- *  X[linear]   Park X (Requires TOOLCHANGE_PARK)
52
- *  Y[linear]   Park Y (Requires TOOLCHANGE_PARK)
53
- *  I[linear]   Park I (Requires TOOLCHANGE_PARK and NUM_AXES >= 4)
54
- *  J[linear]   Park J (Requires TOOLCHANGE_PARK and NUM_AXES >= 5)
55
- *  K[linear]   Park K (Requires TOOLCHANGE_PARK and NUM_AXES >= 6)
56
- *  C[linear]   Park U (Requires TOOLCHANGE_PARK and NUM_AXES >= 7)
57
- *  H[linear]   Park V (Requires TOOLCHANGE_PARK and NUM_AXES >= 8)
58
- *  O[linear]   Park W (Requires TOOLCHANGE_PARK and NUM_AXES >= 9)
59
- *  Z[linear]   Z Raise
60
- *  F[linear]   Fan Speed 0-255
61
- *  G[linear/s] Fan time
43
+ *  S[linear]     Swap length
44
+ *  B[linear]     Extra Swap resume length
45
+ *  E[linear]     Extra Prime length (as used by M217 Q)
46
+ *  P[linear/min] Prime speed
47
+ *  R[linear/min] Retract speed
48
+ *  U[linear/min] UnRetract speed
49
+ *  V[linear]     0/1 Enable auto prime first extruder used
50
+ *  W[linear]     0/1 Enable park & Z Raise
51
+ *  X[linear]     Park X (Requires TOOLCHANGE_PARK)
52
+ *  Y[linear]     Park Y (Requires TOOLCHANGE_PARK)
53
+ *  I[linear]     Park I (Requires TOOLCHANGE_PARK and NUM_AXES >= 4)
54
+ *  J[linear]     Park J (Requires TOOLCHANGE_PARK and NUM_AXES >= 5)
55
+ *  K[linear]     Park K (Requires TOOLCHANGE_PARK and NUM_AXES >= 6)
56
+ *  C[linear]     Park U (Requires TOOLCHANGE_PARK and NUM_AXES >= 7)
57
+ *  H[linear]     Park V (Requires TOOLCHANGE_PARK and NUM_AXES >= 8)
58
+ *  O[linear]     Park W (Requires TOOLCHANGE_PARK and NUM_AXES >= 9)
59
+ *  Z[linear]     Z Raise
60
+ *  F[speed]      Fan Speed 0-255
61
+ *  D[seconds]    Fan time
62 62
  *
63 63
  * Tool migration settings
64 64
  *  A[0|1]      Enable auto-migration on runout
@@ -82,8 +82,8 @@ void GcodeSuite::M217() {
82 82
     if (parser.seenval('R')) { const int16_t v = parser.value_linear_units(); toolchange_settings.retract_speed = constrain(v, 10, 5400); }
83 83
     if (parser.seenval('U')) { const int16_t v = parser.value_linear_units(); toolchange_settings.unretract_speed = constrain(v, 10, 5400); }
84 84
     #if TOOLCHANGE_FS_FAN >= 0 && HAS_FAN
85
-      if (parser.seenval('F')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_speed = constrain(v, 0, 255); }
86
-      if (parser.seenval('G')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_time = constrain(v, 1, 30); }
85
+      if (parser.seenval('F')) { const uint16_t v = parser.value_ushort(); toolchange_settings.fan_speed = constrain(v, 0, 255); }
86
+      if (parser.seenval('D')) { const uint16_t v = parser.value_ushort(); toolchange_settings.fan_time = constrain(v, 1, 30); }
87 87
     #endif
88 88
   #endif
89 89
 
@@ -171,7 +171,7 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) {
171 171
     SERIAL_ECHOPGM(" R", LINEAR_UNIT(toolchange_settings.retract_speed),
172 172
                    " U", LINEAR_UNIT(toolchange_settings.unretract_speed),
173 173
                    " F", toolchange_settings.fan_speed,
174
-                   " G", toolchange_settings.fan_time);
174
+                   " D", toolchange_settings.fan_time);
175 175
 
176 176
     #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
177 177
       SERIAL_ECHOPGM(" A", migration.automode);
@@ -186,13 +186,13 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) {
186 186
           , SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y)
187 187
         #endif
188 188
         #if SECONDARY_AXES >= 1
189
-          , LIST_N(DOUBLE(SECONDARY_AXES),
190
-              PSTR(" I"), I_AXIS_UNIT(toolchange_settings.change_point.i),
191
-              PSTR(" J"), J_AXIS_UNIT(toolchange_settings.change_point.j),
192
-              PSTR(" K"), K_AXIS_UNIT(toolchange_settings.change_point.k),
193
-              SP_C_STR,   U_AXIS_UNIT(toolchange_settings.change_point.u),
194
-              PSTR(" H"), V_AXIS_UNIT(toolchange_settings.change_point.v),
195
-              PSTR(" O"), W_AXIS_UNIT(toolchange_settings.change_point.w)
189
+          , LIST_N(DOUBLE(SECONDARY_AXES)
190
+              , SP_I_STR,   I_AXIS_UNIT(toolchange_settings.change_point.i)
191
+              , SP_J_STR,   J_AXIS_UNIT(toolchange_settings.change_point.j)
192
+              , SP_K_STR,   K_AXIS_UNIT(toolchange_settings.change_point.k)
193
+              , SP_C_STR,   U_AXIS_UNIT(toolchange_settings.change_point.u)
194
+              , PSTR(" H"), V_AXIS_UNIT(toolchange_settings.change_point.v)
195
+              , PSTR(" O"), W_AXIS_UNIT(toolchange_settings.change_point.w)
196 196
             )
197 197
         #endif
198 198
       );

+ 1
- 1
Marlin/src/inc/Conditionals_LCD.h 查看文件

@@ -712,7 +712,7 @@
712 712
  * Number of Primary Linear Axes (e.g., XYZ)
713 713
  * X, XY, or XYZ axes. Excluding duplicate axes (X2, Y2. Z2. Z3, Z4)
714 714
  */
715
-#if HAS_I_AXIS
715
+#if NUM_AXES >= 3
716 716
   #define PRIMARY_LINEAR_AXES 3
717 717
 #else
718 718
   #define PRIMARY_LINEAR_AXES NUM_AXES

+ 2
- 0
Marlin/src/inc/SanityCheck.h 查看文件

@@ -390,6 +390,8 @@
390 390
   #error "ENDSTOP_NOISE_FILTER is now ENDSTOP_NOISE_THRESHOLD [2-7]."
391 391
 #elif defined(RETRACT_ZLIFT)
392 392
   #error "RETRACT_ZLIFT is now RETRACT_ZRAISE."
393
+#elif defined(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
394
+  #error "TOOLCHANGE_FS_INIT_BEFORE_SWAP is now TOOLCHANGE_FS_SLOW_FIRST_PRIME."
393 395
 #elif defined(TOOLCHANGE_PARK_ZLIFT) || defined(TOOLCHANGE_UNPARK_ZLIFT)
394 396
   #error "TOOLCHANGE_PARK_ZLIFT and TOOLCHANGE_UNPARK_ZLIFT are now TOOLCHANGE_ZRAISE."
395 397
 #elif defined(SINGLENOZZLE_TOOLCHANGE_ZRAISE)

+ 2
- 2
Marlin/src/lcd/menu/menu_configuration.cpp 查看文件

@@ -122,8 +122,8 @@ void menu_advanced_settings();
122 122
       EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_UNRETRACT_SPEED, &toolchange_settings.unretract_speed, 10, 5400);
123 123
       EDIT_ITEM(float3, MSG_FILAMENT_PURGE_LENGTH, &toolchange_settings.extra_prime, 0, max_extrude);
124 124
       EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_PRIME_SPEED, &toolchange_settings.prime_speed, 10, 5400);
125
-      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_FAN_SPEED, &toolchange_settings.fan_speed, 0, 255);
126
-      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_FAN_TIME, &toolchange_settings.fan_time, 1, 30);
125
+      EDIT_ITEM_FAST(uint8, MSG_SINGLENOZZLE_FAN_SPEED, &toolchange_settings.fan_speed, 0, 255);
126
+      EDIT_ITEM_FAST(uint8, MSG_SINGLENOZZLE_FAN_TIME, &toolchange_settings.fan_time, 1, 30);
127 127
     #endif
128 128
     EDIT_ITEM(float3, MSG_TOOL_CHANGE_ZLIFT, &toolchange_settings.z_raise, 0, 10);
129 129
     END_MENU();

+ 150
- 75
Marlin/src/module/tool_change.cpp 查看文件

@@ -32,6 +32,7 @@
32 32
 #include "../MarlinCore.h"
33 33
 
34 34
 //#define DEBUG_TOOL_CHANGE
35
+//#define DEBUG_TOOLCHANGE_FILAMENT_SWAP
35 36
 
36 37
 #define DEBUG_OUT ENABLED(DEBUG_TOOL_CHANGE)
37 38
 #include "../core/debug_out.h"
@@ -42,7 +43,6 @@
42 43
 
43 44
 #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
44 45
   migration_settings_t migration = migration_defaults;
45
-  bool enable_first_prime;
46 46
 #endif
47 47
 
48 48
 #if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
@@ -150,6 +150,7 @@
150 150
 
151 151
 #endif // SWITCHING_NOZZLE
152 152
 
153
+// Move to position routines
153 154
 void _line_to_current(const AxisEnum fr_axis, const float fscale=1) {
154 155
   line_to_current_position(planner.settings.max_feedrate_mm_s[fr_axis] * fscale);
155 156
 }
@@ -899,10 +900,135 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
899 900
  */
900 901
 #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
901 902
 
903
+  #ifdef DEBUG_TOOLCHANGE_FILAMENT_SWAP
904
+    #define FS_DEBUG(V...) SERIAL_ECHOLNPGM("DEBUG: " V)
905
+  #else
906
+    #define FS_DEBUG(...) NOOP
907
+  #endif
908
+
909
+  // Define any variables required
910
+  static Flags<EXTRUDERS> extruder_was_primed; // Extruders primed status
911
+
912
+  #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
913
+    bool enable_first_prime; // As set by M217 V
914
+  #endif
915
+
916
+  // Cool down with fan
917
+  inline void filament_swap_cooling() {
918
+    #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
919
+      thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
920
+      gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time));
921
+      thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0;
922
+    #endif
923
+  }
924
+
925
+  /**
926
+   * Check if too cold to move the specified tool
927
+   *
928
+   * Returns TRUE if too cold to move (also echos message: STR_ERR_HOTEND_TOO_COLD)
929
+   * Returns FALSE if able to  move.
930
+   */
931
+  bool too_cold(uint8_t toolID){
932
+    if (TERN0(PREVENT_COLD_EXTRUSION, !DEBUGGING(DRYRUN) && thermalManager.targetTooColdToExtrude(toolID))) {
933
+      SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
934
+      return true;
935
+    }
936
+    return false;
937
+  }
938
+
939
+  /**
940
+   * Cutting recovery -- Recover from cutting retraction that occurs at the end of nozzle priming
941
+   *
942
+   * If the active_extruder is up to temp (!too_cold):
943
+   *  Extrude filament distance = toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT
944
+   *  current_position.e = e;
945
+   *  sync_plan_position_e();
946
+   */
947
+  void extruder_cutting_recover(const_float_t e) {
948
+    if (!too_cold(active_extruder)) {
949
+      const float dist = toolchange_settings.extra_resume + (TOOLCHANGE_FS_WIPE_RETRACT);
950
+      FS_DEBUG("Performing Cutting Recover | Distance: ", dist, " | Speed: ", MMM_TO_MMS(toolchange_settings.unretract_speed), "mm/s");
951
+      unscaled_e_move(dist, MMM_TO_MMS(toolchange_settings.unretract_speed));
952
+      planner.synchronize();
953
+      FS_DEBUG("Set position to: ", e);
954
+      current_position.e = e;
955
+      sync_plan_position_e(); // Resume new E Position
956
+    }
957
+  }
958
+
959
+  /**
960
+   * Prime the currently selected extruder (Filament loading only)
961
+   *
962
+   * If too_cold(toolID) returns TRUE -> returns without moving extruder.
963
+   * Extruders filament = swap_length + extra prime, then performs cutting retraction if enabled.
964
+   * If cooling fan is enabled, calls filament_swap_cooling();
965
+   */
966
+  void extruder_prime() {
967
+
968
+    if (too_cold(active_extruder)) {
969
+      FS_DEBUG("Priming Aborted -  Nozzle Too Cold!");
970
+      return; // Extruder too cold to prime
971
+    }
972
+
973
+    float fr = toolchange_settings.unretract_speed; // Set default speed for unretract
974
+
975
+    #if ENABLED(TOOLCHANGE_FS_SLOW_FIRST_PRIME)
976
+    /*
977
+     * Perform first unretract movement at the slower Prime_Speed to avoid breakage on first prime
978
+     */
979
+    static Flags<EXTRUDERS> extruder_did_first_prime;  // Extruders first priming status
980
+    if (!extruder_did_first_prime[active_extruder]) {
981
+      extruder_did_first_prime.set(active_extruder);   // Log first prime complete
982
+      // new nozzle - prime at user-specified speed.
983
+      FS_DEBUG("First time priming T", active_extruder, ", reducing speed from ", MMM_TO_MMS(fr), " to ",  MMM_TO_MMS(toolchange_settings.prime_speed), "mm/s");
984
+      fr = toolchange_settings.prime_speed;
985
+      unscaled_e_move(0, MMM_TO_MMS(fr));      // Init planner with 0 length move
986
+    }
987
+    #endif
988
+
989
+    //Calculate and perform the priming distance
990
+    if (toolchange_settings.extra_prime >= 0) {
991
+      // Positive extra_prime value
992
+      // - Return filament at speed (fr) then extra_prime at prime speed
993
+      FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", toolchange_settings.swap_length, " | Speed: ", MMM_TO_MMS(fr), "mm/s");
994
+      unscaled_e_move(toolchange_settings.swap_length, MMM_TO_MMS(fr)); // Prime (Unretract) filament by extruding equal to Swap Length (Unretract)
995
+
996
+      if (toolchange_settings.extra_prime > 0) {
997
+        FS_DEBUG("Performing Extra Priming for T", active_extruder, " | Distance: ", toolchange_settings.extra_prime, " | Speed: ", MMM_TO_MMS(toolchange_settings.prime_speed), "mm/s");
998
+        unscaled_e_move(toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed)); // Extra Prime Distance
999
+      }
1000
+    }
1001
+    else {
1002
+      // Negative extra_prime value
1003
+      // - Unretract distance (swap length) is reduced by the value of extra_prime
1004
+      const float eswap = toolchange_settings.swap_length + toolchange_settings.extra_prime;
1005
+      FS_DEBUG("Negative ExtraPrime value - Swap Return Length has been reduced from ", toolchange_settings.swap_length, " to ", eswap);
1006
+      FS_DEBUG("Loading Filament for T", active_extruder, " | Distance: ", eswap, " | Speed: ", MMM_TO_MMS(fr), "mm/s");
1007
+      unscaled_e_move(eswap, MMM_TO_MMS(fr));
1008
+    }
1009
+
1010
+    extruder_was_primed.set(active_extruder); // Log that this extruder has been primed
1011
+
1012
+    // Cutting retraction
1013
+    #if TOOLCHANGE_FS_WIPE_RETRACT
1014
+      FS_DEBUG("Performing Cutting Retraction | Distance: ", -(TOOLCHANGE_FS_WIPE_RETRACT), " | Speed: ", MMM_TO_MMS(toolchange_settings.retract_speed), "mm/s");
1015
+      unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
1016
+    #endif
1017
+
1018
+    // Cool down with fan
1019
+    filament_swap_cooling();
1020
+
1021
+  }
1022
+
1023
+  /**
1024
+   * Sequence to Prime the currently selected extruder
1025
+   * Raise Z, move the ToolChange_Park if enabled, prime the extruder, move back.
1026
+   */
902 1027
   void tool_change_prime() {
903
-    if (toolchange_settings.extra_prime > 0
904
-      && TERN(PREVENT_COLD_EXTRUSION, !thermalManager.targetTooColdToExtrude(active_extruder), 1)
905
-    ) {
1028
+
1029
+    FS_DEBUG(">>> tool_change_prime()");
1030
+
1031
+    if (!too_cold(active_extruder)) {
906 1032
       destination = current_position; // Remember the old position
907 1033
 
908 1034
       const bool ok = TERN1(TOOLCHANGE_PARK, all_axes_homed() && toolchange_settings.enable_park);
@@ -941,20 +1067,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
941 1067
         }
942 1068
       #endif
943 1069
 
944
-      // Prime (All distances are added and slowed down to ensure secure priming in all circumstances)
945
-      unscaled_e_move(toolchange_settings.swap_length + toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed));
946
-
947
-      // Cutting retraction
948
-      #if TOOLCHANGE_FS_WIPE_RETRACT
949
-        unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
950
-      #endif
951
-
952
-      // Cool down with fan
953
-      #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
954
-        thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
955
-        gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time));
956
-        thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0;
957
-      #endif
1070
+      extruder_prime();
958 1071
 
959 1072
       // Move back
960 1073
       #if ENABLED(TOOLCHANGE_PARK)
@@ -968,13 +1081,11 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
968 1081
         }
969 1082
       #endif
970 1083
 
971
-      // Cutting recover
972
-      unscaled_e_move(toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT, MMM_TO_MMS(toolchange_settings.unretract_speed));
973
-
974
-      // Resume at the old E position
975
-      current_position.e = destination.e;
976
-      sync_plan_position_e();
1084
+      extruder_cutting_recover(destination.e); // Cutting recover
977 1085
     }
1086
+
1087
+    FS_DEBUG("<<< tool_change_prime");
1088
+
978 1089
   }
979 1090
 
980 1091
 #endif // TOOLCHANGE_FILAMENT_SWAP
@@ -1051,12 +1162,10 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
1051 1162
       TEMPORARY_BED_LEVELING_STATE(false);
1052 1163
     #endif
1053 1164
 
1054
-    // First tool priming. To prime again, reboot the machine.
1165
+    // First tool priming. To prime again, reboot the machine. -- Should only occur for first T0 after powerup!
1055 1166
     #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
1056
-      static bool first_tool_is_primed = false;
1057
-      if (new_tool == old_tool && !first_tool_is_primed && enable_first_prime) {
1167
+      if (enable_first_prime && old_tool == 0 && new_tool == 0 && !extruder_was_primed[0]) {
1058 1168
         tool_change_prime();
1059
-        first_tool_is_primed = true;
1060 1169
         TERN_(TOOLCHANGE_FS_INIT_BEFORE_SWAP, toolchange_extruder_ready.set(old_tool)); // Primed and initialized
1061 1170
       }
1062 1171
     #endif
@@ -1082,20 +1191,17 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
1082 1191
 
1083 1192
       // Unload / Retract
1084 1193
       #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
1085
-        const bool should_swap = can_move_away && toolchange_settings.swap_length,
1086
-                   too_cold = TERN0(PREVENT_COLD_EXTRUSION,
1087
-                     !DEBUGGING(DRYRUN) && (thermalManager.targetTooColdToExtrude(old_tool) || thermalManager.targetTooColdToExtrude(new_tool))
1088
-                   );
1194
+        const bool should_swap = can_move_away && toolchange_settings.swap_length;
1089 1195
         if (should_swap) {
1090
-          if (too_cold) {
1091
-            SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
1196
+          if (too_cold(old_tool)) {
1197
+            // If SingleNozzle setup is too cold, unable to perform tool_change.
1092 1198
             if (ENABLED(SINGLENOZZLE)) { active_extruder = new_tool; return; }
1093 1199
           }
1094
-          else {
1095
-            // For first new tool, change without unloading the old. 'Just prime/init the new'
1096
-            if (TERN1(TOOLCHANGE_FS_PRIME_FIRST_USED, first_tool_is_primed))
1097
-              unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed));
1098
-            TERN_(TOOLCHANGE_FS_PRIME_FIRST_USED, first_tool_is_primed = true); // The first new tool will be primed by toolchanging
1200
+          else if (extruder_was_primed[old_tool]) {
1201
+            // Retract the old extruder if it was previously primed
1202
+            // To-Do: Should SingleNozzle always retract?
1203
+            FS_DEBUG("Retracting Filament for T", old_tool, ". | Distance: ", toolchange_settings.swap_length, " | Speed: ", MMM_TO_MMS(toolchange_settings.retract_speed), "mm/s");
1204
+            unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed));
1099 1205
           }
1100 1206
         }
1101 1207
       #endif
@@ -1210,36 +1316,8 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
1210 1316
         #endif
1211 1317
 
1212 1318
         #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
1213
-          if (should_swap && !too_cold) {
1214
-
1215
-            float fr = toolchange_settings.unretract_speed;
1216
-
1217
-            #if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
1218
-              if (!toolchange_extruder_ready[new_tool]) {
1219
-                toolchange_extruder_ready.set(new_tool);
1220
-                fr = toolchange_settings.prime_speed;       // Next move is a prime
1221
-                unscaled_e_move(0, MMM_TO_MMS(fr));         // Init planner with 0 length move
1222
-              }
1223
-            #endif
1224
-
1225
-            // Unretract (or Prime)
1226
-            unscaled_e_move(toolchange_settings.swap_length, MMM_TO_MMS(fr));
1227
-
1228
-            // Extra Prime
1229
-            unscaled_e_move(toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed));
1230
-
1231
-            // Cutting retraction
1232
-            #if TOOLCHANGE_FS_WIPE_RETRACT
1233
-              unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
1234
-            #endif
1235
-
1236
-            // Cool down with fan
1237
-            #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
1238
-              thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
1239
-              gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time));
1240
-              thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0;
1241
-            #endif
1242
-          }
1319
+          if (should_swap && !too_cold(active_extruder))
1320
+            extruder_prime(); // Prime selected Extruder
1243 1321
         #endif
1244 1322
 
1245 1323
         // Prevent a move outside physical bounds
@@ -1280,11 +1358,8 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
1280 1358
         else DEBUG_ECHOLNPGM("Move back skipped");
1281 1359
 
1282 1360
         #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
1283
-          if (should_swap && !too_cold) {
1284
-            // Cutting recover
1285
-            unscaled_e_move(toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT, MMM_TO_MMS(toolchange_settings.unretract_speed));
1286
-            current_position.e = 0;
1287
-            sync_plan_position_e(); // New extruder primed and set to 0
1361
+          if (should_swap && !too_cold(active_extruder)) {
1362
+            extruder_cutting_recover(0); // New extruder primed and set to 0
1288 1363
 
1289 1364
             // Restart Fan
1290 1365
             #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0
@@ -1342,7 +1417,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
1342 1417
       #endif
1343 1418
     }
1344 1419
 
1345
-    SERIAL_ECHO_MSG(STR_ACTIVE_EXTRUDER, active_extruder);
1420
+    SERIAL_ECHOLNPGM(STR_ACTIVE_EXTRUDER, active_extruder);
1346 1421
 
1347 1422
   #endif // HAS_MULTI_EXTRUDER
1348 1423
 }

+ 15
- 9
Marlin/src/module/tool_change.h 查看文件

@@ -29,24 +29,30 @@
29 29
 
30 30
   typedef struct {
31 31
     #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
32
-      float swap_length, extra_prime, extra_resume;
33
-      int16_t prime_speed, retract_speed, unretract_speed, fan, fan_speed, fan_time;
32
+      float swap_length;            // M217 S
33
+      float extra_prime;            // M217 E
34
+      float extra_resume;           // M217 B
35
+      int16_t prime_speed;          // M217 P
36
+      int16_t retract_speed;        // M217 R
37
+      int16_t unretract_speed;      // M217 U
38
+      uint8_t fan_speed;            // M217 F
39
+      uint8_t fan_time;             // M217 D
34 40
     #endif
35 41
     #if ENABLED(TOOLCHANGE_PARK)
36
-      bool enable_park;
37
-      xyz_pos_t change_point;
42
+      bool enable_park;             // M217 W
43
+      xyz_pos_t change_point;       // M217 X Y I J K C H O
38 44
     #endif
39
-    float z_raise;
45
+    float z_raise;                  // M217 Z
40 46
   } toolchange_settings_t;
41 47
 
42 48
   extern toolchange_settings_t toolchange_settings;
43 49
 
44
-  #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
45
-    void tool_change_prime();
50
+  #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
51
+    extern bool enable_first_prime; // M217 V
46 52
   #endif
47 53
 
48
-  #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
49
-    extern bool enable_first_prime;
54
+  #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
55
+    void tool_change_prime(); // Prime the currently selected extruder
50 56
   #endif
51 57
 
52 58
   #if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)

+ 1
- 1
buildroot/tests/BIGTREE_GTR_V1_0 查看文件

@@ -24,7 +24,7 @@ opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \
24 24
         EXTRUDERS 5 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 \
25 25
         NUM_Z_STEPPER_DRIVERS 4 \
26 26
         DEFAULT_Kp_LIST '{ 22.2, 20.0, 21.0, 19.0, 18.0 }' DEFAULT_Ki_LIST '{ 1.08 }' DEFAULT_Kd_LIST '{ 114.0, 112.0, 110.0, 108.0 }'
27
-opt_enable TOOLCHANGE_FILAMENT_SWAP TOOLCHANGE_MIGRATION_FEATURE TOOLCHANGE_FS_INIT_BEFORE_SWAP TOOLCHANGE_FS_PRIME_FIRST_USED \
27
+opt_enable TOOLCHANGE_FILAMENT_SWAP TOOLCHANGE_MIGRATION_FEATURE TOOLCHANGE_FS_SLOW_FIRST_PRIME TOOLCHANGE_FS_PRIME_FIRST_USED \
28 28
            PID_PARAMS_PER_HOTEND Z_MULTI_ENDSTOPS
29 29
 exec_test $1 $2 "BigTreeTech GTR | 6 Extruders | Quad Z + Endstops" "$3"
30 30
 

Loading…
取消
儲存