Fix IDEX layer shift and DIR states (#19756)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
2.0.x
nb-rapidia 4 years ago committed by GitHub
parent aa901ac4a2
commit 418b3e5ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -223,8 +223,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
const int8_t saved_ext = active_extruder; const int8_t saved_ext = active_extruder;
const bool saved_ext_dup_mode = extruder_duplication_enabled; const bool saved_ext_dup_mode = extruder_duplication_enabled;
active_extruder = DXC_ext; set_duplication_enabled(false, DXC_ext);
extruder_duplication_enabled = false;
#endif #endif
// Slow Load filament // Slow Load filament
@ -245,9 +244,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l
} }
#if ENABLED(DUAL_X_CARRIAGE) // Tie the two extruders movement back together. #if ENABLED(DUAL_X_CARRIAGE) // Tie the two extruders movement back together.
active_extruder = saved_ext; set_duplication_enabled(saved_ext_dup_mode, saved_ext);
extruder_duplication_enabled = saved_ext_dup_mode;
stepper.set_directions();
#endif #endif
#if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE) #if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE)
@ -439,17 +436,14 @@ bool pause_print(const float &retract, const xyz_pos_t &park_point, const float
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
const int8_t saved_ext = active_extruder; const int8_t saved_ext = active_extruder;
const bool saved_ext_dup_mode = extruder_duplication_enabled; const bool saved_ext_dup_mode = extruder_duplication_enabled;
active_extruder = DXC_ext; set_duplication_enabled(false, DXC_ext);
extruder_duplication_enabled = false;
#endif #endif
if (unload_length) // Unload the filament if (unload_length) // Unload the filament
unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT); unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT);
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
active_extruder = saved_ext; set_duplication_enabled(saved_ext_dup_mode, saved_ext);
extruder_duplication_enabled = saved_ext_dup_mode;
stepper.set_directions();
#endif #endif
return true; return true;
@ -495,8 +489,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
const int8_t saved_ext = active_extruder; const int8_t saved_ext = active_extruder;
const bool saved_ext_dup_mode = extruder_duplication_enabled; const bool saved_ext_dup_mode = extruder_duplication_enabled;
active_extruder = DXC_ext; set_duplication_enabled(false, DXC_ext);
extruder_duplication_enabled = false;
#endif #endif
// Wait for filament insert by user and press button // Wait for filament insert by user and press button
@ -550,9 +543,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
idle_no_sleep(); idle_no_sleep();
} }
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
active_extruder = saved_ext; set_duplication_enabled(saved_ext_dup_mode, saved_ext);
extruder_duplication_enabled = saved_ext_dup_mode;
stepper.set_directions();
#endif #endif
} }

