Browse Source

Automatic Tool Migration feature (#17248)

studiodyne 4 years ago
parent
commit
2f6262c27b
No account linked to committer's email address

+ 47
- 9
Marlin/Configuration_adv.h View File

@@ -1847,19 +1847,55 @@
1847 1847
  */
1848 1848
 #if EXTRUDERS > 1
1849 1849
   // Z raise distance for tool-change, as needed for some extruders
1850
-  #define TOOLCHANGE_ZRAISE     2  // (mm)
1851
-  //#define TOOLCHANGE_NO_RETURN   // Never return to the previous position on tool-change
1850
+  #define TOOLCHANGE_ZRAISE                 2 // (mm)
1851
+  //#define TOOLCHANGE_ZRAISE_BEFORE_RETRACT  // Apply raise before swap retraction (if enabled)
1852
+  //#define TOOLCHANGE_NO_RETURN              // Never return to previous position on tool-change
1852 1853
   #if ENABLED(TOOLCHANGE_NO_RETURN)
1853
-    //#define EVENT_GCODE_AFTER_TOOLCHANGE "G12X"   // G-code to run after tool-change is complete
1854
+    //#define EVENT_GCODE_AFTER_TOOLCHANGE "G12X"   // Extra G-code to run after tool-change
1854 1855
   #endif
1855 1856
 
1856
-  // Retract and prime filament on tool-change
1857
+  /**
1858
+   * Retract and prime filament on tool-change to reduce
1859
+   * ooze and stringing and to get cleaner transitions.
1860
+   */
1857 1861
   //#define TOOLCHANGE_FILAMENT_SWAP
1858 1862
   #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
1859
-    #define TOOLCHANGE_FIL_SWAP_LENGTH          12  // (mm)
1860
-    #define TOOLCHANGE_FIL_EXTRA_PRIME           2  // (mm)
1861
-    #define TOOLCHANGE_FIL_SWAP_RETRACT_SPEED 3600  // (mm/m)
1862
-    #define TOOLCHANGE_FIL_SWAP_PRIME_SPEED   3600  // (mm/m)
1863
+    // Load / Unload
1864
+    #define TOOLCHANGE_FS_LENGTH              12  // (mm) Load / Unload length
1865
+    #define TOOLCHANGE_FS_EXTRA_RESUME_LENGTH  0  // (mm) Extra length for better restart, fine tune by LCD/Gcode)
1866
+    #define TOOLCHANGE_FS_RETRACT_SPEED   (50*60) // (mm/m) (Unloading)
1867
+    #define TOOLCHANGE_FS_UNRETRACT_SPEED (25*60) // (mm/m) (On SINGLENOZZLE or Bowden loading must be slowed down)
1868
+
1869
+    // Longer prime to clean out a SINGLENOZZLE
1870
+    #define TOOLCHANGE_FS_EXTRA_PRIME          0  // (mm) Extra priming length
1871
+    #define TOOLCHANGE_FS_PRIME_SPEED    (4.6*60) // (mm/m) Extra priming feedrate
1872
+    #define TOOLCHANGE_FS_WIPE_RETRACT         0  // (mm/m) Retract before cooling for less stringing, better wipe, etc.
1873
+
1874
+    // Cool after prime to reduce stringing
1875
+    #define TOOLCHANGE_FS_FAN                 -1  // Fan index or -1 to skip
1876
+    #define TOOLCHANGE_FS_FAN_SPEED          255  // 0-255
1877
+    #define TOOLCHANGE_FS_FAN_TIME            10  // (seconds)
1878
+
1879
+    // Swap uninitialized extruder with TOOLCHANGE_FS_PRIME_SPEED for all lengths (recover + prime)
1880
+    // (May break filament if not retracted beforehand.)
1881
+    //#define TOOLCHANGE_FS_INIT_BEFORE_SWAP
1882
+
1883
+    // Prime on the first T command even if the same or no toolchange / swap
1884
+    // Enable it (M217 V[0/1]) before printing, to avoid unwanted priming on host connect
1885
+    //#define TOOLCHANGE_FS_PRIME_FIRST_USED
1886
+
1887
+    /**
1888
+     * Tool Change Migration
1889
+     * This feature provides G-code and LCD options to switch tools mid-print.
1890
+     * All applicable tool properties are migrated so the print can continue.
1891
+     * Tools must be closely matching and other restrictions may apply.
1892
+     * Useful to:
1893
+     *   - Change filament color without interruption
1894
+     *   - Switch spools automatically on filament runout
1895
+     *   - Switch to a different nozzle on an extruder jam
1896
+     */
1897
+    #define TOOLCHANGE_MIGRATION_FEATURE
1898
+
1863 1899
   #endif
1864 1900
 
1865 1901
   /**
@@ -1870,8 +1906,10 @@
1870 1906
   #if ENABLED(TOOLCHANGE_PARK)
1871 1907
     #define TOOLCHANGE_PARK_XY    { X_MIN_POS + 10, Y_MIN_POS + 10 }
1872 1908
     #define TOOLCHANGE_PARK_XY_FEEDRATE 6000  // (mm/m)
1909
+    //#define TOOLCHANGE_PARK_X_ONLY          // X axis only move
1910
+    //#define TOOLCHANGE_PARK_Y_ONLY          // Y axis only move
1873 1911
   #endif
1874
-#endif
1912
+#endif // EXTRUDERS > 1
1875 1913
 
1876 1914
 /**
1877 1915
  * Advanced Pause

+ 9
- 0
Marlin/src/feature/runout.cpp View File

@@ -39,6 +39,10 @@ bool FilamentMonitorBase::enabled = true,
39 39
   bool FilamentMonitorBase::host_handling; // = false
40 40
 #endif
41 41
 
42
+#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
43
+  #include "../module/tool_change.h"
44
+#endif
45
+
42 46
 /**
43 47
  * Called by FilamentSensorSwitch::run when filament is detected.
44 48
  * Called by FilamentSensorEncoder::block_completed when motion is detected.
@@ -76,6 +80,11 @@ void event_filament_runout() {
76 80
 
77 81
   if (TERN0(ADVANCED_PAUSE_FEATURE, did_pause_print)) return;  // Action already in progress. Purge triggered repeated runout.
78 82
 
83
+  #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
84
+    if (migration.in_progress) return;  // Action already in progress. Purge triggered repeated runout.
85
+    if (migration.automode) { extruder_migration(); return; }
86
+  #endif
87
+
79 88
   TERN_(EXTENSIBLE_UI, ExtUI::onFilamentRunout(ExtUI::getActiveTool()));
80 89
 
81 90
   #if EITHER(HOST_PROMPT_SUPPORT, HOST_ACTION_COMMANDS)

+ 90
- 22
Marlin/src/gcode/config/M217.cpp View File

@@ -27,6 +27,10 @@
27 27
 #include "../gcode.h"
28 28
 #include "../../module/tool_change.h"
29 29
 
30
+#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
31
+  #include "../../module/motion.h"
32
+#endif
33
+
30 34
 #include "../../MarlinCore.h" // for SP_X_STR, etc.
31 35
 
32 36
 extern const char SP_X_STR[], SP_Y_STR[], SP_Z_STR[];
@@ -35,16 +39,30 @@ void M217_report(const bool eeprom=false) {
35 39
 
36 40
   #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
37 41
     serialprintPGM(eeprom ? PSTR("  M217") : PSTR("Toolchange:"));
38
-    SERIAL_ECHOPAIR(" S", LINEAR_UNIT(toolchange_settings.swap_length));
39
-    SERIAL_ECHOPAIR_P(SP_E_STR, LINEAR_UNIT(toolchange_settings.extra_prime));
40
-    SERIAL_ECHOPAIR_P(SP_P_STR, LINEAR_UNIT(toolchange_settings.prime_speed));
41
-    SERIAL_ECHOPAIR(" R", LINEAR_UNIT(toolchange_settings.retract_speed));
42
+    SERIAL_ECHOPAIR(" S", LINEAR_UNIT(toolchange_settings.swap_length),
43
+                    " B", LINEAR_UNIT(toolchange_settings.extra_resume));
44
+    SERIAL_ECHOPAIR_P(SP_E_STR, LINEAR_UNIT(toolchange_settings.extra_prime),
45
+                      SP_P_STR, LINEAR_UNIT(toolchange_settings.prime_speed));
46
+    SERIAL_ECHOPAIR(" R", LINEAR_UNIT(toolchange_settings.retract_speed),
47
+                    " U", LINEAR_UNIT(toolchange_settings.unretract_speed),
48
+                    " F", toolchange_settings.fan_speed,
49
+                    " G", toolchange_settings.fan_time);
50
+
51
+    #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
52
+      SERIAL_ECHOPAIR(" N", int(migration.automode));
53
+      SERIAL_ECHOPAIR(" L", LINEAR_UNIT(migration.last));
54
+    #endif
42 55
 
43 56
     #if ENABLED(TOOLCHANGE_PARK)
57
+      SERIAL_ECHOPAIR(" W", LINEAR_UNIT(toolchange_settings.enable_park));
44 58
       SERIAL_ECHOPAIR_P(SP_X_STR, LINEAR_UNIT(toolchange_settings.change_point.x));
45 59
       SERIAL_ECHOPAIR_P(SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y));
46 60
     #endif
47 61
 
62
+    #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
63
+      SERIAL_ECHOPAIR(" V", LINEAR_UNIT(enable_first_prime));
64
+    #endif
65
+
48 66
   #else
49 67
 
50 68
     UNUSED(eeprom);
@@ -58,48 +76,98 @@ void M217_report(const bool eeprom=false) {
58 76
 /**
59 77
  * M217 - Set SINGLENOZZLE toolchange parameters
60 78
  *
79
+ *  // Tool change command
80
+ *  Q           Prime active tool and exit
81
+ *
82
+ *  // Tool change settings
61 83
  *  S[linear]   Swap length
62
- *  E[linear]   Purge length
84
+ *  B[linear]   Extra Swap length
85
+ *  E[linear]   Prime length
63 86
  *  P[linear/m] Prime speed
64 87
  *  R[linear/m] Retract speed
88
+ *  U[linear/m] UnRetract speed
89
+ *  V[linear]   0/1 Enable auto prime first extruder used
90
+ *  W[linear]   0/1 Enable park & Z Raise
65 91
  *  X[linear]   Park X (Requires TOOLCHANGE_PARK)
66 92
  *  Y[linear]   Park Y (Requires TOOLCHANGE_PARK)
67 93
  *  Z[linear]   Z Raise
94
+ *  F[linear]   Fan Speed 0-255
95
+ *  G[linear/s] Fan time
96
+ *
97
+ * Tool migration settings
98
+ *  A[0|1]      Enable auto-migration on runout
99
+ *  L[index]    Last extruder to use for auto-migration
100
+ *
101
+ * Tool migration command
102
+ *  T[index]    Migrate to next extruder or the given extruder
68 103
  */
69 104
 void GcodeSuite::M217() {
70 105
 
71
-  #define SPR_PARAM
72
-  #define XY_PARAM
73
-
74 106
   #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
75 107
 
76
-    #undef SPR_PARAM
77
-    #define SPR_PARAM "SPRE"
108
+    static constexpr float max_extrude = TERN(PREVENT_LENGTHY_EXTRUDE, EXTRUDE_MAXLENGTH, 500);
78 109
 
79
-    static constexpr float max_extrude =
80
-      #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
81
-        EXTRUDE_MAXLENGTH
82
-      #else
83
-        500
84
-      #endif
85
-    ;
110
+    if (parser.seen('Q')) { tool_change_prime(); return; }
86 111
 
87 112
     if (parser.seenval('S')) { const float v = parser.value_linear_units(); toolchange_settings.swap_length = constrain(v, 0, max_extrude); }
113
+    if (parser.seenval('B')) { const float v = parser.value_linear_units(); toolchange_settings.extra_resume = constrain(v, -10, 10); }
88 114
     if (parser.seenval('E')) { const float v = parser.value_linear_units(); toolchange_settings.extra_prime = constrain(v, 0, max_extrude); }
89 115
     if (parser.seenval('P')) { const int16_t v = parser.value_linear_units(); toolchange_settings.prime_speed = constrain(v, 10, 5400); }
90 116
     if (parser.seenval('R')) { const int16_t v = parser.value_linear_units(); toolchange_settings.retract_speed = constrain(v, 10, 5400); }
117
+    if (parser.seenval('U')) { const int16_t v = parser.value_linear_units(); toolchange_settings.unretract_speed = constrain(v, 10, 5400); }
118
+    #if TOOLCHANGE_FS_FAN >= 0 && FAN_COUNT > 0
119
+      if (parser.seenval('F')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_speed = constrain(v, 0, 255); }
120
+      if (parser.seenval('G')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_time = constrain(v, 1, 30); }
121
+    #endif
122
+  #endif
123
+
124
+  #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
125
+    if (parser.seenval('V')) { enable_first_prime = parser.value_linear_units(); }
91 126
   #endif
92 127
 
93 128
   #if ENABLED(TOOLCHANGE_PARK)
94
-    #undef XY_PARAM
95
-    #define XY_PARAM "XY"
96
-    if (parser.seenval('X')) { toolchange_settings.change_point.x = parser.value_linear_units(); }
97
-    if (parser.seenval('Y')) { toolchange_settings.change_point.y = parser.value_linear_units(); }
129
+    if (parser.seenval('W')) { toolchange_settings.enable_park = parser.value_linear_units(); }
130
+    if (parser.seenval('X')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.x = constrain(v, X_MIN_POS, X_MAX_POS); }
131
+    if (parser.seenval('Y')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.y = constrain(v, Y_MIN_POS, Y_MAX_POS); }
98 132
   #endif
99 133
 
100 134
   if (parser.seenval('Z')) { toolchange_settings.z_raise = parser.value_linear_units(); }
101 135
 
102
-  if (!parser.seen(SPR_PARAM XY_PARAM "Z")) M217_report();
136
+  #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
137
+    migration.target = 0;       // 0 = disabled
138
+
139
+    if (parser.seenval('L')) {  // Last
140
+      const int16_t lval = parser.value_int();
141
+      if (WITHIN(lval, 0, EXTRUDERS - 1)) {
142
+        migration.last = lval;
143
+        migration.automode = (active_extruder < migration.last);
144
+      }
145
+    }
146
+
147
+    if (parser.seen('A'))       // Auto on/off
148
+      migration.automode = parser.value_bool();
149
+
150
+    if (parser.seen('T')) {     // Migrate now
151
+      if (parser.has_value()) {
152
+        const int16_t tval = parser.value_int();
153
+        if (WITHIN(tval, 0, EXTRUDERS - 1) && tval != active_extruder) {
154
+          migration.target = tval + 1;
155
+          extruder_migration();
156
+          migration.target = 0; // disable
157
+          return;
158
+        }
159
+        else
160
+          migration.target = 0; // disable
161
+      }
162
+      else {
163
+        extruder_migration();
164
+        return;
165
+      }
166
+    }
167
+
168
+  #endif
169
+
170
+  M217_report();
103 171
 }
104 172
 
105 173
 #endif // EXTRUDERS > 1

+ 2
- 4
Marlin/src/gcode/config/M221.cpp View File

@@ -33,10 +33,8 @@ void GcodeSuite::M221() {
33 33
   const int8_t target_extruder = get_target_extruder_from_command();
34 34
   if (target_extruder < 0) return;
35 35
 
36
-  if (parser.seenval('S')) {
37
-    planner.flow_percentage[target_extruder] = parser.value_int();
38
-    planner.refresh_e_factor(target_extruder);
39
-  }
36
+  if (parser.seenval('S'))
37
+    planner.set_flow(target_extruder, parser.value_int());
40 38
   else {
41 39
     SERIAL_ECHO_START();
42 40
     SERIAL_CHAR('E', '0' + target_extruder);

+ 1
- 4
Marlin/src/gcode/sd/M1001.cpp View File

@@ -31,10 +31,6 @@
31 31
   #include "../queue.h"
32 32
 #endif
33 33
 
34
-#if HAS_LEDS_OFF_FLAG
35
-  #include "../../MarlinCore.h"
36
-#endif
37
-
38 34
 #if EITHER(LCD_SET_PROGRESS_MANUALLY, SD_REPRINT_LAST_SELECTED_FILE)
39 35
   #include "../../lcd/ultralcd.h"
40 36
 #endif
@@ -44,6 +40,7 @@
44 40
 #endif
45 41
 
46 42
 #if HAS_LEDS_OFF_FLAG
43
+  #include "../../MarlinCore.h" // for wait_for_user_response
47 44
   #include "../../feature/leds/printer_event_leds.h"
48 45
 #endif
49 46
 

+ 2
- 2
Marlin/src/inc/Conditionals_post.h View File

@@ -2222,8 +2222,8 @@
2222 2222
   #define FILAMENT_CHANGE_SLOW_LOAD_LENGTH 0
2223 2223
 #endif
2224 2224
 
2225
-#if EXTRUDERS > 1 && !defined(TOOLCHANGE_FIL_EXTRA_PRIME)
2226
-  #define TOOLCHANGE_FIL_EXTRA_PRIME 0
2225
+#if EXTRUDERS > 1 && !defined(TOOLCHANGE_FS_EXTRA_PRIME)
2226
+  #define TOOLCHANGE_FS_EXTRA_PRIME 0
2227 2227
 #endif
2228 2228
 
2229 2229
 /**

+ 7
- 6
Marlin/src/inc/SanityCheck.h View File

@@ -833,14 +833,15 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
833 833
   #endif
834 834
 
835 835
   #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
836
-    #ifndef TOOLCHANGE_FIL_SWAP_LENGTH
837
-      #error "TOOLCHANGE_FILAMENT_SWAP requires TOOLCHANGE_FIL_SWAP_LENGTH. Please update your Configuration."
838
-    #elif !defined(TOOLCHANGE_FIL_SWAP_RETRACT_SPEED)
839
-      #error "TOOLCHANGE_FILAMENT_SWAP requires TOOLCHANGE_FIL_SWAP_RETRACT_SPEED. Please update your Configuration."
840
-    #elif !defined(TOOLCHANGE_FIL_SWAP_PRIME_SPEED)
841
-      #error "TOOLCHANGE_FILAMENT_SWAP requires TOOLCHANGE_FIL_SWAP_PRIME_SPEED. Please update your Configuration."
836
+    #ifndef TOOLCHANGE_FS_LENGTH
837
+      #error "TOOLCHANGE_FILAMENT_SWAP requires TOOLCHANGE_FS_LENGTH. Please update your Configuration_adv.h."
838
+    #elif !defined(TOOLCHANGE_FS_RETRACT_SPEED)
839
+      #error "TOOLCHANGE_FILAMENT_SWAP requires TOOLCHANGE_FS_RETRACT_SPEED. Please update your Configuration_adv.h."
840
+    #elif !defined(TOOLCHANGE_FS_PRIME_SPEED)
841
+      #error "TOOLCHANGE_FILAMENT_SWAP requires TOOLCHANGE_FS_PRIME_SPEED. Please update your Configuration_adv.h."
842 842
     #endif
843 843
   #endif
844
+
844 845
   #if ENABLED(TOOLCHANGE_PARK)
845 846
     #ifndef TOOLCHANGE_PARK_XY
846 847
       #error "TOOLCHANGE_PARK requires TOOLCHANGE_PARK_XY. Please update your Configuration."

+ 1
- 2
Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.cpp View File

@@ -573,8 +573,7 @@ void DGUSScreenVariableHandler::HandleFlowRateChanged(DGUS_VP_Variable &var, voi
573 573
       #endif
574 574
     }
575 575
 
576
-    planner.flow_percentage[target_extruder] = newvalue;
577
-    planner.refresh_e_factor(target_extruder);
576
+    planner.set_flow(target_extruder, newvalue);
578 577
     ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
579 578
   #else
580 579
     UNUSED(var); UNUSED(val_ptr);

+ 1
- 4
Marlin/src/lcd/extui/ui_api.cpp View File

@@ -669,10 +669,7 @@ namespace ExtUI {
669 669
   float getRetractAcceleration_mm_s2()                { return planner.settings.retract_acceleration; }
670 670
   float getTravelAcceleration_mm_s2()                 { return planner.settings.travel_acceleration; }
671 671
   void setFeedrate_mm_s(const feedRate_t fr)          { feedrate_mm_s = fr; }
672
-  void setFlow_percent(const int16_t flow, const extruder_t extr) {
673
-    planner.flow_percentage[extr] = flow;
674
-    planner.refresh_e_factor(extr);
675
-  }
672
+  void setFlow_percent(const int16_t flow, const extruder_t extr) { planner.set_flow(extr, flow); }
676 673
   void setMinFeedrate_mm_s(const feedRate_t fr)       { planner.settings.min_feedrate_mm_s = fr; }
677 674
   void setMinTravelFeedrate_mm_s(const feedRate_t fr) { planner.settings.min_travel_feedrate_mm_s = fr; }
678 675
   void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; }

+ 2
- 2
Marlin/src/lcd/language/language_cz.h View File

@@ -357,8 +357,8 @@ namespace Language_cz {
357 357
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Délka zavedení");
358 358
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Výměna nástroje");
359 359
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Zdvih Z");
360
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Rychlost primár.");
361
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Rychlost retrak.");
360
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Rychlost primár.");
361
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Rychlost retrak.");
362 362
   PROGMEM Language_Str MSG_NOZZLE_STANDBY                  = _UxGT("Tryska standby");
363 363
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Vyměnit filament");
364 364
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Vyměnit filament *");

+ 3
- 3
Marlin/src/lcd/language/language_de.h View File

@@ -347,9 +347,9 @@ namespace Language_de {
347 347
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Entladelänge");
348 348
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Werkzeugwechsel");
349 349
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Z anheben");
350
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Prime-Geschwin.");
351
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Einzug-Geschwin.");
352
-
350
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Prime-Geschwin.");
351
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Einzug-Geschwin.");
352
+  PROGMEM Language_Str MSG_NOZZLE_STANDBY                  = _UxGT("Düsen-Standby");
353 353
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Filament wechseln");
354 354
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Filament wechseln *");
355 355
   PROGMEM Language_Str MSG_FILAMENTLOAD                    = _UxGT("Filament laden");

+ 13
- 2
Marlin/src/lcd/language/language_en.h View File

@@ -371,11 +371,22 @@ namespace Language_en {
371 371
   PROGMEM Language_Str MSG_CONTROL_RETRACT_RECOVER_SWAPF   = _UxGT("S UnRet V");
372 372
   PROGMEM Language_Str MSG_AUTORETRACT                     = _UxGT("AutoRetr.");
373 373
   PROGMEM Language_Str MSG_FILAMENT_SWAP_LENGTH            = _UxGT("Swap Length");
374
+  PROGMEM Language_Str MSG_FILAMENT_SWAP_EXTRA             = _UxGT("Swap Extra");
374 375
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Purge Length");
375 376
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Tool Change");
376 377
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Z Raise");
377
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Prime Speed");
378
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Retract Speed");
378
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Prime Speed");
379
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Retract Speed");
380
+  PROGMEM Language_Str MSG_FILAMENT_PARK_ENABLED           = _UxGT("Park Head");
381
+  PROGMEM Language_Str MSG_SINGLENOZZLE_UNRETRACT_SPEED    = _UxGT("Recover Speed");
382
+  PROGMEM Language_Str MSG_SINGLENOZZLE_FAN_SPEED          = _UxGT("Fan Speed");
383
+  PROGMEM Language_Str MSG_SINGLENOZZLE_FAN_TIME           = _UxGT("Fan Time");
384
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_ON               = _UxGT("Auto ON");
385
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_OFF              = _UxGT("Auto OFF");
386
+  PROGMEM Language_Str MSG_TOOL_MIGRATION                  = _UxGT("Tool Migration");
387
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_AUTO             = _UxGT("Auto-migration");
388
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_END              = _UxGT("Last Extruder");
389
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_SWAP             = _UxGT("Migrate to *");
379 390
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Change Filament");
380 391
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Change Filament *");
381 392
   PROGMEM Language_Str MSG_FILAMENTLOAD                    = _UxGT("Load Filament");

+ 2
- 2
Marlin/src/lcd/language/language_es.h View File

@@ -367,8 +367,8 @@ namespace Language_es {
367 367
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Purgar longitud");
368 368
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Cambiar Herramienta");
369 369
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Aumentar Z");
370
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Vel. de Cebado");
371
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Vel. de retracción");
370
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Vel. de Cebado");
371
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Vel. de retracción");
372 372
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Cambiar filamento");
373 373
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Cambiar filamento *");
374 374
   PROGMEM Language_Str MSG_FILAMENTLOAD                    = _UxGT("Cargar filamento");

+ 14
- 3
Marlin/src/lcd/language/language_fr.h View File

@@ -53,7 +53,7 @@ namespace Language_fr {
53 53
   PROGMEM Language_Str MSG_MAIN                            = _UxGT("Menu principal");
54 54
   PROGMEM Language_Str MSG_ADVANCED_SETTINGS               = _UxGT("Config. avancée");
55 55
   PROGMEM Language_Str MSG_CONFIGURATION                   = _UxGT("Configuration");
56
-  PROGMEM Language_Str MSG_AUTOSTART                       = _UxGT("Exéc. auto#.gcode");
56
+  PROGMEM Language_Str MSG_AUTOSTART                       = _UxGT("Exéc. auto.gcode");
57 57
   PROGMEM Language_Str MSG_DISABLE_STEPPERS                = _UxGT("Arrêter moteurs");
58 58
   PROGMEM Language_Str MSG_DEBUG_MENU                      = _UxGT("Menu debug");
59 59
   PROGMEM Language_Str MSG_PROGRESS_BAR_TEST               = _UxGT("Test barre progress.");
@@ -329,10 +329,21 @@ namespace Language_fr {
329 329
   PROGMEM Language_Str MSG_AUTORETRACT                     = _UxGT("Rétraction auto");
330 330
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Changement outil");
331 331
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Augmenter Z");
332
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Vitesse primaire");
333
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Vitesse rétract°");
332
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Vitesse primaire");
333
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Vitesse rétract°");
334
+  PROGMEM Language_Str MSG_FILAMENT_PARK_ENABLED           = _UxGT("Garer Extrudeur");
335
+  PROGMEM Language_Str MSG_SINGLENOZZLE_UNRETRACT_SPEED    = _UxGT("Vitesse reprise");
336
+  PROGMEM Language_Str MSG_SINGLENOZZLE_FAN_SPEED          = _UxGT("Vit.  ventil.");
337
+  PROGMEM Language_Str MSG_SINGLENOZZLE_FAN_TIME           = _UxGT("Temps ventil.");
338
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_ON               = _UxGT("Auto ON");
339
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_OFF              = _UxGT("Auto OFF");
340
+  PROGMEM Language_Str MSG_TOOL_MIGRATION                  = _UxGT("Migration d'outil");
341
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_AUTO             = _UxGT("Migration auto");
342
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_END              = _UxGT("Extrudeur Final");
343
+  PROGMEM Language_Str MSG_TOOL_MIGRATION_SWAP             = _UxGT("Migrer vers *");
334 344
   PROGMEM Language_Str MSG_NOZZLE_STANDBY                  = _UxGT("Attente buse");
335 345
   PROGMEM Language_Str MSG_FILAMENT_SWAP_LENGTH            = _UxGT("Longueur retrait");
346
+  PROGMEM Language_Str MSG_FILAMENT_SWAP_EXTRA             = _UxGT("Longueur Extra");
336 347
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Longueur de purge");
337 348
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Changer filament");
338 349
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Changer filament *");

+ 2
- 2
Marlin/src/lcd/language/language_gl.h View File

@@ -371,8 +371,8 @@ namespace Language_gl {
371 371
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Lonxitude de Purga");
372 372
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Cambiar Ferramenta");
373 373
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Levantar Z");
374
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Velocidade prim.");
375
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Vel. de Retracción");
374
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Velocidade prim.");
375
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Vel. de Retracción");
376 376
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Cambiar Filamento");
377 377
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Cambiar Filamento *");
378 378
   PROGMEM Language_Str MSG_FILAMENTLOAD                    = _UxGT("Cargar Filamento");

+ 2
- 2
Marlin/src/lcd/language/language_it.h View File

@@ -370,8 +370,8 @@ namespace Language_it {
370 370
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Lunghezza spurgo");
371 371
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Cambio utensile");
372 372
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Risalita Z");
373
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Velocità innesco");
374
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Velocità retrazione");
373
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Velocità innesco");
374
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Velocità retrazione");
375 375
   PROGMEM Language_Str MSG_NOZZLE_PARKED                   = _UxGT("Ugello Parcheggiato");
376 376
   PROGMEM Language_Str MSG_NOZZLE_STANDBY                  = _UxGT("Standby ugello");
377 377
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Cambia filamento");

+ 2
- 2
Marlin/src/lcd/language/language_pl.h View File

@@ -339,8 +339,8 @@ namespace Language_pl {
339 339
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Długość oczyszczania");
340 340
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Zmiana narzędzia");
341 341
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Podniesienie Z");
342
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Prędkość napełniania");
343
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Prędkość wycofania");
342
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Prędkość napełniania");
343
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Prędkość wycofania");
344 344
   PROGMEM Language_Str MSG_NOZZLE_STANDBY                  = _UxGT("Dysza w oczekiwaniu");
345 345
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Zmień filament");
346 346
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Zmień filament *");

+ 2
- 2
Marlin/src/lcd/language/language_pt_br.h View File

@@ -286,8 +286,8 @@ namespace Language_pt_br {
286 286
   PROGMEM Language_Str MSG_FILAMENT_SWAP_LENGTH            = _UxGT("Distancia Retração");
287 287
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Mudar Ferramenta");
288 288
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Levantar Z");
289
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Preparar Veloc.");
290
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Veloc. Retração");
289
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Preparar Veloc.");
290
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Veloc. Retração");
291 291
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Trocar Filamento");
292 292
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Trocar Filamento *");
293 293
   PROGMEM Language_Str MSG_FILAMENTLOAD_E                  = _UxGT("Carregar Filamento *");

+ 2
- 2
Marlin/src/lcd/language/language_tr.h View File

@@ -365,8 +365,8 @@ namespace Language_tr {
365 365
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("Tasfiye uzunluğu");
366 366
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Takım Değişimi");
367 367
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Z Yükselt");
368
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Birincil Hız");
369
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Geri Çekme Hızı");
368
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Birincil Hız");
369
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Geri Çekme Hızı");
370 370
   PROGMEM Language_Str MSG_NOZZLE_STANDBY                  = _UxGT("Nozul Beklemede");
371 371
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Filaman Değiştir");
372 372
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Filaman Değiştir *");

+ 2
- 2
Marlin/src/lcd/language/language_vi.h View File

@@ -299,8 +299,8 @@ namespace Language_vi {
299 299
   PROGMEM Language_Str MSG_FILAMENT_SWAP_LENGTH            = _UxGT("Khoảng Cách Rút");                      // Retract Distance
300 300
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("Thay Đổi Công Cụ");                     // Tool Change
301 301
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Đưa Lên Z");                            // Z Raise
302
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("Tốc Độ Tuôn Ra");                       // Prime Speed
303
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("Tốc Độ Rút Lại");                       // Retract Speed
302
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("Tốc Độ Tuôn Ra");                       // Prime Speed
303
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("Tốc Độ Rút Lại");                       // Retract Speed
304 304
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("Thay dây nhựa");                        // change filament
305 305
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("Thay dây nhựa *");                      // change filament
306 306
   PROGMEM Language_Str MSG_FILAMENTLOAD                    = _UxGT("Nạp dây nhựa");                         // load filament

+ 2
- 2
Marlin/src/lcd/language/language_zh_TW.h View File

@@ -346,8 +346,8 @@ namespace Language_zh_TW {
346 346
   PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH           = _UxGT("清除長度");   //"Purge Length"
347 347
   PROGMEM Language_Str MSG_TOOL_CHANGE                     = _UxGT("交換工具"); //"Tool Change"
348 348
   PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT               = _UxGT("Z軸提昇");    //"Z Raise"
349
-  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD          = _UxGT("最高速度");    //"Prime Speed"
350
-  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD        = _UxGT("收回速度");  //"Retract Speed"
349
+  PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED        = _UxGT("最高速度");    //"Prime Speed"
350
+  PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED      = _UxGT("收回速度");  //"Retract Speed"
351 351
   PROGMEM Language_Str MSG_NOZZLE_STANDBY                  = _UxGT("噴嘴待機"); //"Nozzle Standby"
352 352
   PROGMEM Language_Str MSG_FILAMENTCHANGE                  = _UxGT("更換絲料");     //"Change filament"
353 353
   PROGMEM Language_Str MSG_FILAMENTCHANGE_E                = _UxGT("更換絲料 *");

+ 40
- 9
Marlin/src/lcd/menu/menu_configuration.cpp View File

@@ -104,22 +104,50 @@ void menu_advanced_settings();
104 104
     START_MENU();
105 105
     BACK_ITEM(MSG_CONFIGURATION);
106 106
     #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
107
-      static constexpr float max_extrude =
108
-        #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
109
-          EXTRUDE_MAXLENGTH
110
-        #else
111
-          500
112
-        #endif
113
-      ;
107
+      static constexpr float max_extrude = TERN(PREVENT_LENGTHY_EXTRUDE, EXTRUDE_MAXLENGTH, 500);
108
+      #if ENABLED(TOOLCHANGE_PARK)
109
+        EDIT_ITEM(bool, MSG_FILAMENT_PARK_ENABLED, &toolchange_settings.enable_park);
110
+      #endif
114 111
       EDIT_ITEM(float3, MSG_FILAMENT_SWAP_LENGTH, &toolchange_settings.swap_length, 0, max_extrude);
112
+      EDIT_ITEM(float41sign, MSG_FILAMENT_SWAP_EXTRA, &toolchange_settings.extra_resume, -10, 10);
113
+      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_RETRACT_SPEED, &toolchange_settings.retract_speed, 10, 5400);
114
+      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_UNRETRACT_SPEED, &toolchange_settings.unretract_speed, 10, 5400);
115 115
       EDIT_ITEM(float3, MSG_FILAMENT_PURGE_LENGTH, &toolchange_settings.extra_prime, 0, max_extrude);
116
-      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_RETRACT_SPD, &toolchange_settings.retract_speed, 10, 5400);
117
-      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_PRIME_SPD, &toolchange_settings.prime_speed, 10, 5400);
116
+      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_PRIME_SPEED, &toolchange_settings.prime_speed, 10, 5400);
117
+      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_FAN_SPEED, &toolchange_settings.fan_speed, 0, 255);
118
+      EDIT_ITEM_FAST(int4, MSG_SINGLENOZZLE_FAN_TIME, &toolchange_settings.fan_time, 1, 30);
118 119
     #endif
119 120
     EDIT_ITEM(float3, MSG_TOOL_CHANGE_ZLIFT, &toolchange_settings.z_raise, 0, 10);
120 121
     END_MENU();
121 122
   }
122 123
 
124
+  #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
125
+
126
+    #include "../../module/motion.h" // for active_extruder
127
+
128
+    void menu_toolchange_migration() {
129
+      START_MENU();
130
+      BACK_ITEM(MSG_CONFIGURATION);
131
+
132
+      // Auto mode ON/OFF
133
+      EDIT_ITEM(bool, MSG_TOOL_MIGRATION_AUTO, &migration.automode);
134
+      EDIT_ITEM(uint8, MSG_TOOL_MIGRATION_END, &migration.last, 0, EXTRUDERS - 1);
135
+
136
+      // Migrate to a chosen extruder
137
+      PGM_P const msg_migrate = GET_TEXT(MSG_TOOL_MIGRATION_SWAP);
138
+      LOOP_L_N(s, EXTRUDERS) {
139
+        if (s != active_extruder) {
140
+          ACTION_ITEM_N_P(s, msg_migrate, []{
141
+            char cmd[12];
142
+            sprintf_P(cmd, PSTR("M217 T%i"), int(MenuItemBase::itemIndex));
143
+            queue.inject(cmd);
144
+          });
145
+        }
146
+      }
147
+      END_MENU();
148
+    }
149
+  #endif
150
+
123 151
 #endif
124 152
 
125 153
 #if HAS_HOTEND_OFFSET
@@ -373,6 +401,9 @@ void menu_configuration() {
373 401
   //
374 402
   #if EXTRUDERS > 1
375 403
     SUBMENU(MSG_TOOL_CHANGE, menu_tool_change);
404
+    #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
405
+      SUBMENU(MSG_TOOL_MIGRATION, menu_toolchange_migration);
406
+    #endif
376 407
   #endif
377 408
 
378 409
   //

+ 20
- 4
Marlin/src/module/configuration_store.cpp View File

@@ -2423,16 +2423,32 @@ void MarlinSettings::reset() {
2423 2423
 
2424 2424
   #if EXTRUDERS > 1
2425 2425
     #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
2426
-      toolchange_settings.swap_length = TOOLCHANGE_FIL_SWAP_LENGTH;
2427
-      toolchange_settings.extra_prime = TOOLCHANGE_FIL_EXTRA_PRIME;
2428
-      toolchange_settings.prime_speed = TOOLCHANGE_FIL_SWAP_PRIME_SPEED;
2429
-      toolchange_settings.retract_speed = TOOLCHANGE_FIL_SWAP_RETRACT_SPEED;
2426
+      toolchange_settings.swap_length     = TOOLCHANGE_FS_LENGTH;
2427
+      toolchange_settings.extra_resume    = TOOLCHANGE_FS_EXTRA_RESUME_LENGTH;
2428
+      toolchange_settings.retract_speed   = TOOLCHANGE_FS_RETRACT_SPEED;
2429
+      toolchange_settings.unretract_speed = TOOLCHANGE_FS_UNRETRACT_SPEED;
2430
+      toolchange_settings.extra_prime     = TOOLCHANGE_FS_EXTRA_PRIME;
2431
+      toolchange_settings.prime_speed     = TOOLCHANGE_FS_PRIME_SPEED;
2432
+      toolchange_settings.fan_speed       = TOOLCHANGE_FS_FAN_SPEED;
2433
+      toolchange_settings.fan_time        = TOOLCHANGE_FS_FAN_TIME;
2430 2434
     #endif
2435
+
2436
+    #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
2437
+      enable_first_prime = false;
2438
+    #endif
2439
+
2431 2440
     #if ENABLED(TOOLCHANGE_PARK)
2432 2441
       constexpr xyz_pos_t tpxy = TOOLCHANGE_PARK_XY;
2442
+      toolchange_settings.enable_park = true;
2433 2443
       toolchange_settings.change_point = tpxy;
2434 2444
     #endif
2445
+
2435 2446
     toolchange_settings.z_raise = TOOLCHANGE_ZRAISE;
2447
+
2448
+    #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
2449
+      migration = migration_defaults;
2450
+    #endif
2451
+
2436 2452
   #endif
2437 2453
 
2438 2454
   #if ENABLED(BACKLASH_GCODE)

+ 7
- 5
Marlin/src/module/planner.h View File

@@ -423,12 +423,14 @@ class Planner {
423 423
 
424 424
     #if EXTRUDERS
425 425
       FORCE_INLINE static void refresh_e_factor(const uint8_t e) {
426
-        e_factor[e] = (flow_percentage[e] * 0.01f
427
-          #if DISABLED(NO_VOLUMETRICS)
428
-            * volumetric_multiplier[e]
429
-          #endif
430
-        );
426
+        e_factor[e] = flow_percentage[e] * 0.01f * TERN(NO_VOLUMETRICS, 1.0f, volumetric_multiplier[e]);
431 427
       }
428
+
429
+      static inline void set_flow(const uint8_t e, const int16_t flow) {
430
+        flow_percentage[e] = flow;
431
+        refresh_e_factor(e);
432
+      }
433
+
432 434
     #endif
433 435
 
434 436
     // Manage fans, paste pressure, etc.

+ 272
- 51
Marlin/src/module/tool_change.cpp View File

@@ -38,6 +38,15 @@
38 38
   toolchange_settings_t toolchange_settings;  // Initialized by settings.load()
39 39
 #endif
40 40
 
41
+#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
42
+  migration_settings_t migration = migration_defaults;
43
+  bool enable_first_prime;
44
+#endif
45
+
46
+#if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
47
+  bool toolchange_extruder_ready[EXTRUDERS];
48
+#endif
49
+
41 50
 #if ENABLED(SINGLENOZZLE)
42 51
   uint16_t singlenozzle_temp[EXTRUDERS];
43 52
   #if FAN_COUNT > 0
@@ -85,6 +94,14 @@
85 94
   #include "../feature/pause.h"
86 95
 #endif
87 96
 
97
+#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
98
+  #include "../gcode/gcode.h"
99
+  #if TOOLCHANGE_FS_WIPE_RETRACT <= 0
100
+    #undef TOOLCHANGE_FS_WIPE_RETRACT
101
+    #define TOOLCHANGE_FS_WIPE_RETRACT 0
102
+  #endif
103
+#endif
104
+
88 105
 #if DO_SWITCH_EXTRUDER
89 106
 
90 107
   #if EXTRUDERS > 3
@@ -760,6 +777,77 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a
760 777
 #endif // DUAL_X_CARRIAGE
761 778
 
762 779
 /**
780
+ * Prime active tool using TOOLCHANGE_FILAMENT_SWAP settings
781
+ */
782
+#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
783
+
784
+void tool_change_prime() {
785
+  if (toolchange_settings.extra_prime > 0
786
+    && TERN(PREVENT_COLD_EXTRUSION, !thermalManager.targetTooColdToExtrude(active_extruder), 1)
787
+  ) {
788
+    destination = current_position; // Remember the old position
789
+
790
+    const bool ok = TERN1(TOOLCHANGE_PARK, all_axes_homed() && toolchange_settings.enable_park);
791
+
792
+    // Z raise
793
+    if (ok) {
794
+      // Do a small lift to avoid the workpiece in the move back (below)
795
+      current_position.z += toolchange_settings.z_raise;
796
+      #if HAS_SOFTWARE_ENDSTOPS
797
+        NOMORE(current_position.z, soft_endstop.max.z);
798
+      #endif
799
+      fast_line_to_current(Z_AXIS);
800
+      planner.synchronize();
801
+    }
802
+
803
+    // Park
804
+    #if ENABLED(TOOLCHANGE_PARK)
805
+      if (ok) {
806
+        TERN(TOOLCHANGE_PARK_Y_ONLY,,current_position.x = toolchange_settings.change_point.x);
807
+        TERN(TOOLCHANGE_PARK_X_ONLY,,current_position.y = toolchange_settings.change_point.y);
808
+        planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), active_extruder);
809
+        planner.synchronize();
810
+      }
811
+    #endif
812
+
813
+    // Prime (All distances are added and slowed down to ensure secure priming in all circumstances)
814
+    unscaled_e_move(toolchange_settings.swap_length + toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed));
815
+
816
+    // Cutting retraction
817
+    #if TOOLCHANGE_FS_WIPE_RETRACT
818
+      unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
819
+    #endif
820
+
821
+    // Cool down with fan
822
+    #if TOOLCHANGE_FS_FAN >= 0 && FAN_COUNT > 0
823
+      const int16_t fansp = thermalManager.fan_speed[TOOLCHANGE_FS_FAN];
824
+      thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
825
+      safe_delay(toolchange_settings.fan_time * 1000);
826
+      thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = fansp;
827
+    #endif
828
+
829
+    // Move back
830
+    #if ENABLED(TOOLCHANGE_PARK)
831
+      if (ok) {
832
+        #if ENABLED(TOOLCHANGE_NO_RETURN)
833
+          do_blocking_move_to_z(destination.z, planner.settings.max_feedrate_mm_s[Z_AXIS]);
834
+        #else
835
+          do_blocking_move_to(destination, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE));
836
+        #endif
837
+      }
838
+    #endif
839
+
840
+    // Cutting recover
841
+    unscaled_e_move(toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT, MMM_TO_MMS(toolchange_settings.unretract_speed));
842
+
843
+    planner.synchronize();
844
+    current_position.e = destination.e;
845
+    sync_plan_position_e(); // Resume at the old E position
846
+  }
847
+}
848
+#endif
849
+
850
+/**
763 851
  * Perform a tool-change, which may result in moving the
764 852
  * previous tool out of the way and the new tool into place.
765 853
  */
