Implement support for Dual X and Y endstops

master
Scott Lahteine 7 years ago
parent 7e1232269a
commit 318c419f77

@ -199,12 +199,11 @@ script:
# #
- restore_configs - restore_configs
- opt_enable ULTIMAKERCONTROLLER FILAMENT_LCD_DISPLAY FILAMENT_WIDTH_SENSOR SDSUPPORT - opt_enable ULTIMAKERCONTROLLER FILAMENT_LCD_DISPLAY FILAMENT_WIDTH_SENSOR SDSUPPORT
- opt_enable PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE PCA9632 - opt_enable PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE PCA9632 USE_XMAX_PLUG
- opt_enable_adv Z_DUAL_STEPPER_DRIVERS Z_DUAL_ENDSTOPS BEZIER_CURVE_SUPPORT EXPERIMENTAL_I2CBUS - opt_enable_adv Z_DUAL_STEPPER_DRIVERS Z_DUAL_ENDSTOPS BEZIER_CURVE_SUPPORT EXPERIMENTAL_I2CBUS
- opt_set_adv I2C_SLAVE_ADDRESS 63 - opt_set_adv I2C_SLAVE_ADDRESS 63
- opt_enable_adv ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE LCD_INFO_MENU - opt_enable_adv ADVANCED_PAUSE_FEATURE PARK_HEAD_ON_PAUSE LCD_INFO_MENU
- pins_set RAMPS X_MAX_PIN -1 - opt_add_adv Z2_MIN_PIN 2
- opt_add_adv Z2_MAX_PIN 2
- build_marlin - build_marlin
# #
# Enable COREXY # Enable COREXY

@ -378,29 +378,114 @@
#define ARRAY_BY_HOTENDS(...) ARRAY_N(HOTENDS, __VA_ARGS__) #define ARRAY_BY_HOTENDS(...) ARRAY_N(HOTENDS, __VA_ARGS__)
#define ARRAY_BY_HOTENDS1(v1) ARRAY_BY_HOTENDS(v1, v1, v1, v1, v1, v1) #define ARRAY_BY_HOTENDS1(v1) ARRAY_BY_HOTENDS(v1, v1, v1, v1, v1, v1)
/**
* X_DUAL_ENDSTOPS endstop reassignment
*/
#if ENABLED(X_DUAL_ENDSTOPS)
#if X_HOME_DIR > 0
#if X2_USE_ENDSTOP == _XMIN_
#define X2_MAX_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING
#define X2_MAX_PIN X_MIN_PIN
#elif X2_USE_ENDSTOP == _XMAX_
#define X2_MAX_ENDSTOP_INVERTING X_MAX_ENDSTOP_INVERTING
#define X2_MAX_PIN X_MAX_PIN
#elif X2_USE_ENDSTOP == _YMIN_
#define X2_MAX_ENDSTOP_INVERTING Y_MIN_ENDSTOP_INVERTING
#define X2_MAX_PIN Y_MIN_PIN
#elif X2_USE_ENDSTOP == _YMAX_
#define X2_MAX_ENDSTOP_INVERTING Y_MAX_ENDSTOP_INVERTING
#define X2_MAX_PIN Y_MAX_PIN
#elif X2_USE_ENDSTOP == _ZMIN_
#define X2_MAX_ENDSTOP_INVERTING Z_MIN_ENDSTOP_INVERTING
#define X2_MAX_PIN Z_MIN_PIN
#elif X2_USE_ENDSTOP == _ZMAX_
#define X2_MAX_ENDSTOP_INVERTING Z_MAX_ENDSTOP_INVERTING
#define X2_MAX_PIN Z_MAX_PIN
#else
#define X2_MAX_ENDSTOP_INVERTING false
#endif
#elif X2_USE_ENDSTOP == _XMIN_
#define X2_MIN_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING
#define X2_MIN_PIN X_MIN_PIN
#elif X2_USE_ENDSTOP == _XMAX_
#define X2_MIN_ENDSTOP_INVERTING X_MAX_ENDSTOP_INVERTING
#define X2_MIN_PIN X_MAX_PIN
#elif X2_USE_ENDSTOP == _YMIN_
#define X2_MIN_ENDSTOP_INVERTING Y_MIN_ENDSTOP_INVERTING
#define X2_MIN_PIN Y_MIN_PIN
#elif X2_USE_ENDSTOP == _YMAX_
#define X2_MIN_ENDSTOP_INVERTING Y_MAX_ENDSTOP_INVERTING
#define X2_MIN_PIN Y_MAX_PIN
#elif X2_USE_ENDSTOP == _ZMIN_
#define X2_MIN_ENDSTOP_INVERTING Z_MIN_ENDSTOP_INVERTING
#define X2_MIN_PIN Z_MIN_PIN
#elif X2_USE_ENDSTOP == _ZMAX_
#define X2_MIN_ENDSTOP_INVERTING Z_MAX_ENDSTOP_INVERTING
#define X2_MIN_PIN Z_MAX_PIN
#else
#define X2_MIN_ENDSTOP_INVERTING false
#endif
#endif
// Is an endstop plug used for the X2 endstop?
#define IS_X2_ENDSTOP(A,M) (ENABLED(X_DUAL_ENDSTOPS) && X2_USE_ENDSTOP == _##A##M##_)
/**
* Y_DUAL_ENDSTOPS endstop reassignment
*/
#if ENABLED(Y_DUAL_ENDSTOPS)
#if Y_HOME_DIR > 0
#if Y2_USE_ENDSTOP == _XMIN_
#define Y2_MAX_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING
#define Y2_MAX_PIN X_MIN_PIN
#elif Y2_USE_ENDSTOP == _XMAX_
#define Y2_MAX_ENDSTOP_INVERTING X_MAX_ENDSTOP_INVERTING
#define Y2_MAX_PIN X_MAX_PIN
#elif Y2_USE_ENDSTOP == _YMIN_
#define Y2_MAX_ENDSTOP_INVERTING Y_MIN_ENDSTOP_INVERTING
#define Y2_MAX_PIN Y_MIN_PIN
#elif Y2_USE_ENDSTOP == _YMAX_
#define Y2_MAX_ENDSTOP_INVERTING Y_MAX_ENDSTOP_INVERTING
#define Y2_MAX_PIN Y_MAX_PIN
#elif Y2_USE_ENDSTOP == _ZMIN_
#define Y2_MAX_ENDSTOP_INVERTING Z_MIN_ENDSTOP_INVERTING
#define Y2_MAX_PIN Z_MIN_PIN
#elif Y2_USE_ENDSTOP == _ZMAX_
#define Y2_MAX_ENDSTOP_INVERTING Z_MAX_ENDSTOP_INVERTING
#define Y2_MAX_PIN Z_MAX_PIN
#else
#define Y2_MAX_ENDSTOP_INVERTING false
#endif
#elif Y2_USE_ENDSTOP == _XMIN_
#define Y2_MIN_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING
#define Y2_MIN_PIN X_MIN_PIN
#elif Y2_USE_ENDSTOP == _XMAX_
#define Y2_MIN_ENDSTOP_INVERTING X_MAX_ENDSTOP_INVERTING
#define Y2_MIN_PIN X_MAX_PIN
#elif Y2_USE_ENDSTOP == _YMIN_
#define Y2_MIN_ENDSTOP_INVERTING Y_MIN_ENDSTOP_INVERTING
#define Y2_MIN_PIN Y_MIN_PIN
#elif Y2_USE_ENDSTOP == _YMAX_
#define Y2_MIN_ENDSTOP_INVERTING Y_MAX_ENDSTOP_INVERTING
#define Y2_MIN_PIN Y_MAX_PIN
#elif Y2_USE_ENDSTOP == _ZMIN_
#define Y2_MIN_ENDSTOP_INVERTING Z_MIN_ENDSTOP_INVERTING
#define Y2_MIN_PIN Z_MIN_PIN
#elif Y2_USE_ENDSTOP == _ZMAX_
#define Y2_MIN_ENDSTOP_INVERTING Z_MAX_ENDSTOP_INVERTING
#define Y2_MIN_PIN Z_MAX_PIN
#else
#define Y2_MIN_ENDSTOP_INVERTING false
#endif
#endif
// Is an endstop plug used for the Y2 endstop or the bed probe?
#define IS_Y2_ENDSTOP(A,M) (ENABLED(Y_DUAL_ENDSTOPS) && Y2_USE_ENDSTOP == _##A##M##_)
/** /**
* Z_DUAL_ENDSTOPS endstop reassignment * Z_DUAL_ENDSTOPS endstop reassignment
*/ */
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
#define _XMIN_ 100
#define _YMIN_ 200
#define _ZMIN_ 300
#define _XMAX_ 101
#define _YMAX_ 201
#define _ZMAX_ 301
#if Z2_USE_ENDSTOP == _XMIN_
#define USE_XMIN_PLUG
#elif Z2_USE_ENDSTOP == _XMAX_
#define USE_XMAX_PLUG
#elif Z2_USE_ENDSTOP == _YMIN_
#define USE_YMIN_PLUG
#elif Z2_USE_ENDSTOP == _YMAX_
#define USE_YMAX_PLUG
#elif Z2_USE_ENDSTOP == _ZMIN_
#define USE_ZMIN_PLUG
#elif Z2_USE_ENDSTOP == _ZMAX_
#define USE_ZMAX_PLUG
#endif
#if Z_HOME_DIR > 0 #if Z_HOME_DIR > 0
#if Z2_USE_ENDSTOP == _XMIN_ #if Z2_USE_ENDSTOP == _XMIN_
#define Z2_MAX_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING #define Z2_MAX_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING
@ -423,28 +508,26 @@
#else #else
#define Z2_MAX_ENDSTOP_INVERTING false #define Z2_MAX_ENDSTOP_INVERTING false
#endif #endif
#elif Z2_USE_ENDSTOP == _XMIN_
#define Z2_MIN_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING
#define Z2_MIN_PIN X_MIN_PIN
#elif Z2_USE_ENDSTOP == _XMAX_
#define Z2_MIN_ENDSTOP_INVERTING X_MAX_ENDSTOP_INVERTING
#define Z2_MIN_PIN X_MAX_PIN
#elif Z2_USE_ENDSTOP == _YMIN_
#define Z2_MIN_ENDSTOP_INVERTING Y_MIN_ENDSTOP_INVERTING
#define Z2_MIN_PIN Y_MIN_PIN
#elif Z2_USE_ENDSTOP == _YMAX_
#define Z2_MIN_ENDSTOP_INVERTING Y_MAX_ENDSTOP_INVERTING
#define Z2_MIN_PIN Y_MAX_PIN
#elif Z2_USE_ENDSTOP == _ZMIN_
#define Z2_MIN_ENDSTOP_INVERTING Z_MIN_ENDSTOP_INVERTING
#define Z2_MIN_PIN Z_MIN_PIN
#elif Z2_USE_ENDSTOP == _ZMAX_
#define Z2_MIN_ENDSTOP_INVERTING Z_MAX_ENDSTOP_INVERTING
#define Z2_MIN_PIN Z_MAX_PIN
#else #else
#if Z2_USE_ENDSTOP == _XMIN_ #define Z2_MIN_ENDSTOP_INVERTING false
#define Z2_MIN_ENDSTOP_INVERTING X_MIN_ENDSTOP_INVERTING
#define Z2_MIN_PIN X_MIN_PIN
#elif Z2_USE_ENDSTOP == _XMAX_
#define Z2_MIN_ENDSTOP_INVERTING X_MAX_ENDSTOP_INVERTING
#define Z2_MIN_PIN X_MAX_PIN
#elif Z2_USE_ENDSTOP == _YMIN_
#define Z2_MIN_ENDSTOP_INVERTING Y_MIN_ENDSTOP_INVERTING
#define Z2_MIN_PIN Y_MIN_PIN
#elif Z2_USE_ENDSTOP == _YMAX_
#define Z2_MIN_ENDSTOP_INVERTING Y_MAX_ENDSTOP_INVERTING
#define Z2_MIN_PIN Y_MAX_PIN
#elif Z2_USE_ENDSTOP == _ZMIN_
#define Z2_MIN_ENDSTOP_INVERTING Z_MIN_ENDSTOP_INVERTING
#define Z2_MIN_PIN Z_MIN_PIN
#elif Z2_USE_ENDSTOP == _ZMAX_
#define Z2_MIN_ENDSTOP_INVERTING Z_MAX_ENDSTOP_INVERTING
#define Z2_MIN_PIN Z_MAX_PIN
#else
#define Z2_MIN_ENDSTOP_INVERTING false
#endif
#endif #endif
#endif #endif
@ -541,12 +624,16 @@
#define HAS_SOLENOID_4 (PIN_EXISTS(SOL4)) #define HAS_SOLENOID_4 (PIN_EXISTS(SOL4))
// Endstops and bed probe // Endstops and bed probe
#define HAS_X_MIN (PIN_EXISTS(X_MIN) && !IS_Z2_OR_PROBE(X,MIN)) #define HAS_X_MIN (PIN_EXISTS(X_MIN) && !IS_X2_ENDSTOP(X,MIN) && !IS_Y2_ENDSTOP(X,MIN) && !IS_Z2_OR_PROBE(X,MIN))
#define HAS_X_MAX (PIN_EXISTS(X_MAX) && !IS_Z2_OR_PROBE(X,MAX)) #define HAS_X_MAX (PIN_EXISTS(X_MAX) && !IS_X2_ENDSTOP(X,MAX) && !IS_Y2_ENDSTOP(X,MAX) && !IS_Z2_OR_PROBE(X,MAX))
#define HAS_Y_MIN (PIN_EXISTS(Y_MIN) && !IS_Z2_OR_PROBE(Y,MIN)) #define HAS_Y_MIN (PIN_EXISTS(Y_MIN) && !IS_X2_ENDSTOP(Y,MIN) && !IS_Y2_ENDSTOP(Y,MIN) && !IS_Z2_OR_PROBE(Y,MIN))
#define HAS_Y_MAX (PIN_EXISTS(Y_MAX) && !IS_Z2_OR_PROBE(Y,MAX)) #define HAS_Y_MAX (PIN_EXISTS(Y_MAX) && !IS_X2_ENDSTOP(Y,MAX) && !IS_Y2_ENDSTOP(Y,MAX) && !IS_Z2_OR_PROBE(Y,MAX))
#define HAS_Z_MIN (PIN_EXISTS(Z_MIN) && !IS_Z2_OR_PROBE(Z,MIN)) #define HAS_Z_MIN (PIN_EXISTS(Z_MIN) && !IS_X2_ENDSTOP(Z,MIN) && !IS_Y2_ENDSTOP(Z,MIN) && !IS_Z2_OR_PROBE(Z,MIN))
#define HAS_Z_MAX (PIN_EXISTS(Z_MAX) && !IS_Z2_OR_PROBE(Z,MAX)) #define HAS_Z_MAX (PIN_EXISTS(Z_MAX) && !IS_X2_ENDSTOP(Z,MAX) && !IS_Y2_ENDSTOP(Z,MAX) && !IS_Z2_OR_PROBE(Z,MAX))
#define HAS_X2_MIN (PIN_EXISTS(X2_MIN))
#define HAS_X2_MAX (PIN_EXISTS(X2_MAX))
#define HAS_Y2_MIN (PIN_EXISTS(Y2_MIN))
#define HAS_Y2_MAX (PIN_EXISTS(Y2_MAX))
#define HAS_Z2_MIN (PIN_EXISTS(Z2_MIN)) #define HAS_Z2_MIN (PIN_EXISTS(Z2_MIN))
#define HAS_Z2_MAX (PIN_EXISTS(Z2_MAX)) #define HAS_Z2_MAX (PIN_EXISTS(Z2_MAX))
#define HAS_Z_MIN_PROBE_PIN (PIN_EXISTS(Z_MIN_PROBE)) #define HAS_Z_MIN_PROBE_PIN (PIN_EXISTS(Z_MIN_PROBE))

