|
|
|
@ -74,17 +74,6 @@
|
|
|
|
|
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
#include "../core/debug_out.h"
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* axis_homed
|
|
|
|
|
* Flags that each linear axis was homed.
|
|
|
|
|
* XYZ on cartesian, ABC on delta, ABZ on SCARA.
|
|
|
|
|
*
|
|
|
|
|
* axis_trusted
|
|
|
|
|
* Flags that the position is trusted in each linear axis. Set when homed.
|
|
|
|
|
* Cleared whenever a stepper powers off, potentially losing its position.
|
|
|
|
|
*/
|
|
|
|
|
uint8_t axis_homed, axis_trusted; // = 0
|
|
|
|
|
|
|
|
|
|
// Relative Mode. Enable with G91, disable with G90.
|
|
|
|
|
bool relative_mode; // = false;
|
|
|
|
|
|
|
|
|
@ -1122,16 +1111,20 @@ void prepare_line_to_destination() {
|
|
|
|
|
current_position = destination;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t axes_should_home(uint8_t axis_bits/*=0x07*/) {
|
|
|
|
|
#if HAS_ENDSTOPS
|
|
|
|
|
|
|
|
|
|
uint8_t axis_homed, axis_trusted; // = 0
|
|
|
|
|
|
|
|
|
|
uint8_t axes_should_home(uint8_t axis_bits/*=0x07*/) {
|
|
|
|
|
#define SHOULD_HOME(A) TERN(HOME_AFTER_DEACTIVATE, axis_is_trusted, axis_was_homed)(A)
|
|
|
|
|
// Clear test bits that are trusted
|
|
|
|
|
if (TEST(axis_bits, X_AXIS) && SHOULD_HOME(X_AXIS)) CBI(axis_bits, X_AXIS);
|
|
|
|
|
if (TEST(axis_bits, Y_AXIS) && SHOULD_HOME(Y_AXIS)) CBI(axis_bits, Y_AXIS);
|
|
|
|
|
if (TEST(axis_bits, Z_AXIS) && SHOULD_HOME(Z_AXIS)) CBI(axis_bits, Z_AXIS);
|
|
|
|
|
return axis_bits;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool homing_needed_error(uint8_t axis_bits/*=0x07*/) {
|
|
|
|
|
bool homing_needed_error(uint8_t axis_bits/*=0x07*/) {
|
|
|
|
|
if ((axis_bits = axes_should_home(axis_bits))) {
|
|
|
|
|
PGM_P home_first = GET_TEXT(MSG_HOME_FIRST);
|
|
|
|
|
char msg[strlen_P(home_first)+1];
|
|
|
|
@ -1146,12 +1139,12 @@ bool homing_needed_error(uint8_t axis_bits/*=0x07*/) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Homing bump feedrate (mm/s)
|
|
|
|
|
*/
|
|
|
|
|
feedRate_t get_homing_bump_feedrate(const AxisEnum axis) {
|
|
|
|
|
feedRate_t get_homing_bump_feedrate(const AxisEnum axis) {
|
|
|
|
|
#if HOMING_Z_WITH_PROBE
|
|
|
|
|
if (axis == Z_AXIS) return MMM_TO_MMS(Z_PROBE_SPEED_SLOW);
|
|
|
|
|
#endif
|
|
|
|
@ -1162,9 +1155,9 @@ feedRate_t get_homing_bump_feedrate(const AxisEnum axis) {
|
|
|
|
|
SERIAL_ECHO_MSG("Warning: Homing Bump Divisor < 1");
|
|
|
|
|
}
|
|
|
|
|
return homing_feedrate(axis) / float(hbd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if ENABLED(SENSORLESS_HOMING)
|
|
|
|
|
#if ENABLED(SENSORLESS_HOMING)
|
|
|
|
|
/**
|
|
|
|
|
* Set sensorless homing if the axis has it, accounting for Core Kinematics.
|
|
|
|
|
*/
|
|
|
|
@ -1294,12 +1287,12 @@ feedRate_t get_homing_bump_feedrate(const AxisEnum axis) {
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // SENSORLESS_HOMING
|
|
|
|
|
#endif // SENSORLESS_HOMING
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Home an individual linear axis
|
|
|
|
|
*/
|
|
|
|
|
void do_homing_move(const AxisEnum axis, const float distance, const feedRate_t fr_mm_s=0.0, const bool final_approach=true) {
|
|
|
|
|
void do_homing_move(const AxisEnum axis, const float distance, const feedRate_t fr_mm_s=0.0, const bool final_approach=true) {
|
|
|
|
|
DEBUG_SECTION(log_move, "do_homing_move", DEBUGGING(LEVELING));
|
|
|
|
|
|
|
|
|
|
const feedRate_t home_fr_mm_s = fr_mm_s ?: homing_feedrate(axis);
|
|
|
|
@ -1377,88 +1370,14 @@ void do_homing_move(const AxisEnum axis, const float distance, const feedRate_t
|
|
|
|
|
// Re-enable stealthChop if used. Disable diag1 pin on driver.
|
|
|
|
|
TERN_(SENSORLESS_HOMING, end_sensorless_homing_per_axis(axis, stealth_states));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set an axis' current position to its home position (after homing).
|
|
|
|
|
*
|
|
|
|
|
* For Core and Cartesian robots this applies one-to-one when an
|
|
|
|
|
* individual axis has been homed.
|
|
|
|
|
*
|
|
|
|
|
* DELTA should wait until all homing is done before setting the XYZ
|
|
|
|
|
* current_position to home, because homing is a single operation.
|
|
|
|
|
* In the case where the axis positions are trusted and previously
|
|
|
|
|
* homed, DELTA could home to X or Y individually by moving either one
|
|
|
|
|
* to the center. However, homing Z always homes XY and Z.
|
|
|
|
|
*
|
|
|
|
|
* SCARA should wait until all XY homing is done before setting the XY
|
|
|
|
|
* current_position to home, because neither X nor Y is at home until
|
|
|
|
|
* both are at home. Z can however be homed individually.
|
|
|
|
|
*
|
|
|
|
|
* Callers must sync the planner position after calling this!
|
|
|
|
|
*/
|
|
|
|
|
void set_axis_is_at_home(const AxisEnum axis) {
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> set_axis_is_at_home(", AS_CHAR(axis_codes[axis]), ")");
|
|
|
|
|
|
|
|
|
|
set_axis_trusted(axis);
|
|
|
|
|
set_axis_homed(axis);
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DUAL_X_CARRIAGE)
|
|
|
|
|
if (axis == X_AXIS && (active_extruder == 1 || dual_x_carriage_mode == DXC_DUPLICATION_MODE)) {
|
|
|
|
|
current_position.x = x_home_pos(active_extruder);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ENABLED(MORGAN_SCARA)
|
|
|
|
|
scara_set_axis_is_at_home(axis);
|
|
|
|
|
#elif ENABLED(DELTA)
|
|
|
|
|
current_position[axis] = (axis == Z_AXIS) ? delta_height - TERN0(HAS_BED_PROBE, probe.offset.z) : base_home_pos(axis);
|
|
|
|
|
#else
|
|
|
|
|
current_position[axis] = base_home_pos(axis);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Z Probe Z Homing? Account for the probe's Z offset.
|
|
|
|
|
* Set an axis to be unhomed. (Unless we are on a machine - e.g. a cheap Chinese CNC machine -
|
|
|
|
|
* that has no endstops. Such machines should always be considered to be in a "known" and
|
|
|
|
|
* "trusted" position).
|
|
|
|
|
*/
|
|
|
|
|
#if HAS_BED_PROBE && Z_HOME_DIR < 0
|
|
|
|
|
if (axis == Z_AXIS) {
|
|
|
|
|
#if HOMING_Z_WITH_PROBE
|
|
|
|
|
|
|
|
|
|
current_position.z -= probe.offset.z;
|
|
|
|
|
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("*** Z HOMED WITH PROBE (Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) ***\n> probe.offset.z = ", probe.offset.z);
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("*** Z HOMED TO ENDSTOP ***");
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
TERN_(I2C_POSITION_ENCODERS, I2CPEM.homed(axis));
|
|
|
|
|
|
|
|
|
|
TERN_(BABYSTEP_DISPLAY_TOTAL, babystep.reset_total(axis));
|
|
|
|
|
|
|
|
|
|
#if HAS_POSITION_SHIFT
|
|
|
|
|
position_shift[axis] = 0;
|
|
|
|
|
update_workspace_offset(axis);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (DEBUGGING(LEVELING)) {
|
|
|
|
|
#if HAS_HOME_OFFSET
|
|
|
|
|
DEBUG_ECHOLNPAIR("> home_offset[", AS_CHAR(axis_codes[axis]), "] = ", home_offset[axis]);
|
|
|
|
|
#endif
|
|
|
|
|
DEBUG_POS("", current_position);
|
|
|
|
|
DEBUG_ECHOLNPAIR("<<< set_axis_is_at_home(", axis_codes[axis], ")");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set an axis to be unhomed.
|
|
|
|
|
*/
|
|
|
|
|
void set_axis_never_homed(const AxisEnum axis) {
|
|
|
|
|
void set_axis_never_homed(const AxisEnum axis) {
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> set_axis_never_homed(", axis_codes[axis], ")");
|
|
|
|
|
|
|
|
|
|
set_axis_untrusted(axis);
|
|
|
|
@ -1467,9 +1386,9 @@ void set_axis_never_homed(const AxisEnum axis) {
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("<<< set_axis_never_homed(", axis_codes[axis], ")");
|
|
|
|
|
|
|
|
|
|
TERN_(I2C_POSITION_ENCODERS, I2CPEM.unhomed(axis));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef TMC_HOME_PHASE
|
|
|
|
|
#if ENABLED(TMC_HOME_PHASE)
|
|
|
|
|
/**
|
|
|
|
|
* Move the axis back to its home_phase if set and driver is capable (TMC)
|
|
|
|
|
*
|
|
|
|
@ -1546,9 +1465,9 @@ void set_axis_never_homed(const AxisEnum axis) {
|
|
|
|
|
do_homing_move(axis, mmDelta, get_homing_bump_feedrate(axis));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Home an individual "raw axis" to its endstop.
|
|
|
|
|
* This applies to XYZ on Cartesian and Core robots, and
|
|
|
|
|
* to the individual ABC steppers on DELTA and SCARA.
|
|
|
|
@ -1559,7 +1478,7 @@ void set_axis_never_homed(const AxisEnum axis) {
|
|
|
|
|
* before updating the current position.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void homeaxis(const AxisEnum axis) {
|
|
|
|
|
void homeaxis(const AxisEnum axis) {
|
|
|
|
|
|
|
|
|
|
#if IS_SCARA
|
|
|
|
|
// Only Z homing (with probe) is permitted
|
|
|
|
@ -1875,7 +1794,85 @@ void homeaxis(const AxisEnum axis) {
|
|
|
|
|
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("<<< homeaxis(", axis_codes[axis], ")");
|
|
|
|
|
|
|
|
|
|
} // homeaxis()
|
|
|
|
|
} // homeaxis()
|
|
|
|
|
|
|
|
|
|
#endif // HAS_ENDSTOPS
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set an axis' current position to its home position (after homing).
|
|
|
|
|
*
|
|
|
|
|
* For Core and Cartesian robots this applies one-to-one when an
|
|
|
|
|
* individual axis has been homed.
|
|
|
|
|
*
|
|
|
|
|
* DELTA should wait until all homing is done before setting the XYZ
|
|
|
|
|
* current_position to home, because homing is a single operation.
|
|
|
|
|
* In the case where the axis positions are trusted and previously
|
|
|
|
|
* homed, DELTA could home to X or Y individually by moving either one
|
|
|
|
|
* to the center. However, homing Z always homes XY and Z.
|
|
|
|
|
*
|
|
|
|
|
* SCARA should wait until all XY homing is done before setting the XY
|
|
|
|
|
* current_position to home, because neither X nor Y is at home until
|
|
|
|
|
* both are at home. Z can however be homed individually.
|
|
|
|
|
*
|
|
|
|
|
* Callers must sync the planner position after calling this!
|
|
|
|
|
*/
|
|
|
|
|
void set_axis_is_at_home(const AxisEnum axis) {
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> set_axis_is_at_home(", AS_CHAR(axis_codes[axis]), ")");
|
|
|
|
|
|
|
|
|
|
set_axis_trusted(axis);
|
|
|
|
|
set_axis_homed(axis);
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DUAL_X_CARRIAGE)
|
|
|
|
|
if (axis == X_AXIS && (active_extruder == 1 || dual_x_carriage_mode == DXC_DUPLICATION_MODE)) {
|
|
|
|
|
current_position.x = x_home_pos(active_extruder);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ENABLED(MORGAN_SCARA)
|
|
|
|
|
scara_set_axis_is_at_home(axis);
|
|
|
|
|
#elif ENABLED(DELTA)
|
|
|
|
|
current_position[axis] = (axis == Z_AXIS) ? delta_height - TERN0(HAS_BED_PROBE, probe.offset.z) : base_home_pos(axis);
|
|
|
|
|
#else
|
|
|
|
|
current_position[axis] = base_home_pos(axis);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Z Probe Z Homing? Account for the probe's Z offset.
|
|
|
|
|
*/
|
|
|
|
|
#if HAS_BED_PROBE && Z_HOME_DIR < 0
|
|
|
|
|
if (axis == Z_AXIS) {
|
|
|
|
|
#if HOMING_Z_WITH_PROBE
|
|
|
|
|
|
|
|
|
|
current_position.z -= probe.offset.z;
|
|
|
|
|
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("*** Z HOMED WITH PROBE (Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) ***\n> probe.offset.z = ", probe.offset.z);
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("*** Z HOMED TO ENDSTOP ***");
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
TERN_(I2C_POSITION_ENCODERS, I2CPEM.homed(axis));
|
|
|
|
|
|
|
|
|
|
TERN_(BABYSTEP_DISPLAY_TOTAL, babystep.reset_total(axis));
|
|
|
|
|
|
|
|
|
|
#if HAS_POSITION_SHIFT
|
|
|
|
|
position_shift[axis] = 0;
|
|
|
|
|
update_workspace_offset(axis);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (DEBUGGING(LEVELING)) {
|
|
|
|
|
#if HAS_HOME_OFFSET
|
|
|
|
|
DEBUG_ECHOLNPAIR("> home_offset[", AS_CHAR(axis_codes[axis]), "] = ", home_offset[axis]);
|
|
|
|
|
#endif
|
|
|
|
|
DEBUG_POS("", current_position);
|
|
|
|
|
DEBUG_ECHOLNPAIR("<<< set_axis_is_at_home(", axis_codes[axis], ")");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if HAS_WORKSPACE_OFFSET
|
|
|
|
|
void update_workspace_offset(const AxisEnum axis) {
|
|
|
|
@ -1893,4 +1890,4 @@ void homeaxis(const AxisEnum axis) {
|
|
|
|
|
home_offset[axis] = v;
|
|
|
|
|
update_workspace_offset(axis);
|
|
|
|
|
}
|
|
|
|
|
#endif // HAS_M206_COMMAND
|
|
|
|
|
#endif
|
|
|
|
|