@@ -826,39 +914,52 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
826 914
     const uint8_t old_tool = active_extruder;
827 915
     const bool can_move_away = !no_move && !idex_full_control;
828 916
 
829
-    #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
830
-      const bool should_swap = can_move_away && toolchange_settings.swap_length;
831
-      #if ENABLED(PREVENT_COLD_EXTRUSION)
832
-        const bool too_cold = !DEBUGGING(DRYRUN) && (thermalManager.targetTooColdToExtrude(old_tool) || thermalManager.targetTooColdToExtrude(new_tool));
833
-      #else
834
-        constexpr bool too_cold = false;
835
-      #endif
836
-      if (should_swap) {
837
-        if (too_cold) {
838
-          SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
839
-          #if ENABLED(SINGLENOZZLE)
840
-            active_extruder = new_tool;
841
-            return;
842
-          #endif
843
-        }
844
-        else {
845
-          #if ENABLED(ADVANCED_PAUSE_FEATURE)
846
-            unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed));
847
-          #else
848
-            current_position.e -= toolchange_settings.swap_length / planner.e_factor[old_tool];
849
-            planner.buffer_line(current_position, MMM_TO_MMS(toolchange_settings.retract_speed), old_tool);
850
-            planner.synchronize();
851
-          #endif
852
-        }
853
-      }
854
-    #endif // TOOLCHANGE_FILAMENT_SWAP
855
-
856 917
     #if HAS_LEVELING && DISABLED(SINGLENOZZLE)