@ -331,6 +331,12 @@ extern float soft_endstop_min[XYZ], soft_endstop_max[XYZ];
void set_z_fade_height(const float zfh); void set_z_fade_height(const float zfh);
#endif #endif
#if ENABLED(X_DUAL_ENDSTOPS)
extern float x_endstop_adj;
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
extern float y_endstop_adj;
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
extern float z_endstop_adj; extern float z_endstop_adj;
#endif #endif

@ -562,13 +562,19 @@ static uint8_t target_extruder;
#define ADJUST_DELTA(V) NOOP #define ADJUST_DELTA(V) NOOP
#endif #endif
#if ENABLED(X_DUAL_ENDSTOPS)
float x_endstop_adj; // Initialized by settings.load()
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
float y_endstop_adj; // Initialized by settings.load()
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
float z_endstop_adj; float z_endstop_adj; // Initialized by settings.load()
#endif #endif
// Extruder offsets // Extruder offsets
#if HOTENDS > 1 #if HOTENDS > 1
float hotend_offset[XYZ][HOTENDS]; // Initialized by settings.load() float hotend_offset[XYZ][HOTENDS]; // Initialized by settings.load()
#endif #endif
#if HAS_Z_SERVO_ENDSTOP #if HAS_Z_SERVO_ENDSTOP
@ -3017,9 +3023,15 @@ static void homeaxis(const AxisEnum axis) {
if (axis == Z_AXIS && DEPLOY_PROBE()) return; if (axis == Z_AXIS && DEPLOY_PROBE()) return;
#endif #endif
// Set a flag for Z motor locking // Set flags for X, Y, Z motor locking
#if ENABLED(X_DUAL_ENDSTOPS)
if (axis == X_AXIS) stepper.set_homing_flag_x(true);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
if (axis == Y_AXIS) stepper.set_homing_flag_y(true);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
if (axis == Z_AXIS) stepper.set_homing_flag(true); if (axis == Z_AXIS) stepper.set_homing_flag_z(true);
#endif #endif
// Disable stealthChop if used. Enable diag1 pin on driver. // Disable stealthChop if used. Enable diag1 pin on driver.
@ -3061,25 +3073,41 @@ static void homeaxis(const AxisEnum axis) {
do_homing_move(axis, 2 * bump, get_homing_bump_feedrate(axis)); do_homing_move(axis, 2 * bump, get_homing_bump_feedrate(axis));
} }
#if ENABLED(Z_DUAL_ENDSTOPS) /**
if (axis == Z_AXIS) { * Home axes that have dual endstops... differently
float adj = FABS(z_endstop_adj); */
bool lockZ1; #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
if (axis_home_dir > 0) { const bool pos_dir = axis_home_dir > 0;
adj = -adj; #if ENABLED(X_DUAL_ENDSTOPS)
lockZ1 = (z_endstop_adj > 0); if (axis == X_AXIS) {
const bool lock_x1 = pos_dir ? (x_endstop_adj > 0) : (x_endstop_adj < 0);
const float adj = FABS(x_endstop_adj);
if (lock_x1) stepper.set_x_lock(true); else stepper.set_x2_lock(true);
do_homing_move(axis, pos_dir ? -adj : adj);
if (lock_x1) stepper.set_x_lock(false); else stepper.set_x2_lock(false);
stepper.set_homing_flag_x(false);
} }
else #endif
lockZ1 = (z_endstop_adj < 0); #if ENABLED(Y_DUAL_ENDSTOPS)
if (axis == Y_AXIS) {
if (lockZ1) stepper.set_z_lock(true); else stepper.set_z2_lock(true); const bool lock_y1 = pos_dir ? (y_endstop_adj > 0) : (y_endstop_adj < 0);
const float adj = FABS(y_endstop_adj);
// Move to the adjusted endstop height if (lock_y1) stepper.set_y_lock(true); else stepper.set_y2_lock(true);
do_homing_move(axis, adj); do_homing_move(axis, pos_dir ? -adj : adj);
if (lock_y1) stepper.set_y_lock(false); else stepper.set_y2_lock(false);
if (lockZ1) stepper.set_z_lock(false); else stepper.set_z2_lock(false); stepper.set_homing_flag_y(false);
stepper.set_homing_flag(false); }
} // Z_AXIS #endif
#if ENABLED(Z_DUAL_ENDSTOPS)
if (axis == Z_AXIS) {
const bool lock_z1 = pos_dir ? (z_endstop_adj > 0) : (z_endstop_adj < 0);
const float adj = FABS(z_endstop_adj);
if (lock_z1) stepper.set_z_lock(true); else stepper.set_z2_lock(true);
do_homing_move(axis, pos_dir ? -adj : adj);
if (lock_z1) stepper.set_z_lock(false); else stepper.set_z2_lock(false);
stepper.set_homing_flag_z(false);
}
#endif
#endif #endif
#if IS_SCARA #if IS_SCARA
@ -8894,14 +8922,28 @@ inline void gcode_M205() {
} }
} }
#elif ENABLED(Z_DUAL_ENDSTOPS) // !DELTA && ENABLED(Z_DUAL_ENDSTOPS)
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
/** /**
* M666: For Z Dual Endstop setup, set z axis offset to the z2 axis. * M666: For Z Dual Endstop setup, set z axis offset to the z2 axis.
*/ */
inline void gcode_M666() { inline void gcode_M666() {
if (parser.seen('Z')) z_endstop_adj = parser.value_linear_units(); SERIAL_ECHOPGM("Dual Endstop Adjustment (mm): ");
SERIAL_ECHOLNPAIR("Z Endstop Adjustment set to (mm):", z_endstop_adj); #if ENABLED(X_DUAL_ENDSTOPS)
if (parser.seen('X')) x_endstop_adj = parser.value_linear_units();
SERIAL_ECHOPAIR(" X", x_endstop_adj);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
if (parser.seen('Y')) y_endstop_adj = parser.value_linear_units();
SERIAL_ECHOPAIR(" Y", y_endstop_adj);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
if (parser.seen('Z')) z_endstop_adj = parser.value_linear_units();
SERIAL_ECHOPAIR(" Z", z_endstop_adj);
#endif
SERIAL_EOL();
} }
#endif // !DELTA && Z_DUAL_ENDSTOPS #endif // !DELTA && Z_DUAL_ENDSTOPS
@ -11606,7 +11648,7 @@ void process_next_command() {
break; break;
#endif #endif
#if ENABLED(DELTA) || ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(DELTA) || ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
case 666: // M666: Set delta or dual endstop adjustment case 666: // M666: Set delta or dual endstop adjustment
gcode_M666(); gcode_M666();
break; break;
@ -13949,4 +13991,3 @@ void loop() {
endstops.report_state(); endstops.report_state();
idle(); idle();
} }

