|
@@ -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
|