857 918
       // Set current position to the physical position
858 919
       TEMPORARY_BED_LEVELING_STATE(false);
859 920
     #endif
860 921
 
922
+    // First tool priming. To prime again, reboot the machine.
923
+    #if BOTH(TOOLCHANGE_FILAMENT_SWAP, TOOLCHANGE_FS_PRIME_FIRST_USED)
924
+      static bool first_tool_is_primed = false;
925
+      if (new_tool == old_tool && !first_tool_is_primed && enable_first_prime) {
926
+        tool_change_prime();
927
+        first_tool_is_primed = true;
928
+        toolchange_extruder_ready[old_tool] = true; // Primed and initialized
929
+      }
930
+    #endif
931
+
861 932
     if (new_tool != old_tool) {
933
+      destination = current_position;
934
+
935
+      // Z raise before retraction
936
+      #if ENABLED(TOOLCHANGE_ZRAISE_BEFORE_RETRACT) && DISABLED(SWITCHING_NOZZLE)
937
+        if (can_move_away && TERN1(toolchange_settings.enable_park)) {
938
+          // Do a small lift to avoid the workpiece in the move back (below)
939
+          current_position.z += toolchange_settings.z_raise;
940
+          #if HAS_SOFTWARE_ENDSTOPS
941
+            NOMORE(current_position.z, soft_endstop.max.z);
942
+          #endif
943
+          fast_line_to_current(Z_AXIS);
944
+          planner.synchronize();
945
+        }
946
+      #endif
947
+
948
+      // Unload / Retract
949
+      #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
950
+        const bool should_swap = can_move_away && toolchange_settings.swap_length;
951
+                   too_cold = TERN0(PREVENT_COLD_EXTRUSION,
952
+                     !DEBUGGING(DRYRUN) && (thermalManager.targetTooColdToExtrude(old_tool) || thermalManager.targetTooColdToExtrude(new_tool))
953
+                   );
954
+        if (should_swap) {
955
+          if (too_cold) {
956
+            SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD);
957
+            if (ENABLED(SINGLENOZZLE)) { active_extruder = new_tool; return; }
958
+          }
959
+          else
960
+            unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed));
961
+        }
962
+      #endif
862 963
 