@ -78,8 +78,6 @@
#error "FILAMENT_SENSOR is deprecated. Use FILAMENT_WIDTH_SENSOR instead." #error "FILAMENT_SENSOR is deprecated. Use FILAMENT_WIDTH_SENSOR instead."
#elif defined(DISABLE_MAX_ENDSTOPS) || defined(DISABLE_MIN_ENDSTOPS) #elif defined(DISABLE_MAX_ENDSTOPS) || defined(DISABLE_MIN_ENDSTOPS)
#error "DISABLE_MAX_ENDSTOPS and DISABLE_MIN_ENDSTOPS deprecated. Use individual USE_*_PLUG options instead." #error "DISABLE_MAX_ENDSTOPS and DISABLE_MIN_ENDSTOPS deprecated. Use individual USE_*_PLUG options instead."
#elif ENABLED(Z_DUAL_ENDSTOPS) && !defined(Z2_USE_ENDSTOP)
#error "Z_DUAL_ENDSTOPS settings are simplified. Just set Z2_USE_ENDSTOP to the endstop you want to repurpose for Z2."
#elif defined(LANGUAGE_INCLUDE) #elif defined(LANGUAGE_INCLUDE)
#error "LANGUAGE_INCLUDE has been replaced by LCD_LANGUAGE. Please update your configuration." #error "LANGUAGE_INCLUDE has been replaced by LCD_LANGUAGE. Please update your configuration."
#elif defined(EXTRUDER_OFFSET_X) || defined(EXTRUDER_OFFSET_Y) #elif defined(EXTRUDER_OFFSET_X) || defined(EXTRUDER_OFFSET_Y)
@ -1059,23 +1057,25 @@ static_assert(1 >= 0
#endif #endif
/** /**
* Endstops * Endstop Tests
*/ */
#if DISABLED(USE_XMIN_PLUG) && DISABLED(USE_XMAX_PLUG) && !(ENABLED(Z_DUAL_ENDSTOPS) && WITHIN(Z2_USE_ENDSTOP, _XMAX_, _XMIN_))
#error "You must enable USE_XMIN_PLUG or USE_XMAX_PLUG." #define _PLUG_UNUSED_TEST(AXIS,PLUG) (DISABLED(USE_##PLUG##MIN_PLUG) && DISABLED(USE_##PLUG##MAX_PLUG) && !(ENABLED(AXIS##_DUAL_ENDSTOPS) && WITHIN(AXIS##2_USE_ENDSTOP, _##PLUG##MAX_, _##PLUG##MIN_)))
#elif DISABLED(USE_YMIN_PLUG) && DISABLED(USE_YMAX_PLUG) && !(ENABLED(Z_DUAL_ENDSTOPS) && WITHIN(Z2_USE_ENDSTOP, _YMAX_, _YMIN_)) #define _AXIS_PLUG_UNUSED_TEST(AXIS) (_PLUG_UNUSED_TEST(AXIS,X) && _PLUG_UNUSED_TEST(AXIS,Y) && _PLUG_UNUSED_TEST(AXIS,Z))
#error "You must enable USE_YMIN_PLUG or USE_YMAX_PLUG."
#elif DISABLED(USE_ZMIN_PLUG) && DISABLED(USE_ZMAX_PLUG) && !(ENABLED(Z_DUAL_ENDSTOPS) && WITHIN(Z2_USE_ENDSTOP, _ZMAX_, _ZMIN_)) // At least 3 endstop plugs must be used
#error "You must enable USE_ZMIN_PLUG or USE_ZMAX_PLUG." #if _AXIS_PLUG_UNUSED_TEST(X)
#elif ENABLED(Z_DUAL_ENDSTOPS) #error "You must enable USE_XMIN_PLUG or USE_XMAX_PLUG."
#if !Z2_USE_ENDSTOP #endif
#error "You must set Z2_USE_ENDSTOP with Z_DUAL_ENDSTOPS." #if _AXIS_PLUG_UNUSED_TEST(Y)
#elif Z2_MAX_PIN == 0 && Z2_MIN_PIN == 0 #error "You must enable USE_YMIN_PLUG or USE_YMAX_PLUG."
#error "Z2_USE_ENDSTOP has been assigned to a nonexistent endstop!" #endif
#elif ENABLED(DELTA) #if _AXIS_PLUG_UNUSED_TEST(Z)
#error "Z_DUAL_ENDSTOPS is not compatible with DELTA." #error "You must enable USE_ZMIN_PLUG or USE_ZMAX_PLUG."
#endif #endif
#elif !IS_SCARA
// Delta and Cartesian use 3 homing endstops
#if !IS_SCARA
#if X_HOME_DIR < 0 && DISABLED(USE_XMIN_PLUG) #if X_HOME_DIR < 0 && DISABLED(USE_XMIN_PLUG)
#error "Enable USE_XMIN_PLUG when homing X to MIN." #error "Enable USE_XMIN_PLUG when homing X to MIN."
#elif X_HOME_DIR > 0 && DISABLED(USE_XMAX_PLUG) #elif X_HOME_DIR > 0 && DISABLED(USE_XMAX_PLUG)
@ -1084,10 +1084,76 @@ static_assert(1 >= 0
#error "Enable USE_YMIN_PLUG when homing Y to MIN." #error "Enable USE_YMIN_PLUG when homing Y to MIN."
#elif Y_HOME_DIR > 0 && DISABLED(USE_YMAX_PLUG) #elif Y_HOME_DIR > 0 && DISABLED(USE_YMAX_PLUG)
#error "Enable USE_YMAX_PLUG when homing Y to MAX." #error "Enable USE_YMAX_PLUG when homing Y to MAX."
#elif Z_HOME_DIR < 0 && DISABLED(USE_ZMIN_PLUG) #endif
#error "Enable USE_ZMIN_PLUG when homing Z to MIN." #endif
#elif Z_HOME_DIR > 0 && DISABLED(USE_ZMAX_PLUG) #if Z_HOME_DIR < 0 && DISABLED(USE_ZMIN_PLUG)
#error "Enable USE_ZMAX_PLUG when homing Z to MAX." #error "Enable USE_ZMIN_PLUG when homing Z to MIN."
#elif Z_HOME_DIR > 0 && DISABLED(USE_ZMAX_PLUG)
#error "Enable USE_ZMAX_PLUG when homing Z to MAX."
#endif
// Dual endstops requirements
#if ENABLED(X_DUAL_ENDSTOPS)
#if !X2_USE_ENDSTOP
#error "You must set X2_USE_ENDSTOP with X_DUAL_ENDSTOPS."
#elif X2_USE_ENDSTOP == _X_MIN_ && DISABLED(USE_XMIN_PLUG)
#error "USE_XMIN_PLUG is required when X2_USE_ENDSTOP is _X_MIN_."
#elif X2_USE_ENDSTOP == _X_MAX_ && DISABLED(USE_XMAX_PLUG)
#error "USE_XMAX_PLUG is required when X2_USE_ENDSTOP is _X_MAX_."
#elif X2_USE_ENDSTOP == _Y_MIN_ && DISABLED(USE_YMIN_PLUG)
#error "USE_YMIN_PLUG is required when X2_USE_ENDSTOP is _Y_MIN_."
#elif X2_USE_ENDSTOP == _Y_MAX_ && DISABLED(USE_YMAX_PLUG)
#error "USE_YMAX_PLUG is required when X2_USE_ENDSTOP is _Y_MAX_."
#elif X2_USE_ENDSTOP == _Z_MIN_ && DISABLED(USE_ZMIN_PLUG)
#error "USE_ZMIN_PLUG is required when X2_USE_ENDSTOP is _Z_MIN_."
#elif X2_USE_ENDSTOP == _Z_MAX_ && DISABLED(USE_ZMAX_PLUG)
#error "USE_ZMAX_PLUG is required when X2_USE_ENDSTOP is _Z_MAX_."
#elif !HAS_X2_MIN && !HAS_X2_MAX
#error "X2_USE_ENDSTOP has been assigned to a nonexistent endstop!"
#elif ENABLED(DELTA)
#error "X_DUAL_ENDSTOPS is not compatible with DELTA."
#endif
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
#if !Y2_USE_ENDSTOP
#error "You must set Y2_USE_ENDSTOP with Y_DUAL_ENDSTOPS."
#elif Y2_USE_ENDSTOP == _X_MIN_ && DISABLED(USE_XMIN_PLUG)
#error "USE_XMIN_PLUG is required when Y2_USE_ENDSTOP is _X_MIN_."
#elif Y2_USE_ENDSTOP == _X_MAX_ && DISABLED(USE_XMAX_PLUG)
#error "USE_XMAX_PLUG is required when Y2_USE_ENDSTOP is _X_MAX_."
#elif Y2_USE_ENDSTOP == _Y_MIN_ && DISABLED(USE_YMIN_PLUG)
#error "USE_YMIN_PLUG is required when Y2_USE_ENDSTOP is _Y_MIN_."
#elif Y2_USE_ENDSTOP == _Y_MAX_ && DISABLED(USE_YMAX_PLUG)
#error "USE_YMAX_PLUG is required when Y2_USE_ENDSTOP is _Y_MAX_."
#elif Y2_USE_ENDSTOP == _Z_MIN_ && DISABLED(USE_ZMIN_PLUG)
#error "USE_ZMIN_PLUG is required when Y2_USE_ENDSTOP is _Z_MIN_."
#elif Y2_USE_ENDSTOP == _Z_MAX_ && DISABLED(USE_ZMAX_PLUG)
#error "USE_ZMAX_PLUG is required when Y2_USE_ENDSTOP is _Z_MAX_."
#elif !HAS_Y2_MIN && !HAS_Y2_MAX
#error "Y2_USE_ENDSTOP has been assigned to a nonexistent endstop!"
#elif ENABLED(DELTA)
#error "Y_DUAL_ENDSTOPS is not compatible with DELTA."
#endif
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
#if !Z2_USE_ENDSTOP
#error "You must set Z2_USE_ENDSTOP with Z_DUAL_ENDSTOPS."
#elif Z2_USE_ENDSTOP == _X_MIN_ && DISABLED(USE_XMIN_PLUG)
#error "USE_XMIN_PLUG is required when Z2_USE_ENDSTOP is _X_MIN_."
#elif Z2_USE_ENDSTOP == _X_MAX_ && DISABLED(USE_XMAX_PLUG)
#error "USE_XMAX_PLUG is required when Z2_USE_ENDSTOP is _X_MAX_."
#elif Z2_USE_ENDSTOP == _Y_MIN_ && DISABLED(USE_YMIN_PLUG)
#error "USE_YMIN_PLUG is required when Z2_USE_ENDSTOP is _Y_MIN_."
#elif Z2_USE_ENDSTOP == _Y_MAX_ && DISABLED(USE_YMAX_PLUG)
#error "USE_YMAX_PLUG is required when Z2_USE_ENDSTOP is _Y_MAX_."
#elif Z2_USE_ENDSTOP == _Z_MIN_ && DISABLED(USE_ZMIN_PLUG)
#error "USE_ZMIN_PLUG is required when Z2_USE_ENDSTOP is _Z_MIN_."
#elif Z2_USE_ENDSTOP == _Z_MAX_ && DISABLED(USE_ZMAX_PLUG)
#error "USE_ZMAX_PLUG is required when Z2_USE_ENDSTOP is _Z_MAX_."
#elif !HAS_Z2_MIN && !HAS_Z2_MAX
#error "Z2_USE_ENDSTOP has been assigned to a nonexistent endstop!"
#elif ENABLED(DELTA)
#error "Z_DUAL_ENDSTOPS is not compatible with DELTA."
#endif #endif
#endif #endif

@ -36,13 +36,13 @@
* *
*/ */
#define EEPROM_VERSION "V42" #define EEPROM_VERSION "V43"
// Change EEPROM version if these are changed: // Change EEPROM version if these are changed:
#define EEPROM_OFFSET 100 #define EEPROM_OFFSET 100
/** /**
* V42 EEPROM Layout: * V43 EEPROM Layout:
* *
* 100 Version (char x4) * 100 Version (char x4)
* 104 EEPROM CRC16 (uint16_t) * 104 EEPROM CRC16 (uint16_t)
@ -87,82 +87,83 @@
* 312 G29 L F bilinear_start (int x2) * 312 G29 L F bilinear_start (int x2)
* 316 z_values[][] (float x9, up to float x256) +988 * 316 z_values[][] (float x9, up to float x256) +988
* *
* AUTO_BED_LEVELING_UBL: 6 bytes * AUTO_BED_LEVELING_UBL: 2 bytes
* 324 G29 A planner.leveling_active (bool) * 324 G29 A planner.leveling_active (bool)
* 325 G29 S ubl.storage_slot (int8_t) * 325 G29 S ubl.storage_slot (int8_t)
* *
* DELTA: 48 bytes * DELTA: 40 bytes
* 348 M666 XYZ delta_endstop_adj (float x3) * 352 M666 XYZ delta_endstop_adj (float x3)
* 360 M665 R delta_radius (float) * 364 M665 R delta_radius (float)
* 364 M665 L delta_diagonal_rod (float) * 368 M665 L delta_diagonal_rod (float)
* 368 M665 S delta_segments_per_second (float) * 372 M665 S delta_segments_per_second (float)
* 372 M665 B delta_calibration_radius (float) * 376 M665 B delta_calibration_radius (float)
* 376 M665 X delta_tower_angle_trim[A] (float) * 380 M665 X delta_tower_angle_trim[A] (float)
* 380 M665 Y delta_tower_angle_trim[B] (float) * 384 M665 Y delta_tower_angle_trim[B] (float)
* 384 M665 Z delta_tower_angle_trim[C] (float) * 388 M665 Z delta_tower_angle_trim[C] (float)
* *
* Z_DUAL_ENDSTOPS: 48 bytes * [XYZ]_DUAL_ENDSTOPS: 12 bytes
* 348 M666 Z z_endstop_adj (float) * 352 M666 X x_endstop_adj (float)
* --- dummy data (float x11) * 356 M666 Y y_endstop_adj (float)
* 360 M666 Z z_endstop_adj (float)
* *
* ULTIPANEL: 6 bytes * ULTIPANEL: 6 bytes
* 396 M145 S0 H lcd_preheat_hotend_temp (int x2) * 392 M145 S0 H lcd_preheat_hotend_temp (int x2)
* 400 M145 S0 B lcd_preheat_bed_temp (int x2) * 396 M145 S0 B lcd_preheat_bed_temp (int x2)
* 404 M145 S0 F lcd_preheat_fan_speed (int x2) * 400 M145 S0 F lcd_preheat_fan_speed (int x2)
* *
* PIDTEMP: 66 bytes * PIDTEMP: 82 bytes
* 408 M301 E0 PIDC Kp[0], Ki[0], Kd[0], Kc[0] (float x4) * 404 M301 E0 PIDC Kp[0], Ki[0], Kd[0], Kc[0] (float x4)
* 424 M301 E1 PIDC Kp[1], Ki[1], Kd[1], Kc[1] (float x4) * 420 M301 E1 PIDC Kp[1], Ki[1], Kd[1], Kc[1] (float x4)
* 440 M301 E2 PIDC Kp[2], Ki[2], Kd[2], Kc[2] (float x4) * 436 M301 E2 PIDC Kp[2], Ki[2], Kd[2], Kc[2] (float x4)
* 456 M301 E3 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4) * 452 M301 E3 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4)
* 472 M301 E4 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4) * 468 M301 E4 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4)
* 488 M301 L lpq_len (int) * 484 M301 L lpq_len (int)
* *
* PIDTEMPBED: 12 bytes * PIDTEMPBED: 12 bytes
* 490 M304 PID thermalManager.bedKp, .bedKi, .bedKd (float x3) * 486 M304 PID thermalManager.bedKp, .bedKi, .bedKd (float x3)
* *
* DOGLCD: 2 bytes * DOGLCD: 2 bytes
* 502 M250 C lcd_contrast (uint16_t) * 498 M250 C lcd_contrast (uint16_t)
* *
* FWRETRACT: 33 bytes * FWRETRACT: 33 bytes
* 504 M209 S autoretract_enabled (bool) * 500 M209 S autoretract_enabled (bool)
* 505 M207 S retract_length (float) * 501 M207 S retract_length (float)
* 509 M207 F retract_feedrate_mm_s (float) * 505 M207 F retract_feedrate_mm_s (float)
* 513 M207 Z retract_zlift (float) * 509 M207 Z retract_zlift (float)
* 517 M208 S retract_recover_length (float) * 513 M208 S retract_recover_length (float)
* 521 M208 F retract_recover_feedrate_mm_s (float) * 517 M208 F retract_recover_feedrate_mm_s (float)
* 525 M207 W swap_retract_length (float) * 521 M207 W swap_retract_length (float)
* 529 M208 W swap_retract_recover_length (float) * 525 M208 W swap_retract_recover_length (float)
* 533 M208 R swap_retract_recover_feedrate_mm_s (float) * 529 M208 R swap_retract_recover_feedrate_mm_s (float)
* *
* Volumetric Extrusion: 21 bytes * Volumetric Extrusion: 21 bytes
* 537 M200 D volumetric_enabled (bool) * 533 M200 D volumetric_enabled (bool)
* 538 M200 T D filament_size (float x5) (T0..3) * 534 M200 T D filament_size (float x5) (T0..3)
* *
* HAVE_TMC2130: 20 bytes * HAVE_TMC2130: 22 bytes
* 558 M906 X Stepper X current (uint16_t) * 554 M906 X Stepper X current (uint16_t)
* 560 M906 Y Stepper Y current (uint16_t) * 556 M906 Y Stepper Y current (uint16_t)
* 562 M906 Z Stepper Z current (uint16_t) * 558 M906 Z Stepper Z current (uint16_t)
* 564 M906 X2 Stepper X2 current (uint16_t) * 560 M906 X2 Stepper X2 current (uint16_t)
* 566 M906 Y2 Stepper Y2 current (uint16_t) * 562 M906 Y2 Stepper Y2 current (uint16_t)
* 568 M906 Z2 Stepper Z2 current (uint16_t) * 564 M906 Z2 Stepper Z2 current (uint16_t)
* 570 M906 E0 Stepper E0 current (uint16_t) * 566 M906 E0 Stepper E0 current (uint16_t)
* 572 M906 E1 Stepper E1 current (uint16_t) * 568 M906 E1 Stepper E1 current (uint16_t)
* 574 M906 E2 Stepper E2 current (uint16_t) * 570 M906 E2 Stepper E2 current (uint16_t)
* 576 M906 E3 Stepper E3 current (uint16_t) * 572 M906 E3 Stepper E3 current (uint16_t)
* 580 M906 E4 Stepper E4 current (uint16_t) * 574 M906 E4 Stepper E4 current (uint16_t)
* *
* LIN_ADVANCE: 8 bytes * LIN_ADVANCE: 8 bytes
* 584 M900 K extruder_advance_k (float) * 576 M900 K extruder_advance_k (float)
* 588 M900 WHD advance_ed_ratio (float) * 580 M900 WHD advance_ed_ratio (float)
* *
* HAS_MOTOR_CURRENT_PWM: * HAS_MOTOR_CURRENT_PWM:
* 592 M907 X Stepper XY current (uint32_t) * 584 M907 X Stepper XY current (uint32_t)
* 596 M907 Z Stepper Z current (uint32_t) * 588 M907 Z Stepper Z current (uint32_t)
* 600 M907 E Stepper E current (uint32_t) * 592 M907 E Stepper E current (uint32_t)
* *
* 604 Minimum end-point * 596 Minimum end-point
* 1925 (604 + 36 + 9 + 288 + 988) Maximum end-point * 1917 (596 + 36 + 9 + 288 + 988) Maximum end-point
* *
* ======================================================================== * ========================================================================
* meshes_begin (between max and min end-point, directly above) * meshes_begin (between max and min end-point, directly above)
@ -209,8 +210,8 @@ MarlinSettings settings;
#endif #endif
/** /**
* Post-process after Retrieve or Reset * Post-process after Retrieve or Reset
*/ */
void MarlinSettings::postprocess() { void MarlinSettings::postprocess() {
// steps per s2 needs to be updated to agree with units per s2 // steps per s2 needs to be updated to agree with units per s2
planner.reset_acceleration_rates(); planner.reset_acceleration_rates();
@ -448,7 +449,7 @@ void MarlinSettings::postprocess() {
EEPROM_WRITE(storage_slot); EEPROM_WRITE(storage_slot);
#endif // AUTO_BED_LEVELING_UBL #endif // AUTO_BED_LEVELING_UBL
// 10 floats for DELTA / Z_DUAL_ENDSTOPS // 10 floats for DELTA / [XYZ]_DUAL_ENDSTOPS
#if ENABLED(DELTA) #if ENABLED(DELTA)
EEPROM_WRITE(delta_endstop_adj); // 3 floats EEPROM_WRITE(delta_endstop_adj); // 3 floats
EEPROM_WRITE(delta_radius); // 1 float EEPROM_WRITE(delta_radius); // 1 float
@ -456,15 +457,33 @@ void MarlinSettings::postprocess() {
EEPROM_WRITE(delta_segments_per_second); // 1 float EEPROM_WRITE(delta_segments_per_second); // 1 float
EEPROM_WRITE(delta_calibration_radius); // 1 float EEPROM_WRITE(delta_calibration_radius); // 1 float
EEPROM_WRITE(delta_tower_angle_trim); // 3 floats EEPROM_WRITE(delta_tower_angle_trim); // 3 floats
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
// Write dual endstops in X, Y, Z order. Unused = 0.0
dummy = 0.0f; dummy = 0.0f;
for (uint8_t q = 2; q--;) EEPROM_WRITE(dummy); #if ENABLED(X_DUAL_ENDSTOPS)
#elif ENABLED(Z_DUAL_ENDSTOPS) EEPROM_WRITE(x_endstop_adj); // 1 float
EEPROM_WRITE(z_endstop_adj); // 1 float #else
dummy = 0.0f; EEPROM_WRITE(dummy);
for (uint8_t q = 11; q--;) EEPROM_WRITE(dummy); #endif
#if ENABLED(Y_DUAL_ENDSTOPS)
EEPROM_WRITE(y_endstop_adj); // 1 float
#else
EEPROM_WRITE(dummy);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
EEPROM_WRITE(z_endstop_adj); // 1 float
#else
EEPROM_WRITE(dummy);
#endif
for (uint8_t q = 7; q--;) EEPROM_WRITE(dummy);
#else #else
dummy = 0.0f; dummy = 0.0f;
for (uint8_t q = 12; q--;) EEPROM_WRITE(dummy); for (uint8_t q = 10; q--;) EEPROM_WRITE(dummy);
#endif #endif
#if DISABLED(ULTIPANEL) #if DISABLED(ULTIPANEL)
@ -845,13 +864,31 @@ void MarlinSettings::postprocess() {
EEPROM_READ(delta_tower_angle_trim); // 3 floats EEPROM_READ(delta_tower_angle_trim); // 3 floats
dummy = 0.0f; dummy = 0.0f;
for (uint8_t q=2; q--;) EEPROM_READ(dummy); for (uint8_t q=2; q--;) EEPROM_READ(dummy);
#elif ENABLED(Z_DUAL_ENDSTOPS)
EEPROM_READ(z_endstop_adj); #elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
dummy = 0.0f;
for (uint8_t q=11; q--;) EEPROM_READ(dummy); #if ENABLED(X_DUAL_ENDSTOPS)
EEPROM_READ(x_endstop_adj); // 1 float
#else
EEPROM_READ(dummy);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
EEPROM_READ(y_endstop_adj); // 1 float
#else
EEPROM_READ(dummy);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
EEPROM_READ(z_endstop_adj); // 1 float
#else
EEPROM_READ(dummy);
#endif
for (uint8_t q=7; q--;) EEPROM_READ(dummy);
#else #else
dummy = 0.0f;
for (uint8_t q=12; q--;) EEPROM_READ(dummy); for (uint8_t q=10; q--;) EEPROM_READ(dummy);
#endif #endif
#if DISABLED(ULTIPANEL) #if DISABLED(ULTIPANEL)
@ -1234,15 +1271,35 @@ void MarlinSettings::reset() {
COPY(delta_tower_angle_trim, dta); COPY(delta_tower_angle_trim, dta);
home_offset[Z_AXIS] = 0; home_offset[Z_AXIS] = 0;
#elif ENABLED(Z_DUAL_ENDSTOPS) #elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
z_endstop_adj = #if ENABLED(X_DUAL_ENDSTOPS)
#ifdef Z_DUAL_ENDSTOPS_ADJUSTMENT x_endstop_adj = (
Z_DUAL_ENDSTOPS_ADJUSTMENT #ifdef X_DUAL_ENDSTOPS_ADJUSTMENT
#else X_DUAL_ENDSTOPS_ADJUSTMENT
0 #else
#endif 0
; #endif
);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
y_endstop_adj = (
#ifdef Y_DUAL_ENDSTOPS_ADJUSTMENT
Y_DUAL_ENDSTOPS_ADJUSTMENT
#else
0
#endif
);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
z_endstop_adj = (
#ifdef Z_DUAL_ENDSTOPS_ADJUSTMENT
Z_DUAL_ENDSTOPS_ADJUSTMENT
#else
0
#endif
);
#endif
#endif #endif
@ -1656,13 +1713,24 @@ void MarlinSettings::reset() {
SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(delta_tower_angle_trim[B_AXIS])); SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(delta_tower_angle_trim[B_AXIS]));
SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(delta_tower_angle_trim[C_AXIS])); SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(delta_tower_angle_trim[C_AXIS]));
SERIAL_EOL(); SERIAL_EOL();
#elif ENABLED(Z_DUAL_ENDSTOPS)
#elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
if (!forReplay) { if (!forReplay) {
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOLNPGM("Z2 Endstop adjustment:"); SERIAL_ECHOLNPGM("Endstop adjustment:");
} }
CONFIG_ECHO_START; CONFIG_ECHO_START;
SERIAL_ECHOLNPAIR(" M666 Z", LINEAR_UNIT(z_endstop_adj)); SERIAL_ECHOPGM(" M666");
#if ENABLED(X_DUAL_ENDSTOPS)
SERIAL_ECHOPAIR(" X", LINEAR_UNIT(x_endstop_adj));
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(y_endstop_adj));
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(z_endstop_adj));
#endif
SERIAL_EOL();
#endif // DELTA #endif // DELTA
#if ENABLED(ULTIPANEL) #if ENABLED(ULTIPANEL)

@ -170,6 +170,46 @@ void setup_endstop_interrupts( void ) {
#endif #endif
#endif #endif
#if HAS_X2_MAX
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(X2_MAX_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(X2_MAX_PIN) != NULL, "X2_MAX_PIN is not interrupt-capable");
pciSetup(X2_MAX_PIN);
#endif
#endif
#if HAS_X2_MIN
#if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(X2_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(X2_MIN_PIN) != NULL, "X2_MIN_PIN is not interrupt-capable");
pciSetup(X2_MIN_PIN);
#endif
#endif
#if HAS_Y2_MAX
#if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(Y2_MAX_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Y2_MAX_PIN) != NULL, "Y2_MAX_PIN is not interrupt-capable");
pciSetup(Y2_MAX_PIN);
#endif
#endif
#if HAS_Y2_MIN
#if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(Y2_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Y2_MIN_PIN) != NULL, "Y2_MIN_PIN is not interrupt-capable");
pciSetup(Y2_MIN_PIN);
#endif
#endif
#if HAS_Z2_MAX #if HAS_Z2_MAX
#if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(Z2_MAX_PIN), endstop_ISR, CHANGE); attachInterrupt(digitalPinToInterrupt(Z2_MAX_PIN), endstop_ISR, CHANGE);

@ -41,7 +41,7 @@ Endstops endstops;
bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load() bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load()
volatile char Endstops::endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value volatile char Endstops::endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
uint16_t uint16_t
#else #else
byte byte
@ -67,6 +67,14 @@ void Endstops::init() {
#endif #endif
#endif #endif
#if HAS_X2_MIN
#if ENABLED(ENDSTOPPULLUP_XMIN)
SET_INPUT_PULLUP(X2_MIN_PIN);
#else
SET_INPUT(X2_MIN_PIN);
#endif
#endif
#if HAS_Y_MIN #if HAS_Y_MIN
#if ENABLED(ENDSTOPPULLUP_YMIN) #if ENABLED(ENDSTOPPULLUP_YMIN)
SET_INPUT_PULLUP(Y_MIN_PIN); SET_INPUT_PULLUP(Y_MIN_PIN);
@ -75,6 +83,14 @@ void Endstops::init() {
#endif #endif
#endif #endif
#if HAS_Y2_MIN
#if ENABLED(ENDSTOPPULLUP_YMIN)
SET_INPUT_PULLUP(Y2_MIN_PIN);
#else
SET_INPUT(Y2_MIN_PIN);
#endif
#endif
#if HAS_Z_MIN #if HAS_Z_MIN
#if ENABLED(ENDSTOPPULLUP_ZMIN) #if ENABLED(ENDSTOPPULLUP_ZMIN)
SET_INPUT_PULLUP(Z_MIN_PIN); SET_INPUT_PULLUP(Z_MIN_PIN);
@ -99,6 +115,14 @@ void Endstops::init() {
#endif #endif
#endif #endif
#if HAS_X2_MAX
#if ENABLED(ENDSTOPPULLUP_XMAX)
SET_INPUT_PULLUP(X2_MAX_PIN);
#else
SET_INPUT(X2_MAX_PIN);
#endif
#endif
#if HAS_Y_MAX #if HAS_Y_MAX
#if ENABLED(ENDSTOPPULLUP_YMAX) #if ENABLED(ENDSTOPPULLUP_YMAX)
SET_INPUT_PULLUP(Y_MAX_PIN); SET_INPUT_PULLUP(Y_MAX_PIN);
@ -107,6 +131,14 @@ void Endstops::init() {
#endif #endif
#endif #endif
#if HAS_Y2_MAX
#if ENABLED(ENDSTOPPULLUP_YMAX)
SET_INPUT_PULLUP(Y2_MAX_PIN);
#else
SET_INPUT(Y2_MAX_PIN);
#endif
#endif
#if HAS_Z_MAX #if HAS_Z_MAX
#if ENABLED(ENDSTOPPULLUP_ZMAX) #if ENABLED(ENDSTOPPULLUP_ZMAX)
SET_INPUT_PULLUP(Z_MAX_PIN); SET_INPUT_PULLUP(Z_MAX_PIN);
@ -185,37 +217,45 @@ void Endstops::report_state() {
void Endstops::M119() { void Endstops::M119() {
SERIAL_PROTOCOLLNPGM(MSG_M119_REPORT); SERIAL_PROTOCOLLNPGM(MSG_M119_REPORT);
#define ES_REPORT(AXIS) do{ \
SERIAL_PROTOCOLPGM(MSG_##AXIS); \
SERIAL_PROTOCOLLN(((READ(AXIS##_PIN)^AXIS##_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN)); \
}while(0)
#if HAS_X_MIN #if HAS_X_MIN
SERIAL_PROTOCOLPGM(MSG_X_MIN); ES_REPORT(X_MIN);
SERIAL_PROTOCOLLN(((READ(X_MIN_PIN)^X_MIN_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN)); #endif
#if HAS_X2_MIN
ES_REPORT(X2_MIN);
#endif #endif
#if HAS_X_MAX #if HAS_X_MAX
SERIAL_PROTOCOLPGM(MSG_X_MAX); ES_REPORT(X_MAX);
SERIAL_PROTOCOLLN(((READ(X_MAX_PIN)^X_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN)); #endif
#if HAS_X2_MAX
ES_REPORT(X2_MAX);
#endif #endif
#if HAS_Y_MIN #if HAS_Y_MIN
SERIAL_PROTOCOLPGM(MSG_Y_MIN); ES_REPORT(Y_MIN);
SERIAL_PROTOCOLLN(((READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN)); #endif
#if HAS_Y2_MIN
ES_REPORT(Y2_MIN);
#endif #endif
#if HAS_Y_MAX #if HAS_Y_MAX
SERIAL_PROTOCOLPGM(MSG_Y_MAX); ES_REPORT(Y_MAX);
SERIAL_PROTOCOLLN(((READ(Y_MAX_PIN)^Y_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN)); #endif
#if HAS_Y2_MAX
ES_REPORT(Y2_MAX);
#endif #endif
#if HAS_Z_MIN #if HAS_Z_MIN
SERIAL_PROTOCOLPGM(MSG_Z_MIN); ES_REPORT(Z_MIN);
SERIAL_PROTOCOLLN(((READ(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
#endif #endif
#if HAS_Z2_MIN #if HAS_Z2_MIN
SERIAL_PROTOCOLPGM(MSG_Z2_MIN); ES_REPORT(Z2_MIN);
SERIAL_PROTOCOLLN(((READ(Z2_MIN_PIN)^Z2_MIN_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
#endif #endif
#if HAS_Z_MAX #if HAS_Z_MAX
SERIAL_PROTOCOLPGM(MSG_Z_MAX); ES_REPORT(Z_MAX);
SERIAL_PROTOCOLLN(((READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
#endif #endif
#if HAS_Z2_MAX #if HAS_Z2_MAX
SERIAL_PROTOCOLPGM(MSG_Z2_MAX); ES_REPORT(Z2_MAX);
SERIAL_PROTOCOLLN(((READ(Z2_MAX_PIN)^Z2_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
#endif #endif
#if ENABLED(Z_MIN_PROBE_ENDSTOP) #if ENABLED(Z_MIN_PROBE_ENDSTOP)
SERIAL_PROTOCOLPGM(MSG_Z_PROBE); SERIAL_PROTOCOLPGM(MSG_Z_PROBE);
@ -227,9 +267,27 @@ void Endstops::M119() {
#endif #endif
} // Endstops::M119 } // Endstops::M119
#if ENABLED(X_DUAL_ENDSTOPS)
void Endstops::test_dual_x_endstops(const EndstopEnum es1, const EndstopEnum es2) {
byte x_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for X, bit 1 for X2
if (x_test && stepper.current_block->steps[X_AXIS] > 0) {
SBI(endstop_hit_bits, X_MIN);
if (!stepper.performing_homing || (x_test == 0x3)) //if not performing home or if both endstops were trigged during homing...
stepper.kill_current_block();
}
}
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
void Endstops::test_dual_y_endstops(const EndstopEnum es1, const EndstopEnum es2) {
byte y_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Y, bit 1 for Y2
if (y_test && stepper.current_block->steps[Y_AXIS] > 0) {
SBI(endstop_hit_bits, Y_MIN);
if (!stepper.performing_homing || (y_test == 0x3)) //if not performing home or if both endstops were trigged during homing...
stepper.kill_current_block();
}
}
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
// Pass the result of the endstop test
void Endstops::test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2) { void Endstops::test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2) {
byte z_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Z, bit 1 for Z2 byte z_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Z, bit 1 for Z2
if (z_test && stepper.current_block->steps[Z_AXIS] > 0) { if (z_test && stepper.current_block->steps[Z_AXIS] > 0) {
@ -238,7 +296,6 @@ void Endstops::M119() {
stepper.kill_current_block(); stepper.kill_current_block();
} }
} }
#endif #endif
// Check endstops - Called from ISR! // Check endstops - Called from ISR!
@ -357,18 +414,36 @@ void Endstops::update() {
/** /**
* Check and update endstops according to conditions * Check and update endstops according to conditions
*/ */
if (X_MOVE_TEST) { if (X_MOVE_TEST) {
if (stepper.motor_direction(X_AXIS_HEAD)) { if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
if (X_MIN_TEST) { // -direction #if HAS_X_MIN
#if HAS_X_MIN #if ENABLED(X_DUAL_ENDSTOPS)
UPDATE_ENDSTOP(X, MIN); UPDATE_ENDSTOP_BIT(X, MIN);
#if HAS_X2_MIN
UPDATE_ENDSTOP_BIT(X2, MIN);
#else
COPY_BIT(current_endstop_bits, X_MIN, X2_MIN);
#endif
test_dual_x_endstops(X_MIN, X2_MIN);
#else
if (X_MIN_TEST) UPDATE_ENDSTOP(X, MIN);
#endif #endif
} #endif
} }
else if (X_MAX_TEST) { // +direction else { // +direction
#if HAS_X_MAX #if HAS_X_MAX
UPDATE_ENDSTOP(X, MAX); #if ENABLED(X_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(X, MAX);
#if HAS_X2_MAX
UPDATE_ENDSTOP_BIT(X2, MAX);
#else
COPY_BIT(current_endstop_bits, X_MAX, X2_MAX);
#endif
test_dual_x_endstops(X_MAX, X2_MAX);
#else
if (X_MIN_TEST) UPDATE_ENDSTOP(X, MAX);
#endif
#endif #endif
} }
} }
@ -376,12 +451,32 @@ void Endstops::update() {
if (Y_MOVE_TEST) { if (Y_MOVE_TEST) {
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
#if HAS_Y_MIN #if HAS_Y_MIN
UPDATE_ENDSTOP(Y, MIN); #if ENABLED(Y_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Y, MIN);
#if HAS_Y2_MIN
UPDATE_ENDSTOP_BIT(Y2, MIN);
#else
COPY_BIT(current_endstop_bits, Y_MIN, Y2_MIN);
#endif
test_dual_y_endstops(Y_MIN, Y2_MIN);
#else
UPDATE_ENDSTOP(Y, MIN);
#endif
#endif #endif
} }
else { // +direction else { // +direction
#if HAS_Y_MAX #if HAS_Y_MAX
UPDATE_ENDSTOP(Y, MAX); #if ENABLED(Y_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Y, MAX);
#if HAS_Y2_MAX
UPDATE_ENDSTOP_BIT(Y2, MAX);
#else
COPY_BIT(current_endstop_bits, Y_MAX, Y2_MAX);
#endif
test_dual_y_endstops(Y_MAX, Y2_MAX);
#else
UPDATE_ENDSTOP(Y, MAX);
#endif
#endif #endif
} }
} }
@ -390,27 +485,21 @@ void Endstops::update() {
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up. if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
#if HAS_Z_MIN #if HAS_Z_MIN
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Z, MIN); UPDATE_ENDSTOP_BIT(Z, MIN);
#if HAS_Z2_MIN #if HAS_Z2_MIN
UPDATE_ENDSTOP_BIT(Z2, MIN); UPDATE_ENDSTOP_BIT(Z2, MIN);
#else #else
COPY_BIT(current_endstop_bits, Z_MIN, Z2_MIN); COPY_BIT(current_endstop_bits, Z_MIN, Z2_MIN);
#endif #endif
test_dual_z_endstops(Z_MIN, Z2_MIN); test_dual_z_endstops(Z_MIN, Z2_MIN);
#else
#else // !Z_DUAL_ENDSTOPS
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
if (z_probe_enabled) UPDATE_ENDSTOP(Z, MIN); if (z_probe_enabled) UPDATE_ENDSTOP(Z, MIN);
#else #else
UPDATE_ENDSTOP(Z, MIN); UPDATE_ENDSTOP(Z, MIN);
#endif #endif
#endif
#endif // !Z_DUAL_ENDSTOPS #endif
#endif // HAS_Z_MIN
// When closing the gap check the enabled probe // When closing the gap check the enabled probe
#if ENABLED(Z_MIN_PROBE_ENDSTOP) #if ENABLED(Z_MIN_PROBE_ENDSTOP)
@ -422,27 +511,21 @@ void Endstops::update() {
} }
else { // Z +direction. Gantry up, bed down. else { // Z +direction. Gantry up, bed down.
#if HAS_Z_MAX #if HAS_Z_MAX
// Check both Z dual endstops // Check both Z dual endstops
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Z, MAX); UPDATE_ENDSTOP_BIT(Z, MAX);
#if HAS_Z2_MAX #if HAS_Z2_MAX
UPDATE_ENDSTOP_BIT(Z2, MAX); UPDATE_ENDSTOP_BIT(Z2, MAX);
#else #else
COPY_BIT(current_endstop_bits, Z_MAX, Z2_MAX); COPY_BIT(current_endstop_bits, Z_MAX, Z2_MAX);
#endif #endif
test_dual_z_endstops(Z_MAX, Z2_MAX); test_dual_z_endstops(Z_MAX, Z2_MAX);
// If this pin is not hijacked for the bed probe // If this pin is not hijacked for the bed probe
// then it belongs to the Z endstop // then it belongs to the Z endstop
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN #elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
UPDATE_ENDSTOP(Z, MAX); UPDATE_ENDSTOP(Z, MAX);
#endif
#endif // !Z_MIN_PROBE_PIN... #endif
#endif // Z_MAX_PIN
} }
} }

@ -36,7 +36,7 @@ class Endstops {
static bool enabled, enabled_globally; static bool enabled, enabled_globally;
static volatile char endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value static volatile char endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
static uint16_t static uint16_t
#else #else
static byte static byte
@ -85,6 +85,12 @@ class Endstops {
private: private:
#if ENABLED(X_DUAL_ENDSTOPS)
static void test_dual_x_endstops(const EndstopEnum es1, const EndstopEnum es2);
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
static void test_dual_y_endstops(const EndstopEnum es1, const EndstopEnum es2);
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
static void test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2); static void test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2);
#endif #endif

@ -93,6 +93,10 @@ enum EndstopEnum {
X_MAX, X_MAX,
Y_MAX, Y_MAX,
Z_MAX, Z_MAX,
X2_MIN,
X2_MAX,
Y2_MIN,
Y2_MAX,
Z2_MIN, Z2_MIN,
Z2_MAX Z2_MAX
}; };

@ -150,8 +150,12 @@
#define MSG_ACTIVE_EXTRUDER "Active Extruder: " #define MSG_ACTIVE_EXTRUDER "Active Extruder: "
#define MSG_X_MIN "x_min: " #define MSG_X_MIN "x_min: "
#define MSG_X_MAX "x_max: " #define MSG_X_MAX "x_max: "
#define MSG_X2_MIN "x2_min: "
#define MSG_X2_MAX "x2_max: "
#define MSG_Y_MIN "y_min: " #define MSG_Y_MIN "y_min: "
#define MSG_Y_MAX "y_max: " #define MSG_Y_MAX "y_max: "
#define MSG_Y2_MIN "y2_min: "
#define MSG_Y2_MAX "y2_max: "
#define MSG_Z_MIN "z_min: " #define MSG_Z_MIN "z_min: "
#define MSG_Z_MAX "z_max: " #define MSG_Z_MAX "z_max: "
#define MSG_Z2_MIN "z2_min: " #define MSG_Z2_MIN "z2_min: "

@ -28,6 +28,13 @@
#define ABC 3 #define ABC 3
#define XYZ 3 #define XYZ 3
#define _XMIN_ 100
#define _YMIN_ 200
#define _ZMIN_ 300
#define _XMAX_ 101
#define _YMAX_ 201
#define _ZMAX_ 301
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
#define _UNUSED __attribute__((unused)) #define _UNUSED __attribute__((unused))
#define _O0 __attribute__((optimize("O0"))) #define _O0 __attribute__((optimize("O0")))

@ -72,7 +72,7 @@ block_t* Stepper::current_block = NULL; // A pointer to the block currently bei
bool Stepper::abort_on_endstop_hit = false; bool Stepper::abort_on_endstop_hit = false;
#endif #endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
bool Stepper::performing_homing = false; bool Stepper::performing_homing = false;
#endif #endif
@ -85,9 +85,14 @@ block_t* Stepper::current_block = NULL; // A pointer to the block currently bei
uint8_t Stepper::last_direction_bits = 0; // The next stepping-bits to be output uint8_t Stepper::last_direction_bits = 0; // The next stepping-bits to be output
uint16_t Stepper::cleaning_buffer_counter = 0; uint16_t Stepper::cleaning_buffer_counter = 0;
#if ENABLED(X_DUAL_ENDSTOPS)
bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
bool Stepper::locked_y_motor = false, Stepper::locked_y2_motor = false;
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
bool Stepper::locked_z_motor = false; bool Stepper::locked_z_motor = false, Stepper::locked_z2_motor = false;
bool Stepper::locked_z2_motor = false;
#endif #endif
long Stepper::counter_X = 0, long Stepper::counter_X = 0,
@ -142,26 +147,54 @@ unsigned short Stepper::OCR1A_nominal;
volatile long Stepper::endstops_trigsteps[XYZ]; volatile long Stepper::endstops_trigsteps[XYZ];
#if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
#define LOCKED_X_MOTOR locked_x_motor
#define LOCKED_Y_MOTOR locked_y_motor
#define LOCKED_Z_MOTOR locked_z_motor
#define LOCKED_X2_MOTOR locked_x2_motor
#define LOCKED_Y2_MOTOR locked_y2_motor
#define LOCKED_Z2_MOTOR locked_z2_motor
#define DUAL_ENDSTOP_APPLY_STEP(AXIS,v) \
if (performing_homing) { \
if (AXIS##_HOME_DIR < 0) { \
if (!(TEST(endstops.old_endstop_bits, AXIS##_MIN) && (count_direction[AXIS##_AXIS] < 0)) && !LOCKED_##AXIS##_MOTOR) AXIS##_STEP_WRITE(v); \
if (!(TEST(endstops.old_endstop_bits, AXIS##2_MIN) && (count_direction[AXIS##_AXIS] < 0)) && !LOCKED_##AXIS##2_MOTOR) AXIS##2_STEP_WRITE(v); \
} \
else { \
if (!(TEST(endstops.old_endstop_bits, AXIS##_MAX) && (count_direction[AXIS##_AXIS] > 0)) && !LOCKED_##AXIS##_MOTOR) AXIS##_STEP_WRITE(v); \
if (!(TEST(endstops.old_endstop_bits, AXIS##2_MAX) && (count_direction[AXIS##_AXIS] > 0)) && !LOCKED_##AXIS##2_MOTOR) AXIS##2_STEP_WRITE(v); \
} \
} \
else { \
AXIS##_STEP_WRITE(v); \
AXIS##2_STEP_WRITE(v); \
}
#endif
#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) != INVERT_X2_VS_X_DIR); }while(0)
#define X_APPLY_STEP(v,Q) do{ X_STEP_WRITE(v); X2_STEP_WRITE(v); }while(0) #if ENABLED(DUAL_X_CARRIAGE)
#elif ENABLED(DUAL_X_CARRIAGE) #define X_APPLY_DIR(v,ALWAYS) \
#define X_APPLY_DIR(v,ALWAYS) \ if (extruder_duplication_enabled || ALWAYS) { \
if (extruder_duplication_enabled || ALWAYS) { \ X_DIR_WRITE(v); \
X_DIR_WRITE(v); \ X2_DIR_WRITE(v); \
X2_DIR_WRITE(v); \ } \
} \ else { \
else { \ if (current_block->active_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \
if (current_block->active_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \ }
} #define X_APPLY_STEP(v,ALWAYS) \
#define X_APPLY_STEP(v,ALWAYS) \ if (extruder_duplication_enabled || ALWAYS) { \
if (extruder_duplication_enabled || ALWAYS) { \ X_STEP_WRITE(v); \
X_STEP_WRITE(v); \ X2_STEP_WRITE(v); \
X2_STEP_WRITE(v); \ } \
} \ else { \
else { \ if (current_block->active_extruder) X2_STEP_WRITE(v); else X_STEP_WRITE(v); \
if (current_block->active_extruder) X2_STEP_WRITE(v); else X_STEP_WRITE(v); \ }
} #elif ENABLED(X_DUAL_ENDSTOPS)
#define X_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(X,v)
#else
#define X_APPLY_STEP(v,Q) do{ X_STEP_WRITE(v); X2_STEP_WRITE(v); }while(0)
#endif
#else #else
#define X_APPLY_DIR(v,Q) X_DIR_WRITE(v) #define X_APPLY_DIR(v,Q) X_DIR_WRITE(v)
#define X_APPLY_STEP(v,Q) X_STEP_WRITE(v) #define X_APPLY_STEP(v,Q) X_STEP_WRITE(v)
@ -169,7 +202,11 @@ volatile long Stepper::endstops_trigsteps[XYZ];
#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) != INVERT_Y2_VS_Y_DIR); }while(0)
#define Y_APPLY_STEP(v,Q) do{ Y_STEP_WRITE(v); Y2_STEP_WRITE(v); }while(0) #if ENABLED(Y_DUAL_ENDSTOPS)
#define Y_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Y,v)
#else
#define Y_APPLY_STEP(v,Q) do{ Y_STEP_WRITE(v); Y2_STEP_WRITE(v); }while(0)
#endif
#else #else
#define Y_APPLY_DIR(v,Q) Y_DIR_WRITE(v) #define Y_APPLY_DIR(v,Q) Y_DIR_WRITE(v)
#define Y_APPLY_STEP(v,Q) Y_STEP_WRITE(v) #define Y_APPLY_STEP(v,Q) Y_STEP_WRITE(v)
@ -178,21 +215,7 @@ volatile long Stepper::endstops_trigsteps[XYZ];
#if ENABLED(Z_DUAL_STEPPER_DRIVERS) #if ENABLED(Z_DUAL_STEPPER_DRIVERS)
#define Z_APPLY_DIR(v,Q) do{ Z_DIR_WRITE(v); Z2_DIR_WRITE(v); }while(0) #define Z_APPLY_DIR(v,Q) do{ Z_DIR_WRITE(v); Z2_DIR_WRITE(v); }while(0)
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
#define Z_APPLY_STEP(v,Q) \ #define Z_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Z,v)
if (performing_homing) { \
if (Z_HOME_DIR < 0) { \
if (!(TEST(endstops.old_endstop_bits, Z_MIN) && (count_direction[Z_AXIS] < 0)) && !locked_z_motor) Z_STEP_WRITE(v); \
if (!(TEST(endstops.old_endstop_bits, Z2_MIN) && (count_direction[Z_AXIS] < 0)) && !locked_z2_motor) Z2_STEP_WRITE(v); \
} \
else { \
if (!(TEST(endstops.old_endstop_bits, Z_MAX) && (count_direction[Z_AXIS] > 0)) && !locked_z_motor) Z_STEP_WRITE(v); \
if (!(TEST(endstops.old_endstop_bits, Z2_MAX) && (count_direction[Z_AXIS] > 0)) && !locked_z2_motor) Z2_STEP_WRITE(v); \
} \
} \
else { \
Z_STEP_WRITE(v); \
Z2_STEP_WRITE(v); \
}
#else #else
#define Z_APPLY_STEP(v,Q) do{ Z_STEP_WRITE(v); Z2_STEP_WRITE(v); }while(0) #define Z_APPLY_STEP(v,Q) do{ Z_STEP_WRITE(v); Z2_STEP_WRITE(v); }while(0)
#endif #endif

@ -87,7 +87,7 @@ class Stepper {
static bool abort_on_endstop_hit; static bool abort_on_endstop_hit;
#endif #endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
static bool performing_homing; static bool performing_homing;
#endif #endif
@ -103,6 +103,12 @@ class Stepper {
static uint8_t last_direction_bits; // The next stepping-bits to be output static uint8_t last_direction_bits; // The next stepping-bits to be output
static uint16_t cleaning_buffer_counter; static uint16_t cleaning_buffer_counter;
#if ENABLED(X_DUAL_ENDSTOPS)
static bool locked_x_motor, locked_x2_motor;
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
static bool locked_y_motor, locked_y2_motor;
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
static bool locked_z_motor, locked_z2_motor; static bool locked_z_motor, locked_z2_motor;
#endif #endif
@ -250,8 +256,18 @@ class Stepper {
static void microstep_readings(); static void microstep_readings();
#endif #endif
#if ENABLED(X_DUAL_ENDSTOPS)
static FORCE_INLINE void set_homing_flag_x(const bool state) { performing_homing = state; }
static FORCE_INLINE void set_x_lock(const bool state) { locked_x_motor = state; }
static FORCE_INLINE void set_x2_lock(const bool state) { locked_x2_motor = state; }
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
static FORCE_INLINE void set_homing_flag_y(const bool state) { performing_homing = state; }
static FORCE_INLINE void set_y_lock(const bool state) { locked_y_motor = state; }
static FORCE_INLINE void set_y2_lock(const bool state) { locked_y2_motor = state; }
#endif
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
static FORCE_INLINE void set_homing_flag(const bool state) { performing_homing = state; } static FORCE_INLINE void set_homing_flag_z(const bool state) { performing_homing = state; }
static FORCE_INLINE void set_z_lock(const bool state) { locked_z_motor = state; } static FORCE_INLINE void set_z_lock(const bool state) { locked_z_motor = state; }
static FORCE_INLINE void set_z2_lock(const bool state) { locked_z2_motor = state; } static FORCE_INLINE void set_z2_lock(const bool state) { locked_z2_motor = state; }
#endif #endif

Loading…
Cancel
Save