Switching extruder/nozzle without servo (e.g., Dondolo) (#24553)

Co-authored-by: Anson Liu <ansonl@users.noreply.github.com>
This commit is contained in:
EvilGremlin
2023-03-04 05:43:20 +03:00
committed by GitHub
parent f359f8818a
commit e977232735
11 changed files with 145 additions and 66 deletions

View File

@@ -270,7 +270,13 @@
#endif
#endif
// A dual-nozzle that uses a servomotor to raise/lower one (or both) of the nozzles
// Switch extruders by bumping the toolhead. Requires EVENT_GCODE_TOOLCHANGE_#.
//#define MECHANICAL_SWITCHING_EXTRUDER
/**
* A dual-nozzle that uses a servomotor to raise/lower one (or both) of the nozzles.
* Can be combined with SWITCHING_EXTRUDER.
*/
//#define SWITCHING_NOZZLE
#if ENABLED(SWITCHING_NOZZLE)
#define SWITCHING_NOZZLE_SERVO_NR 0
@@ -279,6 +285,9 @@
#define SWITCHING_NOZZLE_SERVO_DWELL 2500 // Dwell time to wait for servo to make physical move
#endif
// Switch nozzles by bumping the toolhead. Requires EVENT_GCODE_TOOLCHANGE_#.
//#define MECHANICAL_SWITCHING_NOZZLE
/**
* Two separate X-carriages with extruders that connect to a moving part
* via a solenoid docking mechanism. Requires SOL1_PIN and SOL2_PIN.

View File

@@ -669,7 +669,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
&& ELAPSED(ms, gcode.previous_move_ms + SEC_TO_MS(EXTRUDER_RUNOUT_SECONDS))
&& !planner.has_blocks_queued()
) {
#if ENABLED(SWITCHING_EXTRUDER)
#if HAS_SWITCHING_EXTRUDER
bool oldstatus;
switch (active_extruder) {
default: oldstatus = stepper.AXIS_IS_ENABLED(E_AXIS, 0); stepper.ENABLE_EXTRUDER(0); break;
@@ -683,7 +683,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
#endif // E_STEPPERS > 2
#endif // E_STEPPERS > 1
}
#else // !SWITCHING_EXTRUDER
#else // !HAS_SWITCHING_EXTRUDER
bool oldstatus;
switch (active_extruder) {
default:
@@ -699,7 +699,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
planner.set_e_position_mm(olde);
planner.synchronize();
#if ENABLED(SWITCHING_EXTRUDER)
#if HAS_SWITCHING_EXTRUDER
switch (active_extruder) {
default: if (oldstatus) stepper.ENABLE_EXTRUDER(0); else stepper.DISABLE_EXTRUDER(0); break;
#if E_STEPPERS > 1
@@ -709,12 +709,12 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
#endif // E_STEPPERS > 2
#endif // E_STEPPERS > 1
}
#else // !SWITCHING_EXTRUDER
#else // !HAS_SWITCHING_EXTRUDER
switch (active_extruder) {
#define _CASE_RESTORE(N) case N: if (oldstatus) stepper.ENABLE_EXTRUDER(N); else stepper.DISABLE_EXTRUDER(N); break;
REPEAT(E_STEPPERS, _CASE_RESTORE);
}
#endif // !SWITCHING_EXTRUDER
#endif // !HAS_SWITCHING_EXTRUDER
gcode.reset_stepper_timeout(ms);
}

View File

@@ -613,7 +613,9 @@
#undef TEMP_SENSOR_7
#undef SINGLENOZZLE
#undef SWITCHING_EXTRUDER
#undef MECHANICAL_SWITCHING_EXTRUDER
#undef SWITCHING_NOZZLE
#undef MECHANICAL_SWITCHING_NOZZLE
#undef MIXING_EXTRUDER
#undef HOTEND_IDLE_TIMEOUT
#undef DISABLE_E
@@ -629,12 +631,19 @@
#define E_TERN_(N) TERN_(HAS_MULTI_EXTRUDER, N)
#define E_TERN0(N) TERN0(HAS_MULTI_EXTRUDER, N)
#if EITHER(SWITCHING_EXTRUDER, MECHANICAL_SWITCHING_EXTRUDER)
#define HAS_SWITCHING_EXTRUDER 1
#endif
#if EITHER(SWITCHING_NOZZLE, MECHANICAL_SWITCHING_NOZZLE)
#define HAS_SWITCHING_NOZZLE 1
#endif
#if ENABLED(E_DUAL_STEPPER_DRIVERS) // E0/E1 steppers act in tandem as E0
#define E_STEPPERS 2
#define E_MANUAL 1
#elif ENABLED(SWITCHING_EXTRUDER) // One stepper for every two EXTRUDERS
#elif HAS_SWITCHING_EXTRUDER // One stepper for every two EXTRUDERS
#if EXTRUDERS > 4
#define E_STEPPERS 3
@@ -643,7 +652,7 @@
#else
#define E_STEPPERS 1
#endif
#if DISABLED(SWITCHING_NOZZLE)
#if !HAS_SWITCHING_NOZZLE
#define HOTENDS E_STEPPERS
#endif
@@ -668,7 +677,7 @@
#endif
// No inactive extruders with SWITCHING_NOZZLE or Průša MMU1
#if ENABLED(SWITCHING_NOZZLE) || HAS_PRUSA_MMU1
#if HAS_SWITCHING_NOZZLE || HAS_PRUSA_MMU1
#undef DISABLE_INACTIVE_EXTRUDER
#endif
@@ -1064,7 +1073,7 @@
#endif
// Switching extruder has its own servo?
#if ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR)
#if ENABLED(SWITCHING_EXTRUDER) && (!HAS_SWITCHING_NOZZLE || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR)
#define DO_SWITCH_EXTRUDER 1
#endif

View File

@@ -30,26 +30,26 @@
#define AXIS_RELATIVE_MODES {}
#endif
#ifdef SWITCHING_NOZZLE_E1_SERVO_NR
#if defined(SWITCHING_NOZZLE_E1_SERVO_NR) && DISABLED(MECHANICAL_SWITCHING_NOZZLE)
#define SWITCHING_NOZZLE_TWO_SERVOS 1
#endif
// Determine NUM_SERVOS if none was supplied
#ifndef NUM_SERVOS
#define NUM_SERVOS 0
#if ANY(HAS_Z_SERVO_PROBE, CHAMBER_VENT, SWITCHING_TOOLHEAD, SWITCHING_EXTRUDER, SWITCHING_NOZZLE, SPINDLE_SERVO)
#if NUM_SERVOS <= Z_PROBE_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (Z_PROBE_SERVO_NR + 1)
#endif
#if NUM_SERVOS <= CHAMBER_VENT_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (CHAMBER_VENT_SERVO_NR + 1)
#endif
#if NUM_SERVOS <= SWITCHING_TOOLHEAD_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (SWITCHING_TOOLHEAD_SERVO_NR + 1)
#endif
#if HAS_Z_SERVO_PROBE && NUM_SERVOS <= Z_PROBE_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (Z_PROBE_SERVO_NR + 1)
#endif
#if ENABLED(CHAMBER_VENT) && NUM_SERVOS <= CHAMBER_VENT_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (CHAMBER_VENT_SERVO_NR + 1)
#endif
#if ENABLED(SWITCHING_TOOLHEAD) && NUM_SERVOS <= SWITCHING_TOOLHEAD_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (SWITCHING_TOOLHEAD_SERVO_NR + 1)
#endif
#if ENABLED(SWITCHING_NOZZLE)
#if NUM_SERVOS <= SWITCHING_NOZZLE_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (SWITCHING_NOZZLE_SERVO_NR + 1)
@@ -58,6 +58,8 @@
#undef NUM_SERVOS
#define NUM_SERVOS (SWITCHING_NOZZLE_E1_SERVO_NR + 1)
#endif
#endif
#if ENABLED(SWITCHING_EXTRUDER)
#if NUM_SERVOS <= SWITCHING_EXTRUDER_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (SWITCHING_EXTRUDER_SERVO_NR + 1)
@@ -66,12 +68,12 @@
#undef NUM_SERVOS
#define NUM_SERVOS (SWITCHING_EXTRUDER_E23_SERVO_NR + 1)
#endif
#if NUM_SERVOS <= SPINDLE_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (SPINDLE_SERVO_NR + 1)
#endif
#endif
#endif
#if ENABLED(SPINDLE_SERVO) && NUM_SERVOS <= SPINDLE_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (SPINDLE_SERVO_NR + 1)
#endif
#endif // !defined(NUM_SERVOS)
// Convenience override for a BLTouch alone
#if ENABLED(BLTOUCH) && NUM_SERVOS == 1

View File

@@ -1269,20 +1269,34 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
/**
* A Dual Nozzle carriage with switching servo
*/
#if ENABLED(SWITCHING_NOZZLE)
#if ENABLED(DUAL_X_CARRIAGE)
#if BOTH(SWITCHING_NOZZLE, MECHANICAL_SWITCHING_NOZZLE)
#error "Enable only one of SWITCHING_NOZZLE or MECHANICAL_SWITCHING_NOZZLE."
#elif ENABLED(MECHANICAL_SWITCHING_NOZZLE)
#if EXTRUDERS != 2
#error "MECHANICAL_SWITCHING_NOZZLE requires exactly 2 EXTRUDERS."
#elif ENABLED(DUAL_X_CARRIAGE)
#error "MECHANICAL_SWITCHING_NOZZLE and DUAL_X_CARRIAGE are incompatible."
#elif ENABLED(SINGLENOZZLE)
#error "MECHANICAL_SWITCHING_NOZZLE and SINGLENOZZLE are incompatible."
#elif HAS_PRUSA_MMU2
#error "MECHANICAL_SWITCHING_NOZZLE and PRUSA_MMU2(S) are incompatible."
#elif !defined(EVENT_GCODE_TOOLCHANGE_T0)
#error "MECHANICAL_SWITCHING_NOZZLE requires EVENT_GCODE_TOOLCHANGE_T0."
#elif !defined(EVENT_GCODE_TOOLCHANGE_T1)
#error "MECHANICAL_SWITCHING_NOZZLE requires EVENT_GCODE_TOOLCHANGE_T1."
#endif
#elif ENABLED(SWITCHING_NOZZLE)
#if EXTRUDERS != 2
#error "SWITCHING_NOZZLE requires exactly 2 EXTRUDERS."
#elif ENABLED(DUAL_X_CARRIAGE)
#error "SWITCHING_NOZZLE and DUAL_X_CARRIAGE are incompatible."
#elif ENABLED(SINGLENOZZLE)
#error "SWITCHING_NOZZLE and SINGLENOZZLE are incompatible."
#elif HAS_PRUSA_MMU2
#error "SWITCHING_NOZZLE and PRUSA_MMU2(S) are incompatible."
#elif EXTRUDERS != 2
#error "SWITCHING_NOZZLE requires exactly 2 EXTRUDERS."
#elif NUM_SERVOS < 1
#error "SWITCHING_NOZZLE requires NUM_SERVOS >= 1."
#endif
#ifndef SWITCHING_NOZZLE_SERVO_NR
#elif !defined(SWITCHING_NOZZLE_SERVO_NR)
#error "SWITCHING_NOZZLE requires SWITCHING_NOZZLE_SERVO_NR."
#elif SWITCHING_NOZZLE_SERVO_NR == 0 && !PIN_EXISTS(SERVO0)
#error "SERVO0_PIN must be defined for your SWITCHING_NOZZLE."
@@ -1293,7 +1307,6 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#elif SWITCHING_NOZZLE_SERVO_NR == 3 && !PIN_EXISTS(SERVO3)
#error "SERVO3_PIN must be defined for your SWITCHING_NOZZLE."
#endif
#ifdef SWITCHING_NOZZLE_E1_SERVO_NR
#if SWITCHING_NOZZLE_E1_SERVO_NR == SWITCHING_NOZZLE_SERVO_NR
#error "SWITCHING_NOZZLE_E1_SERVO_NR must be different from SWITCHING_NOZZLE_SERVO_NR."
@@ -1307,14 +1320,26 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#error "SERVO3_PIN must be defined for your SWITCHING_NOZZLE."
#endif
#endif
#endif
#endif // SWITCHING_NOZZLE
/**
* Single Stepper Dual Extruder with switching servo
*/
#if ENABLED(SWITCHING_EXTRUDER)
#if BOTH(SWITCHING_EXTRUDER, MECHANICAL_SWITCHING_EXTRUDER)
#error "Enable only one of SWITCHING_EXTRUDER or MECHANICAL_SWITCHING_EXTRUDER."
#elif ENABLED(MECHANICAL_SWITCHING_EXTRUDER)
#if EXTRUDERS < 2
#error "MECHANICAL_SWITCHING_EXTRUDER requires EXTRUDERS >= 2."
#elif !defined(EVENT_GCODE_TOOLCHANGE_T0)
#error "MECHANICAL_SWITCHING_EXTRUDER requires EVENT_GCODE_TOOLCHANGE_T0."
#elif !defined(EVENT_GCODE_TOOLCHANGE_T1)
#error "MECHANICAL_SWITCHING_EXTRUDER requires EVENT_GCODE_TOOLCHANGE_T1."
#endif
#elif ENABLED(SWITCHING_EXTRUDER)
#if NUM_SERVOS < 1
#error "SWITCHING_EXTRUDER requires NUM_SERVOS >= 1."
#elif !defined(SWITCHING_EXTRUDER_SERVO_NR)
#error "SWITCHING_EXTRUDER requires SWITCHING_EXTRUDER_SERVO_NR."
#elif SWITCHING_EXTRUDER_SERVO_NR == 0 && !PIN_EXISTS(SERVO0)
#error "SERVO0_PIN must be defined for your SWITCHING_EXTRUDER."
#elif SWITCHING_EXTRUDER_SERVO_NR == 1 && !PIN_EXISTS(SERVO1)
@@ -1338,8 +1363,10 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#elif SWITCHING_EXTRUDER_E23_SERVO_NR == SWITCHING_EXTRUDER_SERVO_NR
#error "SWITCHING_EXTRUDER_E23_SERVO_NR should be a different extruder from SWITCHING_EXTRUDER_SERVO_NR."
#endif
#elif EXTRUDERS < 2
#error "SWITCHING_EXTRUDER requires EXTRUDERS >= 2."
#endif
#endif
#endif // SWITCHING_EXTRUDER
/**
* Mixing Extruder requirements
@@ -1351,8 +1378,8 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#error "You must set MIXING_STEPPERS >= 2 for a mixing extruder."
#elif ENABLED(FILAMENT_WIDTH_SENSOR)
#error "MIXING_EXTRUDER is incompatible with FILAMENT_WIDTH_SENSOR. Comment out this line to use it anyway."
#elif ENABLED(SWITCHING_EXTRUDER)
#error "Please select either MIXING_EXTRUDER or SWITCHING_EXTRUDER, not both."
#elif HAS_SWITCHING_EXTRUDER
#error "MIXING_EXTRUDER is incompatible with (MECHANICAL_)SWITCHING_EXTRUDER."
#elif ENABLED(SINGLENOZZLE)
#error "MIXING_EXTRUDER is incompatible with SINGLENOZZLE."
#elif ENABLED(DISABLE_INACTIVE_EXTRUDER)
@@ -1370,8 +1397,8 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#error "E_DUAL_STEPPER_DRIVERS can only be used with EXTRUDERS set to 1."
#elif ENABLED(MIXING_EXTRUDER)
#error "E_DUAL_STEPPER_DRIVERS is incompatible with MIXING_EXTRUDER."
#elif ENABLED(SWITCHING_EXTRUDER)
#error "E_DUAL_STEPPER_DRIVERS is incompatible with SWITCHING_EXTRUDER."
#elif HAS_SWITCHING_EXTRUDER
#error "E_DUAL_STEPPER_DRIVERS is incompatible with (MECHANICAL_)SWITCHING_EXTRUDER."
#endif
#endif
@@ -2733,8 +2760,8 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#error "MULTI_NOZZLE_DUPLICATION is incompatible with DUAL_X_CARRIAGE."
#elif ENABLED(MIXING_EXTRUDER)
#error "MULTI_NOZZLE_DUPLICATION is incompatible with MIXING_EXTRUDER."
#elif ENABLED(SWITCHING_EXTRUDER)
#error "MULTI_NOZZLE_DUPLICATION is incompatible with SWITCHING_EXTRUDER."
#elif HAS_SWITCHING_EXTRUDER
#error "MULTI_NOZZLE_DUPLICATION is incompatible with (MECHANICAL_)SWITCHING_EXTRUDER."
#elif HOTENDS < 2
#error "MULTI_NOZZLE_DUPLICATION requires 2 or more hotends."
#endif

View File

@@ -232,7 +232,7 @@ void menu_move() {
else
GCODES_ITEM(MSG_AUTO_HOME, FPSTR(G28_STR));
#if ANY(SWITCHING_EXTRUDER, SWITCHING_NOZZLE, MAGNETIC_SWITCHING_TOOLHEAD)
#if ANY(HAS_SWITCHING_EXTRUDER, HAS_SWITCHING_NOZZLE, MAGNETIC_SWITCHING_TOOLHEAD)
#if EXTRUDERS >= 4
switch (active_extruder) {
@@ -265,7 +265,7 @@ void menu_move() {
#define SUBMENU_MOVE_E(N) SUBMENU_N(N, MSG_MOVE_EN, []{ _menu_move_distance(E_AXIS, []{ lcd_move_e(N); }, N); });
#if EITHER(SWITCHING_EXTRUDER, SWITCHING_NOZZLE)
#if HAS_SWITCHING_EXTRUDER || HAS_SWITCHING_NOZZLE
// ...and the non-switching
#if E_MANUAL == 7 || E_MANUAL == 5 || E_MANUAL == 3

View File

@@ -2283,7 +2283,7 @@ bool Planner::_populate_block(
if (g_uc_extruder_last_move[i]) g_uc_extruder_last_move[i]--;
// Switching Extruder uses one E stepper motor per two nozzles
#define E_STEPPER_INDEX(E) TERN(SWITCHING_EXTRUDER, (E) / 2, E)
#define E_STEPPER_INDEX(E) TERN(HAS_SWITCHING_EXTRUDER, (E) / 2, E)
// Enable all (i.e., both) E steppers for IDEX-style duplication, but only active E steppers for multi-nozzle (i.e., single wide X carriage) duplication
#define _IS_DUPE(N) TERN0(HAS_DUPLICATION_MODE, (extruder_duplication_enabled && TERN1(MULTI_NOZZLE_DUPLICATION, TEST(duplication_e_mask, N))))

View File

@@ -454,7 +454,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
/**
* Extruder indirection for the single E axis
*/
#if ENABLED(SWITCHING_EXTRUDER) // One stepper driver per two extruders, reversed on odd index
#if HAS_SWITCHING_EXTRUDER // One stepper driver per two extruders, reversed on odd index
#if EXTRUDERS > 7
#define E_STEP_WRITE(E,V) do{ if (E < 2) { E0_STEP_WRITE(V); } else if (E < 4) { E1_STEP_WRITE(V); } else if (E < 6) { E2_STEP_WRITE(V); } else { E3_STEP_WRITE(V); } }while(0)
#define NORM_E_DIR(E) do{ switch (E) { \

View File

@@ -748,7 +748,7 @@ class Temperature {
static raw_adc_t mintemp_raw_COOLER, maxtemp_raw_COOLER;
#endif
#if HAS_TEMP_BOARD && ENABLED(THERMAL_PROTECTION_BOARD)
#if BOTH(HAS_TEMP_BOARD, THERMAL_PROTECTION_BOARD)
static raw_adc_t mintemp_raw_BOARD, maxtemp_raw_BOARD;
#endif

View File

@@ -1173,7 +1173,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
#endif
// Z raise before retraction
#if ENABLED(TOOLCHANGE_ZRAISE_BEFORE_RETRACT) && DISABLED(SWITCHING_NOZZLE)
#if ENABLED(TOOLCHANGE_ZRAISE_BEFORE_RETRACT) && !HAS_SWITCHING_NOZZLE
if (can_move_away && TERN1(TOOLCHANGE_PARK, toolchange_settings.enable_park)) {
// Do a small lift to avoid the workpiece in the move back (below)
current_position.z += toolchange_settings.z_raise;
@@ -1217,7 +1217,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
#endif
#endif
#if DISABLED(TOOLCHANGE_ZRAISE_BEFORE_RETRACT) && DISABLED(SWITCHING_NOZZLE)
#if NONE(TOOLCHANGE_ZRAISE_BEFORE_RETRACT, HAS_SWITCHING_NOZZLE)
if (can_move_away && TERN1(TOOLCHANGE_PARK, toolchange_settings.enable_park)) {
// Do a small lift to avoid the workpiece in the move back (below)
current_position.z += toolchange_settings.z_raise;
@@ -1227,7 +1227,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
#endif
// Toolchange park
#if ENABLED(TOOLCHANGE_PARK) && DISABLED(SWITCHING_NOZZLE)
#if ENABLED(TOOLCHANGE_PARK) && !HAS_SWITCHING_NOZZLE
if (can_move_away && toolchange_settings.enable_park) {
IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x);
IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y);
@@ -1279,6 +1279,11 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
fast_line_to_current(Z_AXIS);
}
move_nozzle_servo(new_tool);
#elif EITHER(MECHANICAL_SWITCHING_EXTRUDER, MECHANICAL_SWITCHING_NOZZLE)
if (!no_move) {
current_position.z = _MIN(current_position.z + toolchange_settings.z_raise, _MIN(TERN(HAS_SOFTWARE_ENDSTOPS, soft_endstop.max.z, Z_MAX_POS), Z_MAX_POS));
fast_line_to_current(Z_AXIS);
}
#endif
IF_DISABLED(DUAL_X_CARRIAGE, active_extruder = new_tool); // Set the new active extruder
@@ -1343,15 +1348,19 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
if (toolchange_settings.enable_park) do_blocking_move_to_xy_z(destination, destination.z, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE));
#else
do_blocking_move_to_xy(destination, planner.settings.max_feedrate_mm_s[X_AXIS]);
do_blocking_move_to_z(destination.z, planner.settings.max_feedrate_mm_s[Z_AXIS]);
SECONDARY_AXIS_CODE(
do_blocking_move_to_i(destination.i, planner.settings.max_feedrate_mm_s[I_AXIS]),
do_blocking_move_to_j(destination.j, planner.settings.max_feedrate_mm_s[J_AXIS]),
do_blocking_move_to_k(destination.k, planner.settings.max_feedrate_mm_s[K_AXIS]),
do_blocking_move_to_u(destination.u, planner.settings.max_feedrate_mm_s[U_AXIS]),
do_blocking_move_to_v(destination.v, planner.settings.max_feedrate_mm_s[V_AXIS]),
do_blocking_move_to_w(destination.w, planner.settings.max_feedrate_mm_s[W_AXIS])
);
// If using MECHANICAL_SWITCHING extruder/nozzle, set HOTEND_OFFSET in Z axis after running EVENT_GCODE_TOOLCHANGE below.
#if NONE(MECHANICAL_SWITCHING_EXTRUDER, MECHANICAL_SWITCHING_NOZZLE)
do_blocking_move_to_z(destination.z, planner.settings.max_feedrate_mm_s[Z_AXIS]);
SECONDARY_AXIS_CODE(
do_blocking_move_to_i(destination.i, planner.settings.max_feedrate_mm_s[I_AXIS]),
do_blocking_move_to_j(destination.j, planner.settings.max_feedrate_mm_s[J_AXIS]),
do_blocking_move_to_k(destination.k, planner.settings.max_feedrate_mm_s[K_AXIS]),
do_blocking_move_to_u(destination.u, planner.settings.max_feedrate_mm_s[U_AXIS]),
do_blocking_move_to_v(destination.v, planner.settings.max_feedrate_mm_s[V_AXIS]),
do_blocking_move_to_w(destination.w, planner.settings.max_feedrate_mm_s[W_AXIS])
);
#endif
#endif
#endif
@@ -1373,7 +1382,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
TERN_(DUAL_X_CARRIAGE, idex_set_parked(false));
}
#if ENABLED(SWITCHING_NOZZLE)
#if HAS_SWITCHING_NOZZLE
// Move back down. (Including when the new tool is higher.)
if (!should_move)
do_blocking_move_to_z(destination.z, planner.settings.max_feedrate_mm_s[Z_AXIS]);
@@ -1460,6 +1469,29 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
}
#endif
// If using MECHANICAL_SWITCHING extruder/nozzle, set HOTEND_OFFSET in Z axis after running EVENT_GCODE_TOOLCHANGE
// so that nozzle does not lower below print surface if new hotend Z offset is higher than old hotend Z offset.
#if EITHER(MECHANICAL_SWITCHING_EXTRUDER, MECHANICAL_SWITCHING_NOZZLE)
#if HAS_HOTEND_OFFSET
xyz_pos_t diff = hotend_offset[new_tool] - hotend_offset[old_tool];
TERN_(DUAL_X_CARRIAGE, diff.x = 0);
#else
constexpr xyz_pos_t diff{0};
#endif
if (!no_move) {
// Move to new hotend Z offset and reverse Z_RAISE
do_blocking_move_to_z(
_MIN(
_MAX((destination.z - diff.z) - toolchange_settings.z_raise,
_MAX(TERN(HAS_SOFTWARE_ENDSTOPS, soft_endstop.min.z, Z_MIN_POS), Z_MIN_POS)
),
_MIN(TERN(HAS_SOFTWARE_ENDSTOPS, soft_endstop.max.z, Z_MAX_POS), Z_MAX_POS)),
planner.settings.max_feedrate_mm_s[Z_AXIS]
);
}
#endif
#ifdef EVENT_GCODE_AFTER_TOOLCHANGE
if (TERN1(DUAL_X_CARRIAGE, dual_x_carriage_mode == DXC_AUTO_PARK_MODE))
gcode.process_subcommands_now(F(EVENT_GCODE_AFTER_TOOLCHANGE));

View File

@@ -419,7 +419,7 @@
// Mixing stepper, Switching stepper, or regular stepper
#define E_NEEDED(N) (ENABLED(MIXING_EXTRUDER) && MIXING_STEPPERS > N) \
|| (ENABLED(SWITCHING_EXTRUDER) && E_STEPPERS > N) \
|| (HAS_SWITCHING_EXTRUDER && E_STEPPERS > N) \
|| (NONE(SWITCHING_EXTRUDER, MIXING_EXTRUDER) && EXTRUDERS > N)
#define _E0_CS
@@ -632,7 +632,7 @@
#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, _E0_CS _E0_MS1 _E0_MS2 _E0_MS3
#endif
#if ENABLED(SWITCHING_EXTRUDER)
#if HAS_SWITCHING_EXTRUDER
// Tools 0 and 1 use E0
#if EXTRUDERS > 2 // Tools 2 and 3 use E1
#undef _E1_PINS