863 964
       TERN_(SWITCHING_NOZZLE_TWO_SERVOS, raise_nozzle(old_tool));
864 965
 
@@ -877,18 +978,23 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
877 978
         #endif
878 979
       #endif
879 980
 
880
-      destination = current_position;
881
-
882
-      #if DISABLED(SWITCHING_NOZZLE)
883
-        if (can_move_away) {
981
+      #if DISABLED(TOOLCHANGE_ZRAISE_BEFORE_RETRACT) && DISABLED(SWITCHING_NOZZLE)
982
+        if (can_move_away && TERN1(TOOLCHANGE_PARK, toolchange_settings.enable_park)) {
884 983
           // Do a small lift to avoid the workpiece in the move back (below)
885 984
           current_position.z += toolchange_settings.z_raise;
886 985
           #if HAS_SOFTWARE_ENDSTOPS
887 986
             NOMORE(current_position.z, soft_endstop.max.z);
888 987
           #endif
889 988
           fast_line_to_current(Z_AXIS);
890
-          TERN_(TOOLCHANGE_PARK, current_position = toolchange_settings.change_point);
891
-          planner.buffer_line(current_position, feedrate_mm_s, old_tool);
989
+        }
990
+      #endif
991
+
992
+      // Toolchange park
993
+      #if ENABLED(TOOLCHANGE_PARK) && DISABLED(SWITCHING_NOZZLE)
994
+        if (can_move_away && toolchange_settings.enable_park) {
995
+          TERN(TOOLCHANGE_PARK_Y_ONLY,,current_position.x = toolchange_settings.change_point.x);
996
+          TERN(TOOLCHANGE_PARK_X_ONLY,,current_position.y = toolchange_settings.change_point.y);
997
+          planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), old_tool);
892 998
           planner.synchronize();
