Skip to content

Commit

Permalink
💥 Num Axes and Multi-Stepper based on Driver Types (MarlinFirmware#24120
Browse files Browse the repository at this point in the history
)

Co-authored-by: Scott Lahteine <github@thinkyhead.com>
  • Loading branch information
2 people authored and LCh-77 committed May 11, 2022
1 parent 1f66317 commit f5a1c1d
Show file tree
Hide file tree
Showing 33 changed files with 266 additions and 259 deletions.
2 changes: 0 additions & 2 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@
* These settings allow Marlin to tune stepper driver timing and enable advanced options for
* stepper drivers that support them. You may also override timing options in Configuration_adv.h.
*
* A4988 is assumed for unspecified drivers.
*
* Use TMC2208/TMC2208_STANDALONE for TMC2225 drivers and TMC2209/TMC2209_STANDALONE for TMC2226 drivers.
*
* Options: A4988, A5984, DRV8825, LV8729, L6470, L6474, POWERSTEP01,
Expand Down
142 changes: 73 additions & 69 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -713,73 +713,6 @@
//#define CLOSED_LOOP_MOVE_COMPLETE_PIN -1
#endif

/**
* Dual Steppers / Dual Endstops
*
* This section will allow you to use extra E drivers to drive a second motor for X, Y, or Z axes.
*
* For example, set X_DUAL_STEPPER_DRIVERS setting to use a second motor. If the motors need to
* spin in opposite directions set INVERT_X2_VS_X_DIR. If the second motor needs its own endstop
* set X_DUAL_ENDSTOPS. This can adjust for "racking." Use X2_USE_ENDSTOP to set the endstop plug
* that should be used for the second endstop. Extra endstops will appear in the output of 'M119'.
*
* Use X_DUAL_ENDSTOP_ADJUSTMENT to adjust for mechanical imperfection. After homing both motors
* this offset is applied to the X2 motor. To find the offset home the X axis, and measure the error
* in X2. Dual endstop offsets can be set at runtime with 'M666 X<offset> Y<offset> Z<offset>'.
*/

//#define X_DUAL_STEPPER_DRIVERS
#if ENABLED(X_DUAL_STEPPER_DRIVERS)
//#define INVERT_X2_VS_X_DIR // Enable if X2 direction signal is opposite to X
//#define X_DUAL_ENDSTOPS
#if ENABLED(X_DUAL_ENDSTOPS)
#define X2_USE_ENDSTOP _XMAX_
#define X2_ENDSTOP_ADJUSTMENT 0
#endif
#endif

//#define Y_DUAL_STEPPER_DRIVERS
#if ENABLED(Y_DUAL_STEPPER_DRIVERS)
//#define INVERT_Y2_VS_Y_DIR // Enable if Y2 direction signal is opposite to Y
//#define Y_DUAL_ENDSTOPS
#if ENABLED(Y_DUAL_ENDSTOPS)
#define Y2_USE_ENDSTOP _YMAX_
#define Y2_ENDSTOP_ADJUSTMENT 0
#endif
#endif

//
// For Z set the number of stepper drivers
//
#define NUM_Z_STEPPER_DRIVERS 1 // (1-4) Z options change based on how many

#if NUM_Z_STEPPER_DRIVERS > 1
// Enable if Z motor direction signals are the opposite of Z1
//#define INVERT_Z2_VS_Z_DIR
//#define INVERT_Z3_VS_Z_DIR
//#define INVERT_Z4_VS_Z_DIR

//#define Z_MULTI_ENDSTOPS
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z2_USE_ENDSTOP _XMAX_
#define Z2_ENDSTOP_ADJUSTMENT 0
#if NUM_Z_STEPPER_DRIVERS >= 3
#define Z3_USE_ENDSTOP _YMAX_
#define Z3_ENDSTOP_ADJUSTMENT 0
#endif
#if NUM_Z_STEPPER_DRIVERS >= 4
#define Z4_USE_ENDSTOP _ZMAX_
#define Z4_ENDSTOP_ADJUSTMENT 0
#endif
#endif
#endif

// Drive the E axis with two synchronized steppers
//#define E_DUAL_STEPPER_DRIVERS
#if ENABLED(E_DUAL_STEPPER_DRIVERS)
//#define INVERT_E1_VS_E0_DIR // Enable if the E motors need opposite DIR states
#endif

