From 907cafcbfd3977712324c59a4e9af40bde167421 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 19 Jun 2017 16:54:37 -0500 Subject: [PATCH] Support for two switching extruders --- Marlin/Configuration.h | 5 ++- Marlin/Marlin_main.cpp | 63 ++++++++++++++++++++---------------- Marlin/SanityCheck.h | 28 +++++++--------- Marlin/pins.h | 12 ++++++- Marlin/stepper_indirection.h | 16 +++++++-- 5 files changed, 75 insertions(+), 49 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 7d6c4a561..6c128f4e1 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -142,7 +142,10 @@ //#define SWITCHING_EXTRUDER #if ENABLED(SWITCHING_EXTRUDER) #define SWITCHING_EXTRUDER_SERVO_NR 0 - #define SWITCHING_EXTRUDER_SERVO_ANGLES { 0, 90 } // Angles for E0, E1 + #define SWITCHING_EXTRUDER_SERVO_ANGLES { 0, 90 } // Angles for E0, E1[, E2, E3] + #if EXTRUDERS > 3 + #define SWITCHING_EXTRUDER_E23_SERVO_NR 1 + #endif #endif // A dual-nozzle that uses a servomotor to raise/lower one of the nozzles diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 61bbaa514..b364e6f2f 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -9843,25 +9843,41 @@ inline void gcode_M999() { } #if ENABLED(SWITCHING_EXTRUDER) - inline void move_extruder_servo(uint8_t e) { - const int angles[2] = SWITCHING_EXTRUDER_SERVO_ANGLES; - MOVE_SERVO(SWITCHING_EXTRUDER_SERVO_NR, angles[e]); - safe_delay(500); + #if EXTRUDERS > 3 + #define REQ_ANGLES 4 + #define _SERVO_NR (e < 2 ? SWITCHING_EXTRUDER_SERVO_NR : SWITCHING_EXTRUDER_E23_SERVO_NR) + #else + #define REQ_ANGLES 2 + #define _SERVO_NR SWITCHING_EXTRUDER_SERVO_NR + #endif + inline void move_extruder_servo(const uint8_t e) { + constexpr int16_t angles[] = SWITCHING_EXTRUDER_SERVO_ANGLES; + static_assert(COUNT(angles) == REQ_ANGLES, "SWITCHING_EXTRUDER_SERVO_ANGLES needs " STRINGIFY(REQ_ANGLES) " angles."); + stepper.synchronize(); + #if EXTRUDERS & 1 + if (e < EXTRUDERS - 1) + #endif + { + MOVE_SERVO(_SERVO_NR, angles[e]); + safe_delay(500); + } } -#endif +#endif // SWITCHING_EXTRUDER #if ENABLED(SWITCHING_NOZZLE) - inline void move_nozzle_servo(uint8_t e) { - const int angles[2] = SWITCHING_NOZZLE_SERVO_ANGLES; + inline void move_nozzle_servo(const uint8_t e) { + const int16_t angles[2] = SWITCHING_NOZZLE_SERVO_ANGLES; + stepper.synchronize(); MOVE_SERVO(SWITCHING_NOZZLE_SERVO_NR, angles[e]); safe_delay(500); } #endif -inline void invalid_extruder_error(const uint8_t &e) { +inline void invalid_extruder_error(const uint8_t e) { SERIAL_ECHO_START(); SERIAL_CHAR('T'); SERIAL_ECHO_F(e, DEC); + SERIAL_CHAR(' '); SERIAL_ECHOLN(MSG_INVALID_EXTRUDER); } @@ -9881,10 +9897,10 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n #else // !MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1 - #if HOTENDS > 1 + if (tmp_extruder >= EXTRUDERS) + return invalid_extruder_error(tmp_extruder); - if (tmp_extruder >= EXTRUDERS) - return invalid_extruder_error(tmp_extruder); + #if HOTENDS > 1 const float old_feedrate_mm_s = fr_mm_s > 0.0 ? fr_mm_s : feedrate_mm_s; @@ -10006,6 +10022,7 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n #else // !DUAL_X_CARRIAGE #if ENABLED(SWITCHING_NOZZLE) + #define DONT_SWITCH (SWITCHING_EXTRUDER_SERVO_NR == SWITCHING_NOZZLE_SERVO_NR) // <0 if the new nozzle is higher, >0 if lower. A bigger raise when lower. const float z_diff = hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder], z_raise = 0.3 + (z_diff > 0.0 ? z_diff : 0.0); @@ -10013,16 +10030,7 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n // Always raise by some amount (destination copied from current_position earlier) current_position[Z_AXIS] += z_raise; planner.buffer_line_kinematic(current_position, planner.max_feedrate_mm_s[Z_AXIS], active_extruder); - stepper.synchronize(); - - move_nozzle_servo(active_extruder); - #endif - - #if ENABLED(SWITCHING_EXTRUDER) - #if !(ENABLED(SWITCHING_NOZZLE) && (SWITCHING_EXTRUDER_SERVO_NR == SWITCHING_NOZZLE_SERVO_NR)) - stepper.synchronize(); - move_extruder_servo(active_extruder); - #endif + move_nozzle_servo(tmp_extruder); #endif /** @@ -10167,19 +10175,18 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n #else // HOTENDS <= 1 - // Set the new active extruder - active_extruder = tmp_extruder; - UNUSED(fr_mm_s); UNUSED(no_move); - #if ENABLED(SWITCHING_EXTRUDER) - stepper.synchronize(); - move_extruder_servo(active_extruder); - #endif + // Set the new active extruder + active_extruder = tmp_extruder; #endif // HOTENDS <= 1 + #if ENABLED(SWITCHING_EXTRUDER) && !DONT_SWITCH + move_extruder_servo(active_extruder); + #endif + SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, (int)active_extruder); diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index ee25709af..0b4f612d0 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -355,12 +355,14 @@ #endif /** - * A dual nozzle x-carriage with switching servo + * A Dual Nozzle carriage with switching servo */ #if ENABLED(SWITCHING_NOZZLE) - #if ENABLED(SINGLENOZZLE) + #if ENABLED(DUAL_X_CARRIAGE) + #error "SWITCHING_NOZZLE and DUAL_X_CARRIAGE are incompatible." + #elif ENABLED(SINGLENOZZLE) #error "SWITCHING_NOZZLE and SINGLENOZZLE are incompatible." - #elif EXTRUDERS < 2 + #elif EXTRUDERS != 2 #error "SWITCHING_NOZZLE requires exactly 2 EXTRUDERS." #elif NUM_SERVOS < 1 #error "SWITCHING_NOZZLE requires NUM_SERVOS >= 1." @@ -370,14 +372,8 @@ /** * Single Stepper Dual Extruder with switching servo */ -#if ENABLED(SWITCHING_EXTRUDER) - #if ENABLED(DUAL_X_CARRIAGE) - #error "SWITCHING_EXTRUDER and DUAL_X_CARRIAGE are incompatible." - #elif EXTRUDERS != 2 - #error "SWITCHING_EXTRUDER requires exactly 2 EXTRUDERS." - #elif NUM_SERVOS < 1 - #error "SWITCHING_EXTRUDER requires NUM_SERVOS >= 1." - #endif +#if ENABLED(SWITCHING_EXTRUDER) && NUM_SERVOS < 1 + #error "SWITCHING_EXTRUDER requires NUM_SERVOS >= 1." #endif /** @@ -938,21 +934,21 @@ static_assert(1 >= 0 #endif /** - * Test Extruder Pins + * Test Extruder Stepper Pins */ -#if EXTRUDERS > 4 +#if E_STEPPERS > 4 #if !PIN_EXISTS(E4_STEP) || !PIN_EXISTS(E4_DIR) || !PIN_EXISTS(E4_ENABLE) #error "E4_STEP_PIN, E4_DIR_PIN, or E4_ENABLE_PIN not defined for this board." #endif -#elif EXTRUDERS > 3 +#elif E_STEPPERS > 3 #if !PIN_EXISTS(E3_STEP) || !PIN_EXISTS(E3_DIR) || !PIN_EXISTS(E3_ENABLE) #error "E3_STEP_PIN, E3_DIR_PIN, or E3_ENABLE_PIN not defined for this board." #endif -#elif EXTRUDERS > 2 +#elif E_STEPPERS > 2 #if !PIN_EXISTS(E2_STEP) || !PIN_EXISTS(E2_DIR) || !PIN_EXISTS(E2_ENABLE) #error "E2_STEP_PIN, E2_DIR_PIN, or E2_ENABLE_PIN not defined for this board." #endif -#elif EXTRUDERS > 1 +#elif E_STEPPERS > 1 #if !PIN_EXISTS(E1_STEP) || !PIN_EXISTS(E1_DIR) || !PIN_EXISTS(E1_ENABLE) #error "E1_STEP_PIN, E1_DIR_PIN, or E1_ENABLE_PIN not defined for this board." #endif diff --git a/Marlin/pins.h b/Marlin/pins.h index 689e305d9..0b43a7a1c 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -330,7 +330,17 @@ #define _E3_PINS #define _E4_PINS -#if EXTRUDERS > 1 +#if ENABLED(SWITCHING_EXTRUDER) + // Tools 0 and 1 use E0 + #if EXTRUDERS > 2 // Tools 2 and 3 use E1 + #undef _E1_PINS + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, E1_MS1_PIN, E1_MS2_PIN, + #if EXTRUDERS > 4 // Tools 4 and 5 use E2 + #undef _E2_PINS + #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, + #endif + #endif +#elif EXTRUDERS > 1 #undef _E1_PINS #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, E1_MS1_PIN, E1_MS2_PIN, #if EXTRUDERS > 2 diff --git a/Marlin/stepper_indirection.h b/Marlin/stepper_indirection.h index 79a8da4f6..e9af6e43f 100644 --- a/Marlin/stepper_indirection.h +++ b/Marlin/stepper_indirection.h @@ -416,9 +416,19 @@ * Extruder indirection for the single E axis */ #if ENABLED(SWITCHING_EXTRUDER) - #define E_STEP_WRITE(v) E0_STEP_WRITE(v) - #define NORM_E_DIR() E0_DIR_WRITE(current_block->active_extruder ? INVERT_E0_DIR : !INVERT_E0_DIR) - #define REV_E_DIR() E0_DIR_WRITE(current_block->active_extruder ? !INVERT_E0_DIR : INVERT_E0_DIR) + #if EXTRUDERS == 2 + #define E_STEP_WRITE(v) E0_STEP_WRITE(v) + #define NORM_E_DIR() E0_DIR_WRITE(current_block->active_extruder ? INVERT_E0_DIR : !INVERT_E0_DIR) + #define REV_E_DIR() E0_DIR_WRITE(current_block->active_extruder ? !INVERT_E0_DIR : INVERT_E0_DIR) + #elif EXTRUDERS > 4 + #define E_STEP_WRITE(v) { if (current_block->active_extruder < 2) E0_STEP_WRITE(v); else if (current_block->active_extruder < 4) E1_STEP_WRITE(v); else E2_STEP_WRITE(v); } + #define NORM_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(INVERT_E1_DIR); break; case 4: E2_DIR_WRITE(!INVERT_E2_DIR); } } + #define REV_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 4: E2_DIR_WRITE(INVERT_E2_DIR); } } + #elif EXTRUDERS > 2 + #define E_STEP_WRITE(v) { if (current_block->active_extruder < 2) E0_STEP_WRITE(v); else if (current_block->active_extruder < 4) E1_STEP_WRITE(v); else E1_STEP_WRITE(v); } + #define NORM_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(INVERT_E1_DIR); } } + #define REV_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); } } + #endif #elif EXTRUDERS > 4 #define E_STEP_WRITE(v) { switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); break; case 4: E4_STEP_WRITE(v); } } #define NORM_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; case 4: E4_DIR_WRITE(!INVERT_E4_DIR); } }