893 999
         }
894 1000
       #endif
@@ -932,9 +1038,8 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
932 1038
         move_nozzle_servo(new_tool);
933 1039
       #endif
934 1040
 
935
-      #if DISABLED(DUAL_X_CARRIAGE)
936
-        active_extruder = new_tool; // Set the new active extruder
937
-      #endif
1041
+      // Set the new active extruder
1042
+      if (DISABLED(DUAL_X_CARRIAGE)) active_extruder = new_tool;
938 1043
 
939 1044
       // The newly-selected extruder XYZ is actually at...
940 1045
       if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Offset Tool XYZ by { ", diff.x, ", ", diff.y, ", ", diff.z, " }");
@@ -951,7 +1056,8 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
951 1056
       #endif
952 1057
 
953 1058
       // Return to position and lower again
954
-      if (safe_to_move && !no_move && IsRunning()) {
1059
+      const bool should_move = safe_to_move && !no_move && IsRunning();
1060
+      if (should_move) {
955 1061
 
956 1062
         #if ENABLED(SINGLENOZZLE)
957 1063
           #if FAN_COUNT > 0
@@ -969,17 +1075,35 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
969 1075
 
970 1076
         #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
971 1077
           if (should_swap && !too_cold) {
972
-            #if ENABLED(ADVANCED_PAUSE_FEATURE)
973
-              unscaled_e_move(toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.prime_speed));
974
-              unscaled_e_move(toolchange_settings.extra_prime, ADVANCED_PAUSE_PURGE_FEEDRATE);
975
-            #else
976
-              current_position.e += toolchange_settings.swap_length / planner.e_factor[new_tool];
977
-              planner.buffer_line(current_position, MMM_TO_MMS(toolchange_settings.prime_speed), new_tool);
978
-              current_position.e += toolchange_settings.extra_prime / planner.e_factor[new_tool];
979
-              planner.buffer_line(current_position, MMM_TO_MMS(toolchange_settings.prime_speed * 0.2f), new_tool);
1078
+
1079
+            float fr = toolchange_settings.unretract_speed;
1080
+
1081
+            #if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
1082
+              if (!toolchange_extruder_ready[new_tool]) {
1083
+                toolchange_extruder_ready[new_tool] = true;
1084
+                fr = toolchange_settings.prime_speed;       // Next move is a prime
1085
+                unscaled_e_move(0, MMM_TO_MMS(fr));         // Init planner with 0 length move
1086
+              }
1087
+            #endif
1088
+
1089
+            // Unretract (or Prime)
1090
+            unscaled_e_move(toolchange_settings.swap_length, MMM_TO_MMS(fr));
1091
+
1092
+            // Extra Prime
1093
+            unscaled_e_move(toolchange_settings.extra_prime, MMM_TO_MMS(toolchange_settings.prime_speed));
1094
+
1095
+            // Cutting retraction
1096
+            #if TOOLCHANGE_FS_WIPE_RETRACT
1097
+              unscaled_e_move(-(TOOLCHANGE_FS_WIPE_RETRACT), MMM_TO_MMS(toolchange_settings.retract_speed));
1098
+            #endif
1099
+
1100
+            // Cool down with fan
1101
+            #if TOOLCHANGE_FS_FAN >= 0 && FAN_COUNT > 0
1102
+              const int16_t fansp = thermalManager.fan_speed[TOOLCHANGE_FS_FAN];
1103
+              thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed;
1104
+              safe_delay(toolchange_settings.fan_time * 1000);
1105
+              thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = fansp;
980 1106
             #endif
981
-            planner.synchronize();
982
-            planner.set_e_position_mm((destination.e = current_position.e = current_position.e - (TOOLCHANGE_FIL_EXTRA_PRIME)));
983 1107
           }
984 1108
         #endif
985 1109
 
@@ -1000,22 +1124,43 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
1000 1124
           #if ENABLED(TOOLCHANGE_NO_RETURN)
1001 1125
             // Just move back down
1002 1126
             if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move back Z only");
1127
+
1128
+            #if ENABLED(TOOLCHANGE_PARK)
1129
+              if (toolchange_settings.enable_park)
1130
+            #endif
1003 1131
             do_blocking_move_to_z(destination.z, planner.settings.max_feedrate_mm_s[Z_AXIS]);
1132
+
1004 1133
           #else
1005 1134
             // Move back to the original (or adjusted) position
1006 1135
             if (DEBUGGING(LEVELING)) DEBUG_POS("Move back", destination);
1007
-            do_blocking_move_to(destination);
1136
+
1137
+            #if ENABLED(TOOLCHANGE_PARK)
1138
+              if (toolchange_settings.enable_park) do_blocking_move_to_xy_z(destination, destination.z, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE));
1139
+            #else
1140
+              do_blocking_move_to_xy(destination);
1141
+            #endif
1142
+
1008 1143
           #endif