/**
* Dual X Carriage
*
Expand Down Expand Up @@ -830,6 +763,77 @@
//#define EVENT_GCODE_IDEX_AFTER_MODECHANGE "G28X"
#endif

/**
* Multi-Stepper / Multi-Endstop
*
* When X2_DRIVER_TYPE is defined, this indicates that the X and X2 motors work in tandem.
* The following explanations for X also apply to Y and Z multi-stepper setups.
* Endstop offsets may be changed by 'M666 X<offset> Y<offset> Z<offset>' and stored to EEPROM.
*
* - Enable INVERT_X2_VS_X_DIR if the X2 motor requires an opposite DIR signal from X.
*
* - Enable X_DUAL_ENDSTOPS if the second motor has its own endstop, with adjustable offset.
*
* - Extra endstops are included in the output of 'M119'.
*
* - Set X_DUAL_ENDSTOP_ADJUSTMENT to the known error in the X2 endstop.
* Applied to the X2 motor on 'G28' / 'G28 X'.
* Get the offset by homing X and measuring the error.
* Also set with 'M666 X<offset>' and stored to EEPROM with 'M500'.
*
* - Use X2_USE_ENDSTOP to set the endstop plug by name. (_XMIN_, _XMAX_, _YMIN_, _YMAX_, _ZMIN_, _ZMAX_)
*/
#if HAS_X2_STEPPER && DISABLED(DUAL_X_CARRIAGE)
//#define INVERT_X2_VS_X_DIR // X2 direction signal is the opposite of X
//#define X_DUAL_ENDSTOPS // X2 has its own endstop
#if ENABLED(X_DUAL_ENDSTOPS)
#define X2_USE_ENDSTOP _XMAX_ // X2 endstop board plug. Don't forget to enable USE_*_PLUG.
#define X2_ENDSTOP_ADJUSTMENT 0 // X2 offset relative to X endstop
#endif
#endif

#if HAS_DUAL_Y_STEPPERS
//#define INVERT_Y2_VS_Y_DIR // Y2 direction signal is the opposite of Y
//#define Y_DUAL_ENDSTOPS // Y2 has its own endstop
#if ENABLED(Y_DUAL_ENDSTOPS)
#define Y2_USE_ENDSTOP _YMAX_ // Y2 endstop board plug. Don't forget to enable USE_*_PLUG.
#define Y2_ENDSTOP_ADJUSTMENT 0 // Y2 offset relative to Y endstop
#endif
#endif

//
// Multi-Z steppers
//
#ifdef Z2_DRIVER_TYPE
//#define INVERT_Z2_VS_Z_DIR // Z2 direction signal is the opposite of Z

//#define Z_MULTI_ENDSTOPS // Other Z axes have their own endstops
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z2_USE_ENDSTOP _XMAX_ // Z2 endstop board plug. Don't forget to enable USE_*_PLUG.
#define Z2_ENDSTOP_ADJUSTMENT 0 // Z2 offset relative to Y endstop
#endif
#ifdef Z3_DRIVER_TYPE
//#define INVERT_Z3_VS_Z_DIR // Z3 direction signal is the opposite of Z
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z3_USE_ENDSTOP _YMAX_ // Z3 endstop board plug. Don't forget to enable USE_*_PLUG.
#define Z3_ENDSTOP_ADJUSTMENT 0 // Z3 offset relative to Y endstop
#endif
#endif
#ifdef Z4_DRIVER_TYPE
//#define INVERT_Z4_VS_Z_DIR // Z4 direction signal is the opposite of Z
#if ENABLED(Z_MULTI_ENDSTOPS)
#define Z4_USE_ENDSTOP _ZMAX_ // Z4 endstop board plug. Don't forget to enable USE_*_PLUG.
#define Z4_ENDSTOP_ADJUSTMENT 0 // Z4 offset relative to Y endstop
#endif
#endif
#endif

// Drive the E axis with two synchronized steppers
//#define E_DUAL_STEPPER_DRIVERS
#if ENABLED(E_DUAL_STEPPER_DRIVERS)
//#define INVERT_E1_VS_E0_DIR // E direction signals are opposites
#endif

// Activate a solenoid on the active extruder with M380. Disable all with M381.
// Define SOL0_PIN, SOL1_PIN, etc., for each extruder that has a solenoid.
//#define EXT_SOLENOID
Expand Down Expand Up @@ -963,7 +967,7 @@

