diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ae167f9c058a..1b09c70554f7 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -121,8 +121,8 @@ // @section homing -#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing - +#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops and probes will only be used until homing and for probing. +#define FREE_ENDSTOPS // Free the hardware endstops and probes after homing, probing and during initialisation my ?_HOME_BUMP_MM. // @section extras //#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats. diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 1ccbed879bb9..3dd78f76fc95 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -246,6 +246,7 @@ float current_position[NUM_AXIS] = { 0.0 }; static float destination[NUM_AXIS] = { 0.0 }; bool axis_known_position[3] = { false }; bool axis_homed[3] = { false }; +static int8_t h_endstops_set = 0; static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0; @@ -466,6 +467,10 @@ extern "C" { } #endif //!SDSUPPORT +#if ENABLED(FREE_ENDSTOPS) + void free_endstops(); +#endif + /** * Inject the next command from the command queue, when possible * Return false only if no command was pending @@ -727,6 +732,10 @@ void setup() { pinMode(STAT_LED_BLUE, OUTPUT); digitalWrite(STAT_LED_BLUE, LOW); // turn it off #endif + + #if ENABLED(FREE_ENDSTOPS) + free_endstops(); + #endif } /** @@ -1198,9 +1207,110 @@ static void setup_for_endstop_move() { SERIAL_ECHOLNPGM("setup_for_endstop_move > enable_endstops(true)"); } #endif - enable_endstops(true); + //enable_endstops(true); } +static void clean_up_after_endstop_move() { + if (h_endstops_set == 0) { + #if ENABLED(ENDSTOPS_ONLY_FOR_HOMING) + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (marlin_debug_flags & DEBUG_LEVELING) { + SERIAL_ECHOLNPGM("ENDSTOPS_ONLY_FOR_HOMING enable_endstops(false)"); + } + #endif + enable_endstops(false); + #else + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (marlin_debug_flags & DEBUG_LEVELING) { + SERIAL_ECHOLNPGM("ENDSTOPS_ONLY_FOR_HOMING enable_endstops(true)"); + } + #endif + enable_endstops(true); + #endif + } + else if (h_endstops_set == 1) { + enable_endstops(true); + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (marlin_debug_flags & DEBUG_LEVELING) { + SERIAL_ECHOLNPGM("M120 enable_endstops(true)"); + } + #endif + } + else { + enable_endstops(false); + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (marlin_debug_flags & DEBUG_LEVELING) { + SERIAL_ECHOLNPGM("M121 enable_endstops(false)"); + } + #endif + } + endstops_hit_on_purpose(); // clear endstop hit flags + feedrate = saved_feedrate; + feedrate_multiplier = saved_feedrate_multiplier; + refresh_cmd_timeout(); +} + +#if ENABLED(FREE_ENDSTOPS) + void free_endstop(bool estop, AxisEnum axis, float way) { + if (estop) { + set_homing_bump_feedrate(axis); + destination[axis] = current_position[axis] + way; + line_to_destination(); + st_synchronize(); + }; + } + + void free_endstops() { + #if (HAS_X_MIN && HAS_X_MAX) + if ((READ(X_MIN_PIN)^X_MIN_ENDSTOP_INVERTING) && (READ(X_MAX_PIN)^X_MAX_ENDSTOP_INVERTING)) { + SERIAL_ERROR_START; + SERIAL_ERRORPGM("Min & Max e-stop at same time at:"); + SERIAL_ERRORLNPGM("X"); + kill(PSTR("E-stop Min&Max")); + } + #endif + #if HAS_X_MIN + free_endstop(READ(X_MIN_PIN)^X_MIN_ENDSTOP_INVERTING, X_AXIS, X_HOME_BUMP_MM); + #endif + #if HAS_X_MAX + free_endstop(READ(X_MAX_PIN)^X_MAX_ENDSTOP_INVERTING, X_AXIS, -X_HOME_BUMP_MM); + #endif + + #if (HAS_Y_MIN && HAS_Y_MAX) + if ((READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_INVERTING) && (READ(Y_MAX_PIN)^Y_MAX_ENDSTOP_INVERTING)) { + SERIAL_ERROR_START; + SERIAL_ERRORPGM("Min & Max e-stop at same time at:"); + SERIAL_ERRORLNPGM("Y"); + kill(PSTR("E-stop Min&Max")); + } + #endif + #if HAS_Y_MIN + free_endstop(READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_INVERTING, Y_AXIS, Y_HOME_BUMP_MM); + #endif + #if HAS_Y_MAX + free_endstop(READ(Y_MAX_PIN)^Y_MAX_ENDSTOP_INVERTING, Y_AXIS, -Y_HOME_BUMP_MM); + #endif + + #if (HAS_Z_MIN && HAS_Z_MAX) + if ((READ(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING) && (READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING)) { + SERIAL_ERROR_START; + SERIAL_ERRORPGM("Min & Max e-stop at same time at:"); + SERIAL_ERRORLNPGM("Z"); + kill(PSTR("E-stop Min&Max")); + } + #endif + #if HAS_Z_MIN + free_endstop(READ(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING, Z_AXIS, Z_HOME_BUMP_MM); + #endif + #if HAS_Z_MAX + free_endstop(READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING, Z_AXIS, -Z_HOME_BUMP_MM); + #endif + + endstops_hit_on_purpose(); + feedrate = 1500.0; + } +#endif + #if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(DELTA) @@ -1290,76 +1400,84 @@ static void setup_for_endstop_move() { refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out and EXTRUDER_RUNOUT_PREVENT from extruding - #if ENABLED(DELTA) + st_synchronize(); + set_destination_to_current(); + + feedrate = homing_feedrate[Z_AXIS]; + // move down until you find the bed + float zPosition = -10; + enable_endstops(true); + #if ENABLED(DELTA) float start_z = current_position[Z_AXIS]; long start_steps = st_get_position(Z_AXIS); - - #if ENABLED(DEBUG_LEVELING_FEATURE) - if (marlin_debug_flags & DEBUG_LEVELING) { - SERIAL_ECHOLNPGM("run_z_probe (DELTA) 1"); - } - #endif - - // move down slowly until you find the bed - feedrate = homing_feedrate[Z_AXIS] / 4; - destination[Z_AXIS] = -10; + destination[Z_AXIS] = zPosition; prepare_move_raw(); // this will also set_current_to_destination st_synchronize(); - endstops_hit_on_purpose(); // clear endstop hit flags - - // we have to let the planner know where we are right now as it is not where we said to go. - long stop_steps = st_get_position(Z_AXIS); - float mm = start_z - float(start_steps - stop_steps) / axis_steps_per_unit[Z_AXIS]; - current_position[Z_AXIS] = mm; - - #if ENABLED(DEBUG_LEVELING_FEATURE) - if (marlin_debug_flags & DEBUG_LEVELING) { - print_xyz("run_z_probe (DELTA) 2 > current_position", current_position); - } - #endif - + // Tell the planner where we ended up - Get this from the stepper handler + current_position[Z_AXIS] = start_z - (start_steps - st_get_position(Z_AXIS)) / axis_steps_per_unit[Z_AXIS]; sync_plan_position_delta(); - - #else // !DELTA - + #else plan_bed_level_matrix.set_to_identity(); - feedrate = homing_feedrate[Z_AXIS]; - - // Move down until the Z probe (or endstop?) is triggered - float zPosition = -(Z_MAX_LENGTH + 10); line_to_z(zPosition); st_synchronize(); - // Tell the planner where we ended up - Get this from the stepper handler zPosition = st_get_axis_position_mm(Z_AXIS); plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS]); + #endif + enable_endstops(false); + endstops_hit_on_purpose(); // clear endstop hit flags - // move up the retract distance - zPosition += home_bump_mm(Z_AXIS); + // move up the retract distance + zPosition += home_bump_mm(Z_AXIS); + #if ENABLED(DELTA) + destination[Z_AXIS] = zPosition; + prepare_move_raw(); // this will also set_current_to_destination + #else line_to_z(zPosition); - st_synchronize(); - endstops_hit_on_purpose(); // clear endstop hit flags - - // move back down slowly to find bed - set_homing_bump_feedrate(Z_AXIS); + #endif + st_synchronize(); + endstops_hit_on_purpose(); // clear endstop hit flags - zPosition -= home_bump_mm(Z_AXIS) * 2; + // move back down slowly to find bed + set_homing_bump_feedrate(Z_AXIS); + zPosition -= home_bump_mm(Z_AXIS) * 2; + enable_endstops(true); + #if ENABLED(DELTA) + start_z = current_position[Z_AXIS]; + start_steps = st_get_position(Z_AXIS); + destination[Z_AXIS] = zPosition; + prepare_move_raw(); // this will also set_current_to_destination + st_synchronize(); + // Tell the planner where we ended up - Get this from the stepper handler + current_position[Z_AXIS] = start_z - (start_steps - st_get_position(Z_AXIS)) / axis_steps_per_unit[Z_AXIS]; + sync_plan_position_delta(); + #else line_to_z(zPosition); st_synchronize(); - endstops_hit_on_purpose(); // clear endstop hit flags - + // Tell the planner where we ended up - Get this from the stepper handler + zPosition = st_get_position_mm(Z_AXIS); + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS]); // Get the current stepper position after bumping an endstop current_position[Z_AXIS] = st_get_axis_position_mm(Z_AXIS); sync_plan_position(); + #endif + enable_endstops(false); + endstops_hit_on_purpose(); // clear endstop hit flags - #if ENABLED(DEBUG_LEVELING_FEATURE) - if (marlin_debug_flags & DEBUG_LEVELING) { - print_xyz("run_z_probe > current_position", current_position); - } - #endif + #if ENABLED(FREE_ENDSTOPS) + // Move away from the endstop by the axis HOME_BUMP_MM + destination[axis] = -home_bump_mm(axis) * axis_home_dir; + line_to_destination(); + st_synchronize(); + enable_endstops(true); + #endif - #endif // !DELTA + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (marlin_debug_flags & DEBUG_LEVELING) { + print_xyz("run_z_probe > current_position", current_position); + } + #endif } /** @@ -1410,20 +1528,6 @@ static void setup_for_endstop_move() { inline void do_blocking_move_to_z(float z) { do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], z); } inline void raise_z_after_probing() { do_blocking_move_to_z(current_position[Z_AXIS] + Z_RAISE_AFTER_PROBING); } - static void clean_up_after_endstop_move() { - #if ENABLED(ENDSTOPS_ONLY_FOR_HOMING) - #if ENABLED(DEBUG_LEVELING_FEATURE) - if (marlin_debug_flags & DEBUG_LEVELING) { - SERIAL_ECHOLNPGM("clean_up_after_endstop_move > ENDSTOPS_ONLY_FOR_HOMING > enable_endstops(false)"); - } - #endif - enable_endstops(false); - #endif - feedrate = saved_feedrate; - feedrate_multiplier = saved_feedrate_multiplier; - refresh_cmd_timeout(); - } - static void deploy_z_probe() { #if ENABLED(DEBUG_LEVELING_FEATURE) @@ -1911,6 +2015,15 @@ static void homeaxis(AxisEnum axis) { destination[axis] = 2 * home_bump_mm(axis) * axis_home_dir; line_to_destination(); st_synchronize(); + + #if ENABLED(FREE_ENDSTOPS) + enable_endstops(false); // Disable endstops while moving away + // Move away from the endstop by the axis HOME_BUMP_MM + destination[axis] = -home_bump_mm(axis) * axis_home_dir; + line_to_destination(); + st_synchronize(); + enable_endstops(true); + #endif #if ENABLED(DEBUG_LEVELING_FEATURE) if (marlin_debug_flags & DEBUG_LEVELING) { @@ -2267,6 +2380,7 @@ inline void gcode_G28() { #endif setup_for_endstop_move(); + enable_endstops(true); set_destination_to_current(); // Directly after a reset this is all 0. Later we get a hint if we have to raise z or not. @@ -2552,15 +2666,6 @@ inline void gcode_G28() { sync_plan_position_delta(); #endif - #if ENABLED(ENDSTOPS_ONLY_FOR_HOMING) - #if ENABLED(DEBUG_LEVELING_FEATURE) - if (marlin_debug_flags & DEBUG_LEVELING) { - SERIAL_ECHOLNPGM("ENDSTOPS_ONLY_FOR_HOMING enable_endstops(false)"); - } - #endif - enable_endstops(false); - #endif - // For manual leveling move back to 0,0 #if ENABLED(MESH_BED_LEVELING) if (mbl_was_active) { @@ -2581,10 +2686,7 @@ inline void gcode_G28() { } #endif - feedrate = saved_feedrate; - feedrate_multiplier = saved_feedrate_multiplier; - refresh_cmd_timeout(); - endstops_hit_on_purpose(); // clear endstop hit flags + clean_up_after_endstop_move(); #if ENABLED(DEBUG_LEVELING_FEATURE) if (marlin_debug_flags & DEBUG_LEVELING) { @@ -3228,6 +3330,9 @@ inline void gcode_G28() { * G30: Do a single Z probe at the current XY */ inline void gcode_G30() { + setup_for_endstop_move(); + feedrate = homing_feedrate[Z_AXIS]; + #if HAS_SERVO_ENDSTOPS raise_z_for_servo(); #endif @@ -3235,10 +3340,6 @@ inline void gcode_G28() { st_synchronize(); // TODO: clear the leveling matrix or the planner will be set incorrectly - setup_for_endstop_move(); - - feedrate = homing_feedrate[Z_AXIS]; - run_z_probe(); SERIAL_PROTOCOLPGM("Bed X: "); SERIAL_PROTOCOL(current_position[X_AXIS] + 0.0001); @@ -3248,12 +3349,14 @@ inline void gcode_G28() { SERIAL_PROTOCOL(current_position[Z_AXIS] + 0.0001); SERIAL_EOL; - clean_up_after_endstop_move(); - + feedrate = homing_feedrate[Z_AXIS]; + #if HAS_SERVO_ENDSTOPS raise_z_for_servo(); #endif stow_z_probe(false); // Retract Z Servo endstop if available + + clean_up_after_endstop_move(); } #endif //!Z_PROBE_SLED @@ -3627,6 +3730,7 @@ inline void gcode_M42() { st_synchronize(); plan_bed_level_matrix.set_to_identity(); + setup_for_endstop_move(); plan_buffer_line(X_current, Y_current, Z_start_location, E_current, homing_feedrate[Z_AXIS] / 60, active_extruder); st_synchronize(); @@ -3656,7 +3760,6 @@ inline void gcode_M42() { deploy_z_probe(); - setup_for_endstop_move(); run_z_probe(); Z_current = current_position[Z_AXIS] = st_get_axis_position_mm(Z_AXIS); @@ -3717,7 +3820,6 @@ inline void gcode_M42() { delay(1000); } - setup_for_endstop_move(); run_z_probe(); sample_set[n] = current_position[Z_AXIS]; @@ -4391,12 +4493,12 @@ inline void gcode_M119() { /** * M120: Enable endstops */ -inline void gcode_M120() { enable_endstops(true); } +inline void gcode_M120() { enable_endstops(true); h_endstops_set = 1;} /** * M121: Disable endstops */ -inline void gcode_M121() { enable_endstops(false); } +inline void gcode_M121() { enable_endstops(false); h_endstops_set = -1;} #if ENABLED(BLINKM)