1009 1144
         }
1145
+
1010 1146
         else if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Move back skipped");
1011 1147
 
1148
+        #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
1149
+          if (should_swap && !too_cold) {
1150
+            // Cutting recover
1151
+            unscaled_e_move(toolchange_settings.extra_resume + TOOLCHANGE_FS_WIPE_RETRACT, MMM_TO_MMS(toolchange_settings.unretract_speed));
1152
+            current_position.e = 0;
1153
+            sync_plan_position_e(); // New extruder primed and set to 0
1154
+          }
1155
+        #endif
1156
+
1012 1157
         TERN_(DUAL_X_CARRIAGE, active_extruder_parked = false);
1013 1158
       }
1159
+
1014 1160
       #if ENABLED(SWITCHING_NOZZLE)
1015
-        else {
1016
-          // Move back down. (Including when the new tool is higher.)
1161
+        // Move back down. (Including when the new tool is higher.)
1162
+        if (!should_move)
1017 1163
           do_blocking_move_to_z(destination.z, planner.settings.max_feedrate_mm_s[Z_AXIS]);
1018
-        }
1019 1164
       #endif
1020 1165
 
1021 1166
       TERN_(PRUSA_MMU2, mmu2.tool_change(new_tool));
@@ -1053,3 +1198,79 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
1053 1198
 
