diff --git a/Marlin/Conditionals.h b/Marlin/Conditionals.h index c7e2084724..e441b957b4 100644 --- a/Marlin/Conditionals.h +++ b/Marlin/Conditionals.h @@ -189,6 +189,9 @@ #define ENDSTOPPULLUP_YMIN #define ENDSTOPPULLUP_ZMIN #endif + #ifndef DISABLE_Z_PROBE_ENDSTOP + #define ENDSTOPPULLUP_ZPROBE + #endif #endif /** diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index a984923ea2..f23b1e45b2 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -319,6 +319,7 @@ your extruder heater takes 2 minutes to hit the target on heating. // #define ENDSTOPPULLUP_XMIN // #define ENDSTOPPULLUP_YMIN // #define ENDSTOPPULLUP_ZMIN + // #define ENDSTOPPULLUP_ZPROBE #endif // Mechanical endstop with COM to ground and NC to Signal uses "false" here (most common setup). @@ -328,8 +329,14 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop. const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop. const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop. +const bool Z_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop. //#define DISABLE_MAX_ENDSTOPS //#define DISABLE_MIN_ENDSTOPS +// If you want to enable the Z Probe pin, but disable its use, uncomment the line below. +// This only affects a Z Probe Endstop if you have separate Z min endstop as well and have +// activated Z_PROBE_ENDSTOP below. If you are using the Z Min endstop on your Z Probe, +// this has no effect. +//#define DISABLE_Z_PROBE_ENDSTOP // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 @@ -492,6 +499,20 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o #endif +// Support for a dedicated Z PROBE endstop separate from the Z MIN endstop. +// If you would like to use both a Z PROBE and a Z MIN endstop together or just a Z PROBE with a custom pin, uncomment #define Z_PROBE_ENDSTOP and read the instructions below. +// If you want to still use the Z min endstop for homing, disable Z_SAFE_HOMING above. Eg; to park the head outside the bed area when homing with G28. +// WARNING: The Z MIN endstop will need to set properly as it would without a Z PROBE to prevent head crashes and premature stopping during a print. +// To use a separte Z PROBE endstop, you must have a Z_PROBE_PIN defined in the pins.h file for your control board. +// If you are using a servo based Z PROBE, you will need to enable NUM_SERVOS, SERVO_ENDSTOPS and SERVO_ENDSTOPS_ANGLES in the R/C Servo below. +// RAMPS 1.3/1.4 boards may be able to use the 5V, Ground and the D32 pin in the Aux 4 section of the RAMPS board. Use 5V for powered sensors, otherwise connect to ground and D32 +// for normally closed configuration and 5V and D32 for normally open configurations. Normally closed configuration is advised and assumed. +// The D32 pin in Aux 4 on RAMPS maps to the Arduino D32 pin. Z_PROBE_PIN is setting the pin to use on the Arduino. Since the D32 pin on the RAMPS maps to D32 on Arduino, this works. +// D32 is currently selected in the RAMPS 1.3/1.4 pin file. All other boards will need changes to the respective pins_XXXXX.h file. +// WARNING: Setting the wrong pin may have unexpected and potentially disastrous outcomes. Use with caution and do your homework. + +// #define Z_PROBE_ENDSTOP + #endif // ENABLE_AUTO_BED_LEVELING diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 3eda508593..2f5b6058ac 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -1244,9 +1244,14 @@ inline void sync_plan_position() { prepare_move_raw(); st_synchronize(); - + + #if defined(Z_PROBE_ENDSTOP) + bool z_probe_endstop = (READ(Z_PROBE_PIN) != Z_PROBE_ENDSTOP_INVERTING); + if (z_probe_endstop) { + #else bool z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING); if (z_min_endstop) { + #endif if (!Stopped) { SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Z-Probe failed to engage!"); @@ -1313,9 +1318,14 @@ inline void sync_plan_position() { prepare_move_raw(); st_synchronize(); - + + #if defined(Z_PROBE_ENDSTOP) + bool z_probe_endstop = (READ(Z_PROBE_PIN) != Z_PROBE_ENDSTOP_INVERTING); + if (!z_probe_endstop) { + #else bool z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING); if (!z_min_endstop) { + #endif if (!Stopped) { SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Z-Probe failed to retract!"); @@ -2793,11 +2803,17 @@ inline void gcode_M42() { } // code_seen('S') } - #if defined(ENABLE_AUTO_BED_LEVELING) && defined(Z_PROBE_REPEATABILITY_TEST) - #if Z_MIN_PIN == -1 - #error "You must have a Z_MIN endstop in order to enable calculation of Z-Probe repeatability." + // This is redudant since the SanityCheck.h already checks for a valid Z_PROBE_PIN, but here for clarity. + #if defined (Z_PROBE_ENDSTOP) + #if (! defined (Z_PROBE_PIN) || Z_PROBE_PIN == -1) + #error "You must have a Z_PROBE_PIN defined in order to enable calculation of Z-Probe repeatability." + #endif + #else + #if (Z_MIN_PIN == -1) + #error "You must have a Z_MIN_PIN defined in order to enable calculation of Z-Probe repeatability." + #endif #endif /** @@ -3526,7 +3542,10 @@ inline void gcode_M119() { SERIAL_PROTOCOLPGM(MSG_Z2_MAX); SERIAL_PROTOCOLLN(((READ(Z2_MAX_PIN)^Z2_MAX_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); #endif - + #if defined(Z_PROBE_PIN) && Z_PROBE_PIN > -1 + SERIAL_PROTOCOLPGM(MSG_Z_PROBE); + SERIAL_PROTOCOLLN(((READ(Z_PROBE_PIN)^Z_PROBE_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif } /** diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index 8c05f83bc9..8ea9b2e3d0 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -93,13 +93,39 @@ * Require a Z Min pin */ #if Z_MIN_PIN == -1 - #ifdef Z_PROBE_REPEATABILITY_TEST - #error You must have a Z_MIN endstop to enable Z_PROBE_REPEATABILITY_TEST. - #else - #error ENABLE_AUTO_BED_LEVELING requires a Z_MIN endstop. Z_MIN_PIN must point to a valid hardware pin. + #if Z_PROBE_PIN == -1 || (! defined (Z_PROBE_ENDSTOP) || defined (DISABLE_Z_PROBE_ENDSTOP)) // It's possible for someone to set a pin for the Z Probe, but not enable it. + #ifdef Z_PROBE_REPEATABILITY_TEST + #error You must have a Z_MIN or Z_PROBE endstop to enable Z_PROBE_REPEATABILITY_TEST. + #else + #error ENABLE_AUTO_BED_LEVELING requires a Z_MIN or Z_PROBE endstop. Z_MIN_PIN or Z_PROBE_PIN must point to a valid hardware pin. + #endif #endif #endif + /** + * Require a Z Probe Pin if Z_PROBE_ENDSTOP is enabled. + */ + #if defined(Z_PROBE_ENDSTOP) + #ifndef Z_PROBE_PIN + #error You must have a Z_PROBE_PIN defined in your pins_XXXX.h file if you enable Z_PROBE_ENDSTOP + #endif + #if Z_PROBE_PIN == -1 + #error You must set Z_PROBE_PIN to a valid pin if you enable Z_PROBE_ENDSTOP + #endif +// Forcing Servo definitions can break some hall effect sensor setups. Leaving these here for further comment. +// #ifndef NUM_SERVOS +// #error You must have NUM_SERVOS defined and there must be at least 1 configured to use Z_PROBE_ENDSTOP +// #endif +// #if defined(NUM_SERVOS) && NUM_SERVOS < 1 +// #error You must have at least 1 servo defined for NUM_SERVOS to use Z_PROBE_ENDSTOP +// #endif +// #ifndef SERVO_ENDSTOPS +// #error You must have SERVO_ENDSTOPS defined and have the Z index set to at least 0 or above to use Z_PROBE_ENDSTOP +// #endif +// #ifndef SERVO_ENDSTOP_ANGLES +// #error You must have SERVO_ENDSTOP_ANGLES defined for Z Extend and Retract to use Z_PROBE_AND_ENSTOP +// #endif + #endif /** * Check if Probe_Offset * Grid Points is greater than Probing Range */ diff --git a/Marlin/language.h b/Marlin/language.h index 5b7c22f45b..48daddb585 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -161,6 +161,7 @@ #define MSG_Z_MIN "z_min: " #define MSG_Z_MAX "z_max: " #define MSG_Z2_MAX "z2_max: " +#define MSG_Z_PROBE "z_probe: " #define MSG_M119_REPORT "Reporting endstop status" #define MSG_ENDSTOP_HIT "TRIGGERED" #define MSG_ENDSTOP_OPEN "open" diff --git a/Marlin/pins.h b/Marlin/pins.h index 3c75a73bad..0d63298869 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -187,6 +187,10 @@ #define Z_MIN_PIN -1 #endif +#if defined (DISABLE_Z_PROBE_ENDSTOP) || ! defined (Z_PROBE_ENDSTOP) // Allow code to compile regardless of Z_PROBE_ENDSTOP setting. + #define Z_PROBE_PIN -1 +#endif + #ifdef DISABLE_XMAX_ENDSTOP #undef X_MAX_PIN #define X_MAX_PIN -1 @@ -216,7 +220,7 @@ #define Z_MIN_PIN -1 #endif -#define SENSITIVE_PINS { 0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, PS_ON_PIN, \ +#define SENSITIVE_PINS { 0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, Z_PROBE_PIN, PS_ON_PIN, \ HEATER_BED_PIN, FAN_PIN, \ _E0_PINS _E1_PINS _E2_PINS _E3_PINS \ analogInputToDigitalPin(TEMP_BED_PIN) \ diff --git a/Marlin/pins_RAMPS_13.h b/Marlin/pins_RAMPS_13.h index 71287f6832..11ecddeda2 100644 --- a/Marlin/pins_RAMPS_13.h +++ b/Marlin/pins_RAMPS_13.h @@ -34,6 +34,7 @@ #define Z_ENABLE_PIN 62 #define Z_MIN_PIN 18 #define Z_MAX_PIN 19 +#define Z_PROBE_PIN -1 #define Y2_STEP_PIN 36 #define Y2_DIR_PIN 34 @@ -61,6 +62,11 @@ #define FILWIDTH_PIN 5 #endif +#if defined(Z_PROBE_ENDSTOP) + // Define a pin to use as the signal pin on Arduino for the Z_PROBE endstop. + #define Z_PROBE_PIN 32 +#endif + #if defined(FILAMENT_RUNOUT_SENSOR) // define digital pin 4 for the filament runout sensor. Use the RAMPS 1.4 digital input 4 on the servos connector #define FILRUNOUT_PIN 4 diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index a7dba4659e..5c01e2f154 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -76,6 +76,7 @@ volatile long endstops_stepsTotal, endstops_stepsDone; static volatile bool endstop_x_hit = false; static volatile bool endstop_y_hit = false; static volatile bool endstop_z_hit = false; +static volatile bool endstop_z_probe_hit = false; // Leaving this in even if Z_PROBE_ENDSTOP isn't defined, keeps code below cleaner. #ifdef it and usage below to save space. #ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED bool abort_on_endstop_hit = false; @@ -112,6 +113,10 @@ static volatile bool endstop_z_hit = false; #endif #endif +#ifdef Z_PROBE_ENDSTOP // No need to check for valid pin, SanityCheck.h already does this. +static bool old_z_probe_endstop = false; +#endif + static bool check_endstops = true; volatile long count_position[NUM_AXIS] = { 0 }; @@ -254,11 +259,11 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1 }; #define DISABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 &= ~BIT(OCIE1A) void endstops_hit_on_purpose() { - endstop_x_hit = endstop_y_hit = endstop_z_hit = false; + endstop_x_hit = endstop_y_hit = endstop_z_hit = endstop_z_probe_hit = false; // #ifdef endstop_z_probe_hit = to save space if needed. } void checkHitEndstops() { - if (endstop_x_hit || endstop_y_hit || endstop_z_hit) { + if (endstop_x_hit || endstop_y_hit || endstop_z_hit || endstop_z_probe_hit) { // #ifdef || endstop_z_probe_hit to save space if needed. SERIAL_ECHO_START; SERIAL_ECHOPGM(MSG_ENDSTOPS_HIT); if (endstop_x_hit) { @@ -273,6 +278,12 @@ void checkHitEndstops() { SERIAL_ECHOPAIR(" Z:", (float)endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]); LCD_MESSAGEPGM(MSG_ENDSTOPS_HIT "Z"); } + #ifdef Z_PROBE_ENDSTOP + if (endstop_z_probe_hit) { + SERIAL_ECHOPAIR(" Z_PROBE:", (float)endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]); + LCD_MESSAGEPGM(MSG_ENDSTOPS_HIT "ZP"); + } + #endif SERIAL_EOL; endstops_hit_on_purpose(); @@ -551,6 +562,19 @@ ISR(TIMER1_COMPA_vect) { #endif // Z_MIN_PIN + #ifdef Z_PROBE_ENDSTOP + UPDATE_ENDSTOP(z, Z, probe, PROBE); + z_probe_endstop=(READ(Z_PROBE_PIN) != Z_PROBE_ENDSTOP_INVERTING); + if(z_probe_endstop && old_z_probe_endstop) + { + endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; + endstop_z_probe_hit=true; + +// if (z_probe_endstop && old_z_probe_endstop) SERIAL_ECHOLN("z_probe_endstop = true"); + } + old_z_probe_endstop = z_probe_endstop; + #endif + } // check_endstops } @@ -596,6 +620,18 @@ ISR(TIMER1_COMPA_vect) { #endif // !Z_DUAL_ENDSTOPS #endif // Z_MAX_PIN + + #ifdef Z_PROBE_ENDSTOP + UPDATE_ENDSTOP(z, Z, probe, PROBE); + z_probe_endstop=(READ(Z_PROBE_PIN) != Z_PROBE_ENDSTOP_INVERTING); + if(z_probe_endstop && old_z_probe_endstop) + { + endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; + endstop_z_probe_hit=true; +// if (z_probe_endstop && old_z_probe_endstop) SERIAL_ECHOLN("z_probe_endstop = true"); + } + old_z_probe_endstop = z_probe_endstop; + #endif } // check_endstops @@ -679,7 +715,7 @@ ISR(TIMER1_COMPA_vect) { step_events_completed++; if (step_events_completed >= current_block->step_event_count) break; } - // Calculare new timer value + // Calculate new timer value unsigned short timer; unsigned short step_rate; if (step_events_completed <= (unsigned long int)current_block->accelerate_until) { @@ -962,6 +998,13 @@ void st_init() { #endif #endif +#if (defined(Z_PROBE_PIN) && Z_PROBE_PIN >= 0) && defined(Z_PROBE_ENDSTOP) // Check for Z_PROBE_ENDSTOP so we don't pull a pin high unless it's to be used. + SET_INPUT(Z_PROBE_PIN); + #ifdef ENDSTOPPULLUP_ZPROBE + WRITE(Z_PROBE_PIN,HIGH); + #endif +#endif + #define AXIS_INIT(axis, AXIS, PIN) \ AXIS ##_STEP_INIT; \ AXIS ##_STEP_WRITE(INVERT_## PIN ##_STEP_PIN); \