From 3d620221dd9717ddf2ed0ebd2ad26d18ed1df0cf Mon Sep 17 00:00:00 2001 From: EvilGremlin <22657714+EvilGremlin@users.noreply.github.com> Date: Sat, 4 Mar 2023 05:43:20 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Switching=20extruder/nozzle=20witho?= =?UTF-8?q?ut=20servo=20(e.g.,=20Dondolo)=20(#24553)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Anson Liu --- Marlin/Configuration.h | 11 ++++- Marlin/src/MarlinCore.cpp | 10 ++-- Marlin/src/inc/Conditionals_LCD.h | 17 +++++-- Marlin/src/inc/Conditionals_adv.h | 40 ++++++++-------- Marlin/src/inc/SanityCheck.h | 61 ++++++++++++++++++------- Marlin/src/lcd/menu/menu_motion.cpp | 4 +- Marlin/src/module/planner.cpp | 2 +- Marlin/src/module/stepper/indirection.h | 2 +- Marlin/src/module/temperature.h | 2 +- Marlin/src/module/tool_change.cpp | 58 +++++++++++++++++------ Marlin/src/pins/sensitive_pins.h | 4 +- 11 files changed, 145 insertions(+), 66 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 461290a9ab21..4205c4c58d00 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -277,7 +277,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 @@ -286,6 +292,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. diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index bc82a65c9c53..2a93db2e0ee8 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -676,7 +676,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; @@ -690,7 +690,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: @@ -706,7 +706,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 @@ -716,12 +716,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); } diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index 4e9285e6c14c..0031e17eeaeb 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -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 diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index ff2e54e393da..5b303e919f3c 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -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 diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index d5e91932daf0..54ffcaf0ca18 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -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 diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index e3b9154b777a..9c874388367d 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -233,7 +233,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) { @@ -266,7 +266,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 diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 56a74cf9557e..6c6626ff2ebb 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -2288,7 +2288,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)))) diff --git a/Marlin/src/module/stepper/indirection.h b/Marlin/src/module/stepper/indirection.h index d1f8dafb2b55..ae8f7a96eb81 100644 --- a/Marlin/src/module/stepper/indirection.h +++ b/Marlin/src/module/stepper/indirection.h @@ -455,7 +455,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) { \ diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 6b25801d7d7b..1a634b2aba01 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -773,7 +773,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 diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index 0defced87ece..9955a0f1b0ec 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -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)); diff --git a/Marlin/src/pins/sensitive_pins.h b/Marlin/src/pins/sensitive_pins.h index 061e27faf4f7..288bcc904ead 100644 --- a/Marlin/src/pins/sensitive_pins.h +++ b/Marlin/src/pins/sensitive_pins.h @@ -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