1054 1199
   #endif // EXTRUDERS > 1
1055 1200
 }
1201
+
1202
+#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
1203
+
1204
+  void extruder_migration() {
1205
+
1206
+    #if ENABLED(PREVENT_COLD_EXTRUSION)
1207
+      if (thermalManager.targetTooColdToExtrude(active_extruder)) return;
1208
+    #endif
1209
+
1210
+    // No auto-migration or specified target?
1211
+    if (!migration.target && active_extruder >= migration.last) {
1212
+      migration.automode = false;
1213
+      return;
1214
+    }
1215
+
1216
+    // Migrate to a target or the next extruder
1217
+
1218
+    uint8_t migration_extruder = active_extruder;
1219
+
1220
+    if (migration.target) {
1221
+      // Specified target ok?
1222
+      const int16_t t = migration.target - 1;
1223
+      if (t != active_extruder) migration_extruder = t;
1224
+    }
1225
+    else if (migration.automode && migration_extruder < migration.last && migration_extruder < EXTRUDERS - 1)
1226
+      migration_extruder++;
1227
+
1228
+    if (migration_extruder == active_extruder) return;
1229
+
1230
+    // Migration begins
1231
+
1232
+    migration.in_progress = true; // Prevent runout script
1233
+    planner.synchronize();
1234
+
1235
+    // Remember position before migration
1236
+    const float resume_current_e = current_position.e;
1237
+
1238
+    // Migrate the flow
1239
+    planner.set_flow(migration_extruder, planner.flow_percentage[active_extruder]);
1240
+
1241
+    // Migrate the retracted state
1242
+    #if ENABLED(FWRETRACT)
1243
+      fwretract.retracted[migration_extruder] = fwretract.retracted[active_extruder];
1244
+    #endif
1245
+
1246
+    // Migrate the temperature to the new hotend
1247
+    #if HOTENDS > 1
1248
+      thermalManager.setTargetHotend(thermalManager.degTargetHotend(active_extruder), migration_extruder);
1249
+      #if HAS_DISPLAY
1250
+        thermalManager.set_heating_message(0);
1251
+      #endif
1252
+      thermalManager.wait_for_hotend(active_extruder);
1253
+    #endif
1254
+
1255
+    // Perform the tool change
1256
+    tool_change(migration_extruder);
1257
+
1258
+    // Retract if previously retracted
1259
+    #if ENABLED(FWRETRACT)
1260
+      if (fwretract.retracted[active_extruder])
1261
+        unscaled_e_move(-fwretract.settings.retract_length, fwretract.settings.retract_feedrate_mm_s);
1262
+    #endif
1263
+
1264
+    // If no available extruder
1265
+    if (EXTRUDERS < 2 || active_extruder >= EXTRUDERS - 2 || active_extruder == migration.last)
1266
+      migration.automode = false;
1267
+
1268
+    migration.in_progress = false;
1269
+
1270
+    current_position.e = resume_current_e;
1271
+
1272
+    planner.synchronize();
1273
+    planner.set_e_position_mm(current_position.e); // New extruder primed and ready
1274
+  }
1275
+
1276
+#endif // TOOLCHANGE_MIGRATION_FEATURE