/**
* Z Stepper positions for more rapid convergence in bed alignment.
* Requires NUM_Z_STEPPER_DRIVERS to be 3 or 4.
* Requires 3 or 4 Z steppers.
*
* Define Stepper XY positions for Z1, Z2, Z3... corresponding to the screw
* positions in the bed carriage, with one position per Z stepper in stepper
Expand Down Expand Up @@ -2460,7 +2464,7 @@

/**
* Extra G-code to run while executing tool-change commands. Can be used to use an additional
* stepper motor (I axis, see option NUM_AXES in Configuration.h) to drive the tool-changer.
* stepper motor (e.g., I axis in Configuration.h) to drive the tool-changer.
*/
//#define EVENT_GCODE_TOOLCHANGE_T0 "G28 A\nG1 A0" // Extra G-code to run while executing tool-change command T0
//#define EVENT_GCODE_TOOLCHANGE_T1 "G1 A10" // Extra G-code to run while executing tool-change command T1
Expand Down
10 changes: 5 additions & 5 deletions Marlin/src/core/drivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@
#define AXIS_DRIVER_TYPE_V(T) _AXIS_DRIVER_TYPE(V,T)
#define AXIS_DRIVER_TYPE_W(T) _AXIS_DRIVER_TYPE(W,T)

#define AXIS_DRIVER_TYPE_X2(T) (EITHER(X_DUAL_STEPPER_DRIVERS, DUAL_X_CARRIAGE) && _AXIS_DRIVER_TYPE(X2,T))
#define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T))
#define AXIS_DRIVER_TYPE_Z2(T) (NUM_Z_STEPPER_DRIVERS >= 2 && _AXIS_DRIVER_TYPE(Z2,T))
#define AXIS_DRIVER_TYPE_Z3(T) (NUM_Z_STEPPER_DRIVERS >= 3 && _AXIS_DRIVER_TYPE(Z3,T))
#define AXIS_DRIVER_TYPE_Z4(T) (NUM_Z_STEPPER_DRIVERS >= 4 && _AXIS_DRIVER_TYPE(Z4,T))
#define AXIS_DRIVER_TYPE_X2(T) (HAS_X2_STEPPER && _AXIS_DRIVER_TYPE(X2,T))
#define AXIS_DRIVER_TYPE_Y2(T) (HAS_DUAL_Y_STEPPERS && _AXIS_DRIVER_TYPE(Y2,T))
#define AXIS_DRIVER_TYPE_Z2(T) (NUM_Z_STEPPERS >= 2 && _AXIS_DRIVER_TYPE(Z2,T))
#define AXIS_DRIVER_TYPE_Z3(T) (NUM_Z_STEPPERS >= 3 && _AXIS_DRIVER_TYPE(Z3,T))
#define AXIS_DRIVER_TYPE_Z4(T) (NUM_Z_STEPPERS >= 4 && _AXIS_DRIVER_TYPE(Z4,T))

#define AXIS_DRIVER_TYPE_E(N,T) (E_STEPPERS > N && _AXIS_DRIVER_TYPE(E##N,T))
#define AXIS_DRIVER_TYPE_E0(T) AXIS_DRIVER_TYPE_E(0,T)
Expand Down
22 changes: 11 additions & 11 deletions Marlin/src/feature/z_stepper_align.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,35 @@

ZStepperAlign z_stepper_align;

xy_pos_t ZStepperAlign::xy[NUM_Z_STEPPER_DRIVERS];
xy_pos_t ZStepperAlign::xy[NUM_Z_STEPPERS];

#if HAS_Z_STEPPER_ALIGN_STEPPER_XY
xy_pos_t ZStepperAlign::stepper_xy[NUM_Z_STEPPER_DRIVERS];
xy_pos_t ZStepperAlign::stepper_xy[NUM_Z_STEPPERS];
#endif