@ -89,10 +89,11 @@ bool pause_print(const float &retract, const xyz_pos_t &park_point, const float
void wait_for_confirmation(const bool is_reload=false, const int8_t max_beep_count=0 DXC_PARAMS); void wait_for_confirmation(const bool is_reload=false, const int8_t max_beep_count=0 DXC_PARAMS);
void resume_print(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=ADVANCED_PAUSE_PURGE_LENGTH, const int8_t max_beep_count=0, int16_t targetTemp=0 DXC_PARAMS); void resume_print(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=ADVANCED_PAUSE_PURGE_LENGTH,
const int8_t max_beep_count=0, int16_t targetTemp=0 DXC_PARAMS);
bool load_filament(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=0, const int8_t max_beep_count=0, const bool show_lcd=false, bool load_filament(const float &slow_load_length=0, const float &fast_load_length=0, const float &extrude_length=0, const int8_t max_beep_count=0,
const bool pause_for_user=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT DXC_PARAMS); const bool show_lcd=false, const bool pause_for_user=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT DXC_PARAMS);
bool unload_filament(const float &unload_length, const bool show_lcd=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT bool unload_filament(const float &unload_length, const bool show_lcd=false, const PauseMode mode=PAUSE_MODE_PAUSE_PRINT
#if BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER) #if BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER)

@ -237,7 +237,7 @@ class FilamentSensorBase {
#if NUM_RUNOUT_SENSORS == 1 #if NUM_RUNOUT_SENSORS == 1
UNUSED(extruder); UNUSED(extruder);
#else #else
if ( !TERN0(DUAL_X_CARRIAGE, dxc_is_duplicating()) if ( !TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())
&& !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled) && !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled)
) return TEST(runout_states, extruder); // A specific extruder ran out ) return TEST(runout_states, extruder); // A specific extruder ran out
#endif #endif

@ -110,9 +110,8 @@ void GcodeSuite::G35() {
tool_change(0, true); tool_change(0, true);
#endif #endif
#if HAS_DUPLICATION_MODE // Disable duplication mode on homing
extruder_duplication_enabled = false; TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
#endif
// Home all before this procedure // Home all before this procedure
home_all_axes(); home_all_axes();

@ -134,8 +134,8 @@
if (DEBUGGING(LEVELING)) DEBUG_POS("home_z_safely", destination); if (DEBUGGING(LEVELING)) DEBUG_POS("home_z_safely", destination);
// This causes the carriage on Dual X to unpark // Free the active extruder for movement
TERN_(DUAL_X_CARRIAGE, active_extruder_parked = false); TERN_(DUAL_X_CARRIAGE, idex_set_parked(false));
TERN_(SENSORLESS_HOMING, safe_delay(500)); // Short delay needed to settle TERN_(SENSORLESS_HOMING, safe_delay(500)); // Short delay needed to settle
@ -282,7 +282,7 @@ void GcodeSuite::G28() {
tool_change(0, true); tool_change(0, true);
#endif #endif
TERN_(HAS_DUPLICATION_MODE, extruder_duplication_enabled = false); TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
remember_feedrate_scaling_off(); remember_feedrate_scaling_off();
@ -342,16 +342,14 @@ void GcodeSuite::G28() {
homeaxis(X_AXIS); homeaxis(X_AXIS);
// Remember this extruder's position for later tool change // Remember this extruder's position for later tool change
inactive_extruder_x_pos = current_position.x; inactive_extruder_x = current_position.x;
// Home the 1st (left) extruder // Home the 1st (left) extruder
active_extruder = 0; active_extruder = 0;
homeaxis(X_AXIS); homeaxis(X_AXIS);
// Consider the active extruder to be parked // Consider the active extruder to be in its "parked" position
raised_parked_position = current_position; idex_set_parked();
delayed_move_time = 0;
active_extruder_parked = true;
#else #else
@ -392,7 +390,7 @@ void GcodeSuite::G28() {
*/ */
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
if (dxc_is_duplicating()) { if (idex_is_duplicating()) {
TERN_(IMPROVE_HOMING_RELIABILITY, slow_homing = begin_slow_homing()); TERN_(IMPROVE_HOMING_RELIABILITY, slow_homing = begin_slow_homing());
@ -401,19 +399,17 @@ void GcodeSuite::G28() {
homeaxis(X_AXIS); homeaxis(X_AXIS);
// Remember this extruder's position for later tool change // Remember this extruder's position for later tool change
inactive_extruder_x_pos = current_position.x; inactive_extruder_x = current_position.x;
// Home the 1st (left) extruder // Home the 1st (left) extruder
active_extruder = 0; active_extruder = 0;
homeaxis(X_AXIS); homeaxis(X_AXIS);
// Consider the active extruder to be parked // Consider the active extruder to be parked
raised_parked_position = current_position; idex_set_parked();
delayed_move_time = 0;
active_extruder_parked = true;
extruder_duplication_enabled = IDEX_saved_duplication_state;
dual_x_carriage_mode = IDEX_saved_mode; dual_x_carriage_mode = IDEX_saved_mode;
stepper.set_directions(); set_duplication_enabled(IDEX_saved_duplication_state);
TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing)); TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing));
} }

@ -113,7 +113,7 @@ void GcodeSuite::G34() {
tool_change(0, true); tool_change(0, true);
#endif #endif
TERN_(HAS_DUPLICATION_MODE, extruder_duplication_enabled = false); TERN_(HAS_DUPLICATION_MODE, set_duplication_enabled(false));
// In BLTOUCH HS mode, the probe travels in a deployed state. // In BLTOUCH HS mode, the probe travels in a deployed state.
// Users of G34 might have a badly misaligned bed, so raise Z by the // Users of G34 might have a badly misaligned bed, so raise Z by the

@ -68,7 +68,7 @@
const DualXMode previous_mode = dual_x_carriage_mode; const DualXMode previous_mode = dual_x_carriage_mode;
dual_x_carriage_mode = (DualXMode)parser.value_byte(); dual_x_carriage_mode = (DualXMode)parser.value_byte();
mirrored_duplication_mode = false; idex_set_mirrored_mode(false);
if (dual_x_carriage_mode == DXC_MIRRORED_MODE) { if (dual_x_carriage_mode == DXC_MIRRORED_MODE) {
if (previous_mode != DXC_DUPLICATION_MODE) { if (previous_mode != DXC_DUPLICATION_MODE) {
@ -77,8 +77,7 @@
dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
return; return;
} }
mirrored_duplication_mode = true; idex_set_mirrored_mode(true);
stepper.set_directions();
float x_jog = current_position.x - .1; float x_jog = current_position.x - .1;
for (uint8_t i = 2; --i;) { for (uint8_t i = 2; --i;) {
planner.buffer_line(x_jog, current_position.y, current_position.z, current_position.e, feedrate_mm_s, 0); planner.buffer_line(x_jog, current_position.y, current_position.z, current_position.e, feedrate_mm_s, 0);
@ -102,10 +101,8 @@
dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
break; break;
} }
active_extruder_parked = false; idex_set_parked(false);
extruder_duplication_enabled = false; set_duplication_enabled(false);
stepper.set_directions();
delayed_move_time = 0;
} }
else if (!parser.seen('W')) // if no S or W parameter, the DXC mode gets reset to the user's default else if (!parser.seen('W')) // if no S or W parameter, the DXC mode gets reset to the user's default
dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
@ -125,7 +122,7 @@
if (!active_extruder_parked) DEBUG_ECHOPGM(" NOT "); if (!active_extruder_parked) DEBUG_ECHOPGM(" NOT ");
DEBUG_ECHOPGM(" parked."); DEBUG_ECHOPGM(" parked.");
DEBUG_ECHOPAIR("\nactive_extruder_x_pos: ", current_position.x); DEBUG_ECHOPAIR("\nactive_extruder_x_pos: ", current_position.x);
DEBUG_ECHOPAIR("\ninactive_extruder_x_pos: ", inactive_extruder_x_pos); DEBUG_ECHOPAIR("\ninactive_extruder_x: ", inactive_extruder_x);
DEBUG_ECHOPAIR("\nextruder_duplication_enabled: ", int(extruder_duplication_enabled)); DEBUG_ECHOPAIR("\nextruder_duplication_enabled: ", int(extruder_duplication_enabled));
DEBUG_ECHOPAIR("\nduplicate_extruder_x_offset: ", duplicate_extruder_x_offset); DEBUG_ECHOPAIR("\nduplicate_extruder_x_offset: ", duplicate_extruder_x_offset);
DEBUG_ECHOPAIR("\nduplicate_extruder_temp_offset: ", duplicate_extruder_temp_offset); DEBUG_ECHOPAIR("\nduplicate_extruder_temp_offset: ", duplicate_extruder_temp_offset);
@ -166,7 +163,7 @@
if (parser.seenval('P')) duplication_e_mask = parser.value_int(); // Set the mask directly if (parser.seenval('P')) duplication_e_mask = parser.value_int(); // Set the mask directly
else if (parser.seenval('E')) duplication_e_mask = pow(2, parser.value_int() + 1) - 1; // Set the mask by E index else if (parser.seenval('E')) duplication_e_mask = pow(2, parser.value_int() + 1) - 1; // Set the mask by E index
ena = (2 == parser.intval('S', extruder_duplication_enabled ? 2 : 0)); ena = (2 == parser.intval('S', extruder_duplication_enabled ? 2 : 0));
extruder_duplication_enabled = ena && (duplication_e_mask >= 3); set_duplication_enabled(ena && (duplication_e_mask >= 3));
} }
SERIAL_ECHO_START(); SERIAL_ECHO_START();
SERIAL_ECHOPGM(STR_DUPLICATION_MODE); SERIAL_ECHOPGM(STR_DUPLICATION_MODE);

@ -87,7 +87,7 @@ void GcodeSuite::M600() {
if (!parser.seen('T')) { // If no tool index is specified, M600 was (probably) sent in response to filament runout. if (!parser.seen('T')) { // If no tool index is specified, M600 was (probably) sent in response to filament runout.
// In this case, for duplicating modes set DXC_ext to the extruder that ran out. // In this case, for duplicating modes set DXC_ext to the extruder that ran out.
#if HAS_FILAMENT_SENSOR && NUM_RUNOUT_SENSORS > 1 #if HAS_FILAMENT_SENSOR && NUM_RUNOUT_SENSORS > 1
if (dxc_is_duplicating()) if (idex_is_duplicating())
DXC_ext = (READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT_STATE) ? 1 : 0; DXC_ext = (READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT_STATE) ? 1 : 0;
#else #else
DXC_ext = active_extruder; DXC_ext = active_extruder;
@ -108,7 +108,7 @@ void GcodeSuite::M600() {
#if HAS_MULTI_EXTRUDER #if HAS_MULTI_EXTRUDER
// Change toolhead if specified // Change toolhead if specified
const uint8_t active_extruder_before_filament_change = active_extruder; const uint8_t active_extruder_before_filament_change = active_extruder;
if (active_extruder != target_extruder && TERN1(DUAL_X_CARRIAGE, !dxc_is_duplicating())) if (active_extruder != target_extruder && TERN1(DUAL_X_CARRIAGE, !idex_is_duplicating()))
tool_change(target_extruder, false); tool_change(target_extruder, false);
#endif #endif

@ -94,7 +94,7 @@ void GcodeSuite::M104() {
thermalManager.setTargetHotend(temp, target_extruder); thermalManager.setTargetHotend(temp, target_extruder);
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
if (dxc_is_duplicating() && target_extruder == 0) if (idex_is_duplicating() && target_extruder == 0)
thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1); thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1);
#endif #endif
@ -172,7 +172,7 @@ void GcodeSuite::M109() {
thermalManager.setTargetHotend(temp, target_extruder); thermalManager.setTargetHotend(temp, target_extruder);
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
if (dxc_is_duplicating() && target_extruder == 0) if (idex_is_duplicating() && target_extruder == 0)
thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1); thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1);
#endif #endif

@ -62,11 +62,11 @@ const uint8_t L64XX_Marlin::index_to_dir[MAX_L64XX] = {
INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR
, (INVERT_X_DIR) // X2 , (INVERT_X_DIR) // X2
#if ENABLED(X_DUAL_STEPPER_DRIVERS) #if ENABLED(X_DUAL_STEPPER_DRIVERS)
^ (INVERT_X2_VS_X_DIR) ^ ENABLED(INVERT_X2_VS_X_DIR)
#endif #endif
, (INVERT_Y_DIR) // Y2 , (INVERT_Y_DIR) // Y2
#if ENABLED(Y_DUAL_STEPPER_DRIVERS) #if ENABLED(Y_DUAL_STEPPER_DRIVERS)
^ (INVERT_Y2_VS_Y_DIR) ^ ENABLED(INVERT_Y2_VS_Y_DIR)
#endif #endif
, INVERT_Z_DIR, INVERT_Z_DIR, INVERT_Z_DIR // Z2,Z3,Z4 , INVERT_Z_DIR, INVERT_Z_DIR, INVERT_Z_DIR // Z2,Z3,Z4

@ -569,7 +569,7 @@ void restore_feedrate_and_scaling() {
soft_endstop.min.x = X2_MIN_POS; soft_endstop.min.x = X2_MIN_POS;
soft_endstop.max.x = dual_max_x; soft_endstop.max.x = dual_max_x;
} }
else if (dxc_is_duplicating()) { else if (idex_is_duplicating()) {
// In Duplication Mode, T0 can move as far left as X1_MIN_POS // In Duplication Mode, T0 can move as far left as X1_MIN_POS
// but not so far to the right that T1 would move past the end // but not so far to the right that T1 would move past the end
soft_endstop.min.x = X1_MIN_POS; soft_endstop.min.x = X1_MIN_POS;
@ -932,8 +932,7 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
#endif // !UBL_SEGMENTED #endif // !UBL_SEGMENTED
#if HAS_DUPLICATION_MODE #if HAS_DUPLICATION_MODE
bool extruder_duplication_enabled, bool extruder_duplication_enabled;
mirrored_duplication_mode;
#if ENABLED(MULTI_NOZZLE_DUPLICATION) #if ENABLED(MULTI_NOZZLE_DUPLICATION)
uint8_t duplication_e_mask; // = 0 uint8_t duplication_e_mask; // = 0
#endif #endif
@ -942,12 +941,13 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
DualXMode dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE; DualXMode dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
float inactive_extruder_x_pos = X2_MAX_POS, // used in mode 0 & 1 float inactive_extruder_x = X2_MAX_POS, // Used in mode 0 & 1
duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; // used in mode 2 duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; // Used in mode 2
xyz_pos_t raised_parked_position; // used in mode 1 xyz_pos_t raised_parked_position; // Used in mode 1
bool active_extruder_parked = false; // used in mode 1 & 2 bool active_extruder_parked = false; // Used in mode 1 & 2
millis_t delayed_move_time = 0; // used in mode 1 millis_t delayed_move_time = 0; // Used in mode 1
int16_t duplicate_extruder_temp_offset = 0; // used in mode 2 int16_t duplicate_extruder_temp_offset = 0; // Used in mode 2
bool idex_mirrored_mode = false; // Used in mode 3
float x_home_pos(const uint8_t extruder) { float x_home_pos(const uint8_t extruder) {
if (extruder == 0) if (extruder == 0)
@ -962,6 +962,23 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS; return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS;
} }
void idex_set_mirrored_mode(const bool mirr) {
idex_mirrored_mode = mirr;
stepper.set_directions();
}
void set_duplication_enabled(const bool dupe, const int8_t tool_index/*=-1*/) {
extruder_duplication_enabled = dupe;
if (tool_index >= 0) active_extruder = tool_index;
stepper.set_directions();
}
void idex_set_parked(const bool park/*=true*/) {
delayed_move_time = 0;
active_extruder_parked = park;
if (park) raised_parked_position = current_position; // Remember current raised toolhead position for use by unpark
}
/** /**
* Prepare a linear move in a dual X axis setup * Prepare a linear move in a dual X axis setup
* *
@ -970,9 +987,10 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
inline bool dual_x_carriage_unpark() { inline bool dual_x_carriage_unpark() {
if (active_extruder_parked) { if (active_extruder_parked) {
switch (dual_x_carriage_mode) { switch (dual_x_carriage_mode) {
case DXC_FULL_CONTROL_MODE:
break; case DXC_FULL_CONTROL_MODE: break;
case DXC_AUTO_PARK_MODE:
case DXC_AUTO_PARK_MODE: {
if (current_position.e == destination.e) { if (current_position.e == destination.e) {
// This is a travel move (with no extrusion) // This is a travel move (with no extrusion)
// Skip it, but keep track of the current position // Skip it, but keep track of the current position
@ -984,23 +1002,27 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
return true; return true;
} }
} }
// unpark extruder: 1) raise, 2) move into starting XY position, 3) lower //
// Un-park the active extruder
//
const feedRate_t fr_zfast = planner.settings.max_feedrate_mm_s[Z_AXIS];
#define CURPOS current_position
#define RAISED raised_parked_position
// 1. Move to the raised parked XYZ. Presumably the tool is already at XY.
if (planner.buffer_line(RAISED.x, RAISED.y, RAISED.z, CURPOS.e, fr_zfast, active_extruder)) {
// 2. Move to the current native XY and raised Z. Presumably this is a null move.
if (planner.buffer_line(CURPOS.x, CURPOS.y, RAISED.z, CURPOS.e, PLANNER_XY_FEEDRATE(), active_extruder)) {
// 3. Lower Z back down
line_to_current_position(fr_zfast);
}
}
planner.synchronize(); // paranoia
stepper.set_directions();
#define CUR_X current_position.x idex_set_parked(false);
#define CUR_Y current_position.y if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("idex_set_parked(false)");
#define CUR_Z current_position.z } break;
#define CUR_E current_position.e
#define RAISED_X raised_parked_position.x
#define RAISED_Y raised_parked_position.y
#define RAISED_Z raised_parked_position.z
if ( planner.buffer_line(RAISED_X, RAISED_Y, RAISED_Z, CUR_E, planner.settings.max_feedrate_mm_s[Z_AXIS], active_extruder))
if (planner.buffer_line( CUR_X, CUR_Y, RAISED_Z, CUR_E, PLANNER_XY_FEEDRATE(), active_extruder))
line_to_current_position(planner.settings.max_feedrate_mm_s[Z_AXIS]);
delayed_move_time = 0;
active_extruder_parked = false;
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Clear active_extruder_parked");
break;
case DXC_MIRRORED_MODE: case DXC_MIRRORED_MODE:
case DXC_DUPLICATION_MODE: case DXC_DUPLICATION_MODE:
if (active_extruder == 0) { if (active_extruder == 0) {
@ -1008,22 +1030,23 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE) if (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
new_pos.x += duplicate_extruder_x_offset; new_pos.x += duplicate_extruder_x_offset;
else else
new_pos.x = inactive_extruder_x_pos; new_pos.x = inactive_extruder_x;
// move duplicate extruder into correct duplication position. // Move duplicate extruder into correct duplication position.
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Set planner X", inactive_extruder_x_pos, " ... Line to X", new_pos.x); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Set planner X", inactive_extruder_x, " ... Line to X", new_pos.x);
planner.set_position_mm(inactive_extruder_x_pos, current_position.y, current_position.z, current_position.e); planner.set_position_mm(inactive_extruder_x, current_position.y, current_position.z, current_position.e);
if (!planner.buffer_line(new_pos, planner.settings.max_feedrate_mm_s[X_AXIS], 1)) break; if (!planner.buffer_line(new_pos, planner.settings.max_feedrate_mm_s[X_AXIS], 1)) break;
planner.synchronize(); planner.synchronize();
sync_plan_position(); sync_plan_position();
extruder_duplication_enabled = true;
active_extruder_parked = false; set_duplication_enabled(true);
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Set extruder_duplication_enabled\nClear active_extruder_parked"); idex_set_parked(false);
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("set_duplication_enabled(true)\nidex_set_parked(false)");
} }
else if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Active extruder not 0"); else if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Active extruder not 0");
break; break;
} }
} }
stepper.set_directions();
return false; return false;
} }

@ -384,8 +384,7 @@ bool homing_needed_error(uint8_t axis_bits=0x07);
* Duplication mode * Duplication mode
*/ */
#if HAS_DUPLICATION_MODE #if HAS_DUPLICATION_MODE
extern bool extruder_duplication_enabled, // Used in Dual X mode 2 extern bool extruder_duplication_enabled; // Used in Dual X mode 2
mirrored_duplication_mode; // Used in Dual X mode 3
#if ENABLED(MULTI_NOZZLE_DUPLICATION) #if ENABLED(MULTI_NOZZLE_DUPLICATION)
extern uint8_t duplication_e_mask; extern uint8_t duplication_e_mask;
#endif #endif
@ -404,23 +403,29 @@ bool homing_needed_error(uint8_t axis_bits=0x07);
}; };
extern DualXMode dual_x_carriage_mode; extern DualXMode dual_x_carriage_mode;
extern float inactive_extruder_x_pos, // Used in mode 0 & 1 extern float inactive_extruder_x, // Used in mode 0 & 1
duplicate_extruder_x_offset; // Used in mode 2 & 3 duplicate_extruder_x_offset; // Used in mode 2 & 3
extern xyz_pos_t raised_parked_position; // Used in mode 1 extern xyz_pos_t raised_parked_position; // Used in mode 1
extern bool active_extruder_parked; // Used in mode 1, 2 & 3 extern bool active_extruder_parked; // Used in mode 1, 2 & 3
extern millis_t delayed_move_time; // Used in mode 1 extern millis_t delayed_move_time; // Used in mode 1
extern int16_t duplicate_extruder_temp_offset; // Used in mode 2 & 3 extern int16_t duplicate_extruder_temp_offset; // Used in mode 2 & 3
extern bool idex_mirrored_mode; // Used in mode 3
FORCE_INLINE bool dxc_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; } FORCE_INLINE bool idex_is_duplicating() { return dual_x_carriage_mode >= DXC_DUPLICATION_MODE; }
float x_home_pos(const uint8_t extruder); float x_home_pos(const uint8_t extruder);
FORCE_INLINE int x_home_dir(const uint8_t extruder) { return extruder ? X2_HOME_DIR : X_HOME_DIR; } FORCE_INLINE int x_home_dir(const uint8_t extruder) { return extruder ? X2_HOME_DIR : X_HOME_DIR; }
void set_duplication_enabled(const bool dupe, const int8_t tool_index=-1);
void idex_set_mirrored_mode(const bool mirr);
void idex_set_parked(const bool park=true);
#else #else
#if ENABLED(MULTI_NOZZLE_DUPLICATION) #if ENABLED(MULTI_NOZZLE_DUPLICATION)
enum DualXMode : char { DXC_DUPLICATION_MODE = 2 }; enum DualXMode : char { DXC_DUPLICATION_MODE = 2 };
FORCE_INLINE void set_duplication_enabled(const bool dupe) { extruder_duplication_enabled = dupe; }
#endif #endif
FORCE_INLINE int x_home_dir(const uint8_t) { return home_dir(X_AXIS); } FORCE_INLINE int x_home_dir(const uint8_t) { return home_dir(X_AXIS); }

@ -348,7 +348,7 @@ xyze_int8_t Stepper::count_direction{0};
} }
#if ENABLED(X_DUAL_STEPPER_DRIVERS) #if ENABLED(X_DUAL_STEPPER_DRIVERS)
#define X_APPLY_DIR(v,Q) do{ X_DIR_WRITE(v); X2_DIR_WRITE((v) != INVERT_X2_VS_X_DIR); }while(0) #define X_APPLY_DIR(v,Q) do{ X_DIR_WRITE(v); X2_DIR_WRITE((v) ^ ENABLED(INVERT_X2_VS_X_DIR)); }while(0)
#if ENABLED(X_DUAL_ENDSTOPS) #if ENABLED(X_DUAL_ENDSTOPS)
#define X_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(X,v) #define X_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(X,v)
#else #else
@ -356,7 +356,7 @@ xyze_int8_t Stepper::count_direction{0};
#endif #endif
#elif ENABLED(DUAL_X_CARRIAGE) #elif ENABLED(DUAL_X_CARRIAGE)
#define X_APPLY_DIR(v,ALWAYS) do{ \ #define X_APPLY_DIR(v,ALWAYS) do{ \
if (extruder_duplication_enabled || ALWAYS) { X_DIR_WRITE(v); X2_DIR_WRITE(mirrored_duplication_mode ? !(v) : v); } \ if (extruder_duplication_enabled || ALWAYS) { X_DIR_WRITE(v); X2_DIR_WRITE((v) ^ idex_mirrored_mode); } \
else if (last_moved_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \ else if (last_moved_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \
}while(0) }while(0)
#define X_APPLY_STEP(v,ALWAYS) do{ \ #define X_APPLY_STEP(v,ALWAYS) do{ \
@ -369,7 +369,7 @@ xyze_int8_t Stepper::count_direction{0};
#endif #endif
#if ENABLED(Y_DUAL_STEPPER_DRIVERS) #if ENABLED(Y_DUAL_STEPPER_DRIVERS)
#define Y_APPLY_DIR(v,Q) do{ Y_DIR_WRITE(v); Y2_DIR_WRITE((v) != INVERT_Y2_VS_Y_DIR); }while(0) #define Y_APPLY_DIR(v,Q) do{ Y_DIR_WRITE(v); Y2_DIR_WRITE((v) ^ ENABLED(INVERT_Y2_VS_Y_DIR)); }while(0)
#if ENABLED(Y_DUAL_ENDSTOPS) #if ENABLED(Y_DUAL_ENDSTOPS)
#define Y_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Y,v) #define Y_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Y,v)
#else #else
@ -1605,10 +1605,9 @@ void Stepper::pulse_phase_isr() {
PAGE_SEGMENT_UPDATE(Z, high >> 4); PAGE_SEGMENT_UPDATE(Z, high >> 4);
PAGE_SEGMENT_UPDATE(E, high & 0xF); PAGE_SEGMENT_UPDATE(E, high & 0xF);
if (dm != last_direction_bits) { if (dm != last_direction_bits)
last_direction_bits = dm; set_directions(dm);
set_directions();
}
} break; } break;
default: break; default: break;
@ -2131,9 +2130,7 @@ uint32_t Stepper::block_phase_isr() {
MIXER_STEPPER_SETUP(); MIXER_STEPPER_SETUP();
#endif #endif
#if HAS_MULTI_EXTRUDER TERN_(HAS_MULTI_EXTRUDER, stepper_extruder = current_block->extruder);
stepper_extruder = current_block->extruder;
#endif
// Initialize the trapezoid generator from the current block. // Initialize the trapezoid generator from the current block.
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
@ -2152,16 +2149,13 @@ uint32_t Stepper::block_phase_isr() {
#endif #endif
if ( ENABLED(HAS_L64XX) // Always set direction for L64xx (Also enables the chips) if ( ENABLED(HAS_L64XX) // Always set direction for L64xx (Also enables the chips)
|| ENABLED(DUAL_X_CARRIAGE) // TODO: Find out why this fixes "jittery" small circles
|| current_block->direction_bits != last_direction_bits || current_block->direction_bits != last_direction_bits
|| TERN(MIXING_EXTRUDER, false, stepper_extruder != last_moved_extruder) || TERN(MIXING_EXTRUDER, false, stepper_extruder != last_moved_extruder)
) { ) {
last_direction_bits = current_block->direction_bits; TERN_(HAS_MULTI_EXTRUDER, last_moved_extruder = stepper_extruder);
#if HAS_MULTI_EXTRUDER
last_moved_extruder = stepper_extruder;
#endif
TERN_(HAS_L64XX, L64XX_OK_to_power_up = true); TERN_(HAS_L64XX, L64XX_OK_to_power_up = true);
set_directions(); set_directions(current_block->direction_bits);
} }
#if ENABLED(LASER_POWER_INLINE) #if ENABLED(LASER_POWER_INLINE)
@ -2583,12 +2577,9 @@ void Stepper::init() {
#endif #endif
// Init direction bits for first moves // Init direction bits for first moves
last_direction_bits = 0 set_directions((INVERT_X_DIR ? _BV(X_AXIS) : 0)
| (INVERT_X_DIR ? _BV(X_AXIS) : 0)
| (INVERT_Y_DIR ? _BV(Y_AXIS) : 0) | (INVERT_Y_DIR ? _BV(Y_AXIS) : 0)
| (INVERT_Z_DIR ? _BV(Z_AXIS) : 0); | (INVERT_Z_DIR ? _BV(Z_AXIS) : 0));
set_directions();
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
initialized = true; initialized = true;

@ -514,9 +514,15 @@ class Stepper {
static void refresh_motor_power(); static void refresh_motor_power();
#endif #endif
// Set direction bits for all steppers // Update direction states for all steppers
static void set_directions(); static void set_directions();
// Set direction bits and update all stepper DIR states
static void set_directions(const uint8_t bits) {
last_direction_bits = bits;
set_directions();
}
private: private:
// Set the current position in steps // Set the current position in steps

@ -61,6 +61,10 @@
#include "../gcode/gcode.h" #include "../gcode/gcode.h"
#endif #endif
#if ENABLED(DUAL_X_CARRIAGE)
#include "stepper.h"
#endif
#if ANY(SWITCHING_EXTRUDER, SWITCHING_NOZZLE, SWITCHING_TOOLHEAD) #if ANY(SWITCHING_EXTRUDER, SWITCHING_NOZZLE, SWITCHING_TOOLHEAD)
#include "servo.h" #include "servo.h"
#endif #endif
@ -701,6 +705,13 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
/**
* @brief Dual X Tool Change
* @details Change tools, with extra behavior based on current mode
*
* @param new_tool Tool index to activate
* @param no_move Flag indicating no moves should take place
*/
inline void dualx_tool_change(const uint8_t new_tool, bool &no_move) { inline void dualx_tool_change(const uint8_t new_tool, bool &no_move) {
DEBUG_ECHOPGM("Dual X Carriage Mode "); DEBUG_ECHOPGM("Dual X Carriage Mode ");
@ -711,17 +722,16 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a
case DXC_MIRRORED_MODE: DEBUG_ECHOLNPGM("MIRRORED"); break; case DXC_MIRRORED_MODE: DEBUG_ECHOLNPGM("MIRRORED"); break;
} }
// Get the home position of the currently-active tool
const float xhome = x_home_pos(active_extruder); const float xhome = x_home_pos(active_extruder);
if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE
&& IsRunning() && !no_move if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE // If Auto-Park mode is enabled
&& (delayed_move_time || current_position.x != xhome) && IsRunning() && !no_move // ...and movement is permitted
&& (delayed_move_time || current_position.x != xhome) // ...and delayed_move_time is set OR not "already parked"...
) { ) {
DEBUG_ECHOLNPAIR("MoveX to ", xhome); DEBUG_ECHOLNPAIR("MoveX to ", xhome);
// Park old head
current_position.x = xhome; current_position.x = xhome;
line_to_current_position(planner.settings.max_feedrate_mm_s[X_AXIS]); line_to_current_position(planner.settings.max_feedrate_mm_s[X_AXIS]); // Park the current head
planner.synchronize(); planner.synchronize();
} }
@ -736,20 +746,21 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a
switch (dual_x_carriage_mode) { switch (dual_x_carriage_mode) {
case DXC_FULL_CONTROL_MODE: case DXC_FULL_CONTROL_MODE:
// New current position is the position of the activated extruder // New current position is the position of the activated extruder
current_position.x = inactive_extruder_x_pos; current_position.x = inactive_extruder_x;
// Save the inactive extruder's position (from the old current_position) // Save the inactive extruder's position (from the old current_position)
inactive_extruder_x_pos = destination.x; inactive_extruder_x = destination.x;
DEBUG_ECHOLNPAIR("DXC Full Control curr.x=", current_position.x, " dest.x=", destination.x);
break; break;
case DXC_AUTO_PARK_MODE: case DXC_AUTO_PARK_MODE:
// record current raised toolhead position for use by unpark idex_set_parked();
raised_parked_position = current_position;
active_extruder_parked = true;
delayed_move_time = 0;
break; break;
default: default:
break; break;
} }
// Ensure X axis DIR pertains to the correct carriage
stepper.set_directions();
DEBUG_ECHOLNPAIR("Active extruder parked: ", active_extruder_parked ? "yes" : "no"); DEBUG_ECHOLNPAIR("Active extruder parked: ", active_extruder_parked ? "yes" : "no");
DEBUG_POS("New extruder (parked)", current_position); DEBUG_POS("New extruder (parked)", current_position);
} }
@ -875,7 +886,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
planner.synchronize(); planner.synchronize();
#if ENABLED(DUAL_X_CARRIAGE) // Only T0 allowed if the Printer is in DXC_DUPLICATION_MODE or DXC_MIRRORED_MODE #if ENABLED(DUAL_X_CARRIAGE) // Only T0 allowed if the Printer is in DXC_DUPLICATION_MODE or DXC_MIRRORED_MODE
if (new_tool != 0 && dxc_is_duplicating()) if (new_tool != 0 && idex_is_duplicating())
return invalid_extruder_error(new_tool); return invalid_extruder_error(new_tool);
#endif #endif
@ -1151,7 +1162,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
} }
#endif #endif
TERN_(DUAL_X_CARRIAGE, active_extruder_parked = false); TERN_(DUAL_X_CARRIAGE, idex_set_parked(false));
} }
#if ENABLED(SWITCHING_NOZZLE) #if ENABLED(SWITCHING_NOZZLE)

Loading…
Cancel
Save