Skip to content

Commit

Permalink
✨ Switching extruder/nozzle without servo (e.g., Dondolo) (MarlinFirm…
Browse files Browse the repository at this point in the history
…ware#24553)

Co-authored-by: Anson Liu <ansonl@users.noreply.github.com>
  • Loading branch information
EvilGremlin and ansonl committed Apr 8, 2023
1 parent 45d5a37 commit 953b231
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 66 deletions.
11 changes: 10 additions & 1 deletion Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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);
}
Expand Down
17 changes: 13 additions & 4 deletions Marlin/src/inc/Conditionals_LCD.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -643,7 +652,7 @@
#else
#define E_STEPPERS 1
#endif
#if DISABLED(SWITCHING_NOZZLE)
#if !HAS_SWITCHING_NOZZLE
#define HOTENDS E_STEPPERS
#endif

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

Expand Down Expand Up @@ -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

Expand Down
40 changes: 21 additions & 19 deletions Marlin/src/inc/Conditionals_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand Down
61 changes: 44 additions & 17 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand All @@ -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."
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/lcd/menu/menu_motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/module/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/module/stepper/indirection.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) { \
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/module/temperature.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading

0 comments on commit 953b231

Please sign in to comment.