void ZStepperAlign::reset_to_default() {
#ifdef Z_STEPPER_ALIGN_XY

constexpr xy_pos_t xy_init[] = Z_STEPPER_ALIGN_XY;
static_assert(COUNT(xy_init) == NUM_Z_STEPPER_DRIVERS,
static_assert(COUNT(xy_init) == NUM_Z_STEPPERS,
"Z_STEPPER_ALIGN_XY requires "
#if NUM_Z_STEPPER_DRIVERS == 4
#if NUM_Z_STEPPERS == 4
"four {X,Y} entries (Z, Z2, Z3, and Z4)."
#elif NUM_Z_STEPPER_DRIVERS == 3
#elif NUM_Z_STEPPERS == 3
"three {X,Y} entries (Z, Z2, and Z3)."
#else
"two {X,Y} entries (Z and Z2)."
#endif
);

#define VALIDATE_ALIGN_POINT(N) static_assert(N >= NUM_Z_STEPPER_DRIVERS || Probe::build_time::can_reach(xy_init[N]), \
#define VALIDATE_ALIGN_POINT(N) static_assert(N >= NUM_Z_STEPPERS || Probe::build_time::can_reach(xy_init[N]), \
"Z_STEPPER_ALIGN_XY point " STRINGIFY(N) " is not reachable with the default NOZZLE_TO_PROBE offset and PROBING_MARGIN.")
VALIDATE_ALIGN_POINT(0); VALIDATE_ALIGN_POINT(1); VALIDATE_ALIGN_POINT(2); VALIDATE_ALIGN_POINT(3);

#else // !Z_STEPPER_ALIGN_XY

const xy_pos_t xy_init[] = {
#if NUM_Z_STEPPER_DRIVERS >= 3 // First probe point...
#if NUM_Z_STEPPERS >= 3 // First probe point...
#if !Z_STEPPERS_ORIENTATION
{ probe.min_x(), probe.min_y() }, // SW
#elif Z_STEPPERS_ORIENTATION == 1
Expand All @@ -73,7 +73,7 @@ void ZStepperAlign::reset_to_default() {
#else
#error "Z_STEPPERS_ORIENTATION must be from 0 to 3 (first point SW, NW, NE, SE)."
#endif
#if NUM_Z_STEPPER_DRIVERS == 4 // 3 more points...
#if NUM_Z_STEPPERS == 4 // 3 more points...
#if !Z_STEPPERS_ORIENTATION
{ probe.min_x(), probe.max_y() }, { probe.max_x(), probe.max_y() }, { probe.max_x(), probe.min_y() } // SW
#elif Z_STEPPERS_ORIENTATION == 1
Expand Down Expand Up @@ -106,11 +106,11 @@ void ZStepperAlign::reset_to_default() {
#if HAS_Z_STEPPER_ALIGN_STEPPER_XY
constexpr xy_pos_t stepper_xy_init[] = Z_STEPPER_ALIGN_STEPPER_XY;
static_assert(
COUNT(stepper_xy_init) == NUM_Z_STEPPER_DRIVERS,
COUNT(stepper_xy_init) == NUM_Z_STEPPERS,
"Z_STEPPER_ALIGN_STEPPER_XY requires "
#if NUM_Z_STEPPER_DRIVERS == 4
#if NUM_Z_STEPPERS == 4
"four {X,Y} entries (Z, Z2, Z3, and Z4)."
#elif NUM_Z_STEPPER_DRIVERS == 3
#elif NUM_Z_STEPPERS == 3
"three {X,Y} entries (Z, Z2, and Z3)."
#endif
);
Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/feature/z_stepper_align.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@

class ZStepperAlign {
public:
static xy_pos_t xy[NUM_Z_STEPPER_DRIVERS];
static xy_pos_t xy[NUM_Z_STEPPERS];

#if HAS_Z_STEPPER_ALIGN_STEPPER_XY
static xy_pos_t stepper_xy[NUM_Z_STEPPER_DRIVERS];
static xy_pos_t stepper_xy[NUM_Z_STEPPERS];
#endif

static void reset_to_default();
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/gcode/calibrate/G34.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void GcodeSuite::G34() {
digipot_i2c.set_current(Z_AXIS, target_current)
#elif HAS_TRINAMIC_CONFIG
const uint16_t target_current = parser.intval('S', GANTRY_CALIBRATION_CURRENT);
static uint16_t previous_current_arr[NUM_Z_STEPPER_DRIVERS];
static uint16_t previous_current_arr[NUM_Z_STEPPERS];
#if AXIS_IS_TMC(Z)
previous_current_arr[0] = stepperZ.getMilliamps();
stepperZ.rms_current(target_current);
Expand Down
Loading

0 comments on commit f5a1c1d

Please sign in to comment.