+ 27
- 3
Marlin/src/module/tool_change.h View File

@@ -28,15 +28,39 @@
28 28
 
29 29
   typedef struct {
30 30
     #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
31
-      float swap_length, extra_prime;
32
-      int16_t prime_speed, retract_speed;
31
+      float swap_length, extra_prime, extra_resume;
32
+      int16_t prime_speed, retract_speed, unretract_speed, fan, fan_speed, fan_time;
33
+    #endif
34
+    #if ENABLED(TOOLCHANGE_PARK)
35
+      bool enable_park;
36
+      xy_pos_t change_point;
33 37
     #endif
34
-    TERN_(TOOLCHANGE_PARK, xy_pos_t change_point);
35 38
     float z_raise;
36 39
   } toolchange_settings_t;
37 40
 
38 41
   extern toolchange_settings_t toolchange_settings;
39 42
 
43
+  #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
44
+    extern void tool_change_prime();
45
+  #endif
46
+
47
+  #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
48
+    extern bool enable_first_prime;
49
+  #endif
50
+
51
+  #if ENABLED(TOOLCHANGE_FS_INIT_BEFORE_SWAP)
52
+    extern bool toolchange_extruder_ready[EXTRUDERS];
53
+  #endif
54
+
55
+  #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
56
+    typedef struct {
57
+      uint8_t target, last;
58
+      bool automode, in_progress;
59
+    } migration_settings_t;
60
+    constexpr migration_settings_t migration_defaults = { 0, 0, false, false };
61
+    extern migration_settings_t migration;
62
+    void extruder_migration();
63
+  #endif
40 64
 #endif
41 65
 
42 66
 #if DO_SWITCH_EXTRUDER

+ 1
- 0
buildroot/share/tests/BIGTREE_GTR_V1_0-tests View File

@@ -33,6 +33,7 @@ opt_set TEMP_SENSOR_3 1
33 33
 opt_set TEMP_SENSOR_4 1
34 34
 opt_set TEMP_SENSOR_5 1
35 35
 opt_set NUM_Z_STEPPER_DRIVERS 3
36
+opt_enable TOOLCHANGE_FILAMENT_SWAP TOOLCHANGE_MIGRATION_FEATURE TOOLCHANGE_FS_INIT_BEFORE_SWAP TOOLCHANGE_FS_PRIME_FIRST_USED
36 37
 exec_test $1 $2 "BigTreeTech GTR 6 Extruders Triple Z"
37 38
 
38 39
 # clean up

Loading…
Cancel
Save