|
|
|
@ -1713,27 +1713,37 @@ static void clean_up_after_endstop_or_probe_move() {
|
|
|
|
|
z_dest -= zprobe_zoffset;
|
|
|
|
|
|
|
|
|
|
if (z_dest > current_position[Z_AXIS]) {
|
|
|
|
|
float old_feedrate = feedrate;
|
|
|
|
|
feedrate = homing_feedrate[Z_AXIS];
|
|
|
|
|
do_blocking_move_to_z(z_dest);
|
|
|
|
|
feedrate = old_feedrate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif //HAS_BED_PROBE
|
|
|
|
|
|
|
|
|
|
#if ENABLED(Z_PROBE_SLED) || ENABLED(Z_SAFE_HOMING) || HAS_PROBING_PROCEDURE
|
|
|
|
|
static void axis_unhomed_error(bool xyz=false) {
|
|
|
|
|
if (xyz) {
|
|
|
|
|
LCD_MESSAGEPGM(MSG_XYZ_UNHOMED);
|
|
|
|
|
SERIAL_ECHO_START;
|
|
|
|
|
SERIAL_ECHOLNPGM(MSG_XYZ_UNHOMED);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
LCD_MESSAGEPGM(MSG_YX_UNHOMED);
|
|
|
|
|
static bool axis_unhomed_error(const bool x, const bool y, const bool z) {
|
|
|
|
|
const bool xx = x && !axis_homed[X_AXIS],
|
|
|
|
|
yy = y && !axis_homed[Y_AXIS],
|
|
|
|
|
zz = z && !axis_homed[Z_AXIS];
|
|
|
|
|
if (xx || yy || zz) {
|
|
|
|
|
SERIAL_ECHO_START;
|
|
|
|
|
SERIAL_ECHOLNPGM(MSG_YX_UNHOMED);
|
|
|
|
|
SERIAL_ECHOPGM(MSG_HOME " ");
|
|
|
|
|
if (xx) SERIAL_ECHOPGM(MSG_X);
|
|
|
|
|
if (yy) SERIAL_ECHOPGM(MSG_Y);
|
|
|
|
|
if (zz) SERIAL_ECHOPGM(MSG_Z);
|
|
|
|
|
SERIAL_ECHOLNPGM(" " MSG_FIRST);
|
|
|
|
|
|
|
|
|
|
#if ENABLED(ULTRA_LCD)
|
|
|
|
|
char message[3 * (LCD_WIDTH) + 1] = ""; // worst case is kana.utf with up to 3*LCD_WIDTH+1
|
|
|
|
|
strcat_P(message, PSTR(MSG_HOME " "));
|
|
|
|
|
if (xx) strcat_P(message, PSTR(MSG_X));
|
|
|
|
|
if (yy) strcat_P(message, PSTR(MSG_Y));
|
|
|
|
|
if (zz) strcat_P(message, PSTR(MSG_Z));
|
|
|
|
|
strcat_P(message, PSTR(" " MSG_FIRST));
|
|
|
|
|
lcd_setstatus(message);
|
|
|
|
|
#endif
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -1746,45 +1756,27 @@ static void clean_up_after_endstop_or_probe_move() {
|
|
|
|
|
/**
|
|
|
|
|
* Method to dock/undock a sled designed by Charles Bell.
|
|
|
|
|
*
|
|
|
|
|
* dock[in] If true, move to MAX_X and engage the electromagnet
|
|
|
|
|
* offset[in] The additional distance to move to adjust docking location
|
|
|
|
|
* stow[in] If false, move to MAX_X and engage the solenoid
|
|
|
|
|
* If true, move to MAX_X and release the solenoid
|
|
|
|
|
*/
|
|
|
|
|
static void dock_sled(bool dock, int offset = 0) {
|
|
|
|
|
static void dock_sled(bool stow) {
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
if (DEBUGGING(LEVELING)) {
|
|
|
|
|
SERIAL_ECHOPAIR("dock_sled(", dock);
|
|
|
|
|
SERIAL_ECHOPAIR("dock_sled(", stow);
|
|
|
|
|
SERIAL_ECHOLNPGM(")");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!axis_homed[X_AXIS] || !axis_homed[Y_AXIS] || !axis_homed[Z_AXIS]) {
|
|
|
|
|
axis_unhomed_error(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (endstops.z_probe_enabled == !dock) return; // already docked/undocked?
|
|
|
|
|
if (axis_unhomed_error(true, false, false)) return;
|
|
|
|
|
|
|
|
|
|
float oldXpos = current_position[X_AXIS]; // save x position
|
|
|
|
|
float old_feedrate = feedrate;
|
|
|
|
|
if (dock) {
|
|
|
|
|
#if _Z_RAISE_PROBE_DEPLOY_STOW > 0
|
|
|
|
|
do_probe_raise(_Z_RAISE_PROBE_DEPLOY_STOW);
|
|
|
|
|
#endif
|
|
|
|
|
// Dock sled a bit closer to ensure proper capturing
|
|
|
|
|
feedrate = XY_PROBE_FEEDRATE;
|
|
|
|
|
do_blocking_move_to_x(X_MAX_POS + SLED_DOCKING_OFFSET + offset - 1);
|
|
|
|
|
digitalWrite(SLED_PIN, LOW); // turn off magnet
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
feedrate = XY_PROBE_FEEDRATE;
|
|
|
|
|
float z_loc = current_position[Z_AXIS];
|
|
|
|
|
if (z_loc < _Z_RAISE_PROBE_DEPLOY_STOW + 5) z_loc = _Z_RAISE_PROBE_DEPLOY_STOW;
|
|
|
|
|
do_blocking_move_to(X_MAX_POS + SLED_DOCKING_OFFSET + offset, current_position[Y_AXIS], z_loc); // this also updates current_position
|
|
|
|
|
digitalWrite(SLED_PIN, HIGH); // turn on magnet
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Dock sled a bit closer to ensure proper capturing
|
|
|
|
|
do_blocking_move_to_x(X_MAX_POS + SLED_DOCKING_OFFSET - ((stow) ? 1 : 0));
|
|
|
|
|
digitalWrite(SLED_PIN, !stow); // switch solenoid
|
|
|
|
|
|
|
|
|
|
do_blocking_move_to_x(oldXpos); // return to position before docking
|
|
|
|
|
|
|
|
|
|
feedrate = old_feedrate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // Z_PROBE_SLED
|
|
|
|
@ -1800,9 +1792,7 @@ static void clean_up_after_endstop_or_probe_move() {
|
|
|
|
|
if (endstops.z_probe_enabled) return;
|
|
|
|
|
|
|
|
|
|
// Make room for probe
|
|
|
|
|
#if _Z_RAISE_PROBE_DEPLOY_STOW > 0
|
|
|
|
|
do_probe_raise(_Z_RAISE_PROBE_DEPLOY_STOW);
|
|
|
|
|
#endif
|
|
|
|
|
do_probe_raise(_Z_RAISE_PROBE_DEPLOY_STOW);
|
|
|
|
|
|
|
|
|
|
#if ENABLED(Z_PROBE_SLED)
|
|
|
|
|
|
|
|
|
@ -1904,9 +1894,7 @@ static void clean_up_after_endstop_or_probe_move() {
|
|
|
|
|
if (!endstops.z_probe_enabled) return;
|
|
|
|
|
|
|
|
|
|
// Make more room for the servo
|
|
|
|
|
#if _Z_RAISE_PROBE_DEPLOY_STOW > 0
|
|
|
|
|
do_probe_raise(_Z_RAISE_PROBE_DEPLOY_STOW);
|
|
|
|
|
#endif
|
|
|
|
|
do_probe_raise(_Z_RAISE_PROBE_DEPLOY_STOW);
|
|
|
|
|
|
|
|
|
|
#if ENABLED(Z_PROBE_SLED)
|
|
|
|
|
|
|
|
|
@ -2844,28 +2832,33 @@ inline void gcode_G28() {
|
|
|
|
|
|
|
|
|
|
#elif defined(MIN_Z_HEIGHT_FOR_HOMING) && MIN_Z_HEIGHT_FOR_HOMING > 0
|
|
|
|
|
|
|
|
|
|
// Raise Z before homing any other axes and z is not already high enough (never lower z)
|
|
|
|
|
if (current_position[Z_AXIS] <= MIN_Z_HEIGHT_FOR_HOMING) {
|
|
|
|
|
destination[Z_AXIS] = MIN_Z_HEIGHT_FOR_HOMING;
|
|
|
|
|
feedrate = planner.max_feedrate[Z_AXIS] * 60; // feedrate (mm/m) = max_feedrate (mm/s)
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
if (DEBUGGING(LEVELING)) {
|
|
|
|
|
SERIAL_ECHOPAIR("Raise Z (before homing) to ", (MIN_Z_HEIGHT_FOR_HOMING));
|
|
|
|
|
SERIAL_EOL;
|
|
|
|
|
DEBUG_POS("> (home_all_axis || homeZ)", current_position);
|
|
|
|
|
DEBUG_POS("> (home_all_axis || homeZ)", destination);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
line_to_destination();
|
|
|
|
|
stepper.synchronize();
|
|
|
|
|
#if HAS_BED_PROBE
|
|
|
|
|
do_probe_raise(MIN_Z_HEIGHT_FOR_HOMING);
|
|
|
|
|
destination[Z_AXIS] = current_position[Z_AXIS];
|
|
|
|
|
#else
|
|
|
|
|
// Raise Z before homing any other axes and z is not already high enough (never lower z)
|
|
|
|
|
if (current_position[Z_AXIS] <= MIN_Z_HEIGHT_FOR_HOMING) {
|
|
|
|
|
destination[Z_AXIS] = MIN_Z_HEIGHT_FOR_HOMING;
|
|
|
|
|
feedrate = planner.max_feedrate[Z_AXIS] * 60; // feedrate (mm/m) = max_feedrate (mm/s)
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
if (DEBUGGING(LEVELING)) {
|
|
|
|
|
SERIAL_ECHOPAIR("Raise Z (before homing) to ", (MIN_Z_HEIGHT_FOR_HOMING));
|
|
|
|
|
SERIAL_EOL;
|
|
|
|
|
DEBUG_POS("> (home_all_axis || homeZ)", current_position);
|
|
|
|
|
DEBUG_POS("> (home_all_axis || homeZ)", destination);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
line_to_destination();
|
|
|
|
|
stepper.synchronize();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Update the current Z position even if it currently not real from
|
|
|
|
|
* Z-home otherwise each call to line_to_destination() will want to
|
|
|
|
|
* move Z-axis by MIN_Z_HEIGHT_FOR_HOMING.
|
|
|
|
|
*/
|
|
|
|
|
current_position[Z_AXIS] = destination[Z_AXIS];
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Update the current Z position even if it currently not real from
|
|
|
|
|
* Z-home otherwise each call to line_to_destination() will want to
|
|
|
|
|
* move Z-axis by MIN_Z_HEIGHT_FOR_HOMING.
|
|
|
|
|
*/
|
|
|
|
|
current_position[Z_AXIS] = destination[Z_AXIS];
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ENABLED(QUICK_HOME)
|
|
|
|
@ -2922,7 +2915,12 @@ inline void gcode_G28() {
|
|
|
|
|
|
|
|
|
|
#if ENABLED(HOME_Y_BEFORE_X)
|
|
|
|
|
// Home Y
|
|
|
|
|
if (home_all_axis || homeY) HOMEAXIS(Y);
|
|
|
|
|
if (home_all_axis || homeY) {
|
|
|
|
|
HOMEAXIS(Y);
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_POS("> homeY", current_position);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Home X
|
|
|
|
@ -3015,32 +3013,27 @@ inline void gcode_G28() {
|
|
|
|
|
else if (homeZ) { // Don't need to Home Z twice
|
|
|
|
|
|
|
|
|
|
// Let's see if X and Y are homed
|
|
|
|
|
if (axis_homed[X_AXIS] && axis_homed[Y_AXIS]) {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Make sure the Z probe is within the physical limits
|
|
|
|
|
* NOTE: This doesn't necessarily ensure the Z probe is also
|
|
|
|
|
* within the bed!
|
|
|
|
|
*/
|
|
|
|
|
float cpx = current_position[X_AXIS], cpy = current_position[Y_AXIS];
|
|
|
|
|
if ( cpx >= X_MIN_POS - (X_PROBE_OFFSET_FROM_EXTRUDER)
|
|
|
|
|
&& cpx <= X_MAX_POS - (X_PROBE_OFFSET_FROM_EXTRUDER)
|
|
|
|
|
&& cpy >= Y_MIN_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)
|
|
|
|
|
&& cpy <= Y_MAX_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)) {
|
|
|
|
|
|
|
|
|
|
// Home the Z axis
|
|
|
|
|
HOMEAXIS(Z);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
LCD_MESSAGEPGM(MSG_ZPROBE_OUT);
|
|
|
|
|
SERIAL_ECHO_START;
|
|
|
|
|
SERIAL_ECHOLNPGM(MSG_ZPROBE_OUT);
|
|
|
|
|
}
|
|
|
|
|
if (axis_unhomed_error(true, true, false)) return;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Make sure the Z probe is within the physical limits
|
|
|
|
|
* NOTE: This doesn't necessarily ensure the Z probe is also
|
|
|
|
|
* within the bed!
|
|
|
|
|
*/
|
|
|
|
|
float cpx = current_position[X_AXIS], cpy = current_position[Y_AXIS];
|
|
|
|
|
if ( cpx >= X_MIN_POS - (X_PROBE_OFFSET_FROM_EXTRUDER)
|
|
|
|
|
&& cpx <= X_MAX_POS - (X_PROBE_OFFSET_FROM_EXTRUDER)
|
|
|
|
|
&& cpy >= Y_MIN_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)
|
|
|
|
|
&& cpy <= Y_MAX_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)) {
|
|
|
|
|
|
|
|
|
|
// Home the Z axis
|
|
|
|
|
HOMEAXIS(Z);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
axis_unhomed_error();
|
|
|
|
|
LCD_MESSAGEPGM(MSG_ZPROBE_OUT);
|
|
|
|
|
SERIAL_ECHO_START;
|
|
|
|
|
SERIAL_ECHOLNPGM(MSG_ZPROBE_OUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // !home_all_axes && homeZ
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
@ -3381,10 +3374,7 @@ inline void gcode_G28() {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Don't allow auto-leveling without homing first
|
|
|
|
|
if (!axis_homed[X_AXIS] || !axis_homed[Y_AXIS] || !axis_homed[Z_AXIS]) {
|
|
|
|
|
axis_unhomed_error(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (axis_unhomed_error(true, true, true)) return;
|
|
|
|
|
|
|
|
|
|
int verbose_level = code_seen('V') ? code_value_int() : 1;
|
|
|
|
|
if (verbose_level < 0 || verbose_level > 4) {
|
|
|
|
@ -3394,7 +3384,7 @@ inline void gcode_G28() {
|
|
|
|
|
|
|
|
|
|
bool dryrun = code_seen('D');
|
|
|
|
|
|
|
|
|
|
#if ENABLED(Z_PROBE_SLED) || ENABLED(Z_PROBE_ALLEN_KEY)
|
|
|
|
|
#if ENABLED(Z_PROBE_ALLEN_KEY)
|
|
|
|
|
const bool stow_probe_after_each = false;
|
|
|
|
|
#else
|
|
|
|
|
bool stow_probe_after_each = code_seen('E');
|
|
|
|
@ -4136,10 +4126,7 @@ inline void gcode_M42() {
|
|
|
|
|
*/
|
|
|
|
|
inline void gcode_M48() {
|
|
|
|
|
|
|
|
|
|
if (!axis_homed[X_AXIS] || !axis_homed[Y_AXIS] || !axis_homed[Z_AXIS]) {
|
|
|
|
|
axis_unhomed_error(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (axis_unhomed_error(true, true, true)) return;
|
|
|
|
|
|
|
|
|
|
int8_t verbose_level = code_seen('V') ? code_value_byte() : 1;
|
|
|
|
|
if (verbose_level < 0 || verbose_level > 4) {
|
|
|
|
@ -4159,7 +4146,7 @@ inline void gcode_M42() {
|
|
|
|
|
float X_current = current_position[X_AXIS],
|
|
|
|
|
Y_current = current_position[Y_AXIS];
|
|
|
|
|
|
|
|
|
|
#if ENABLED(Z_PROBE_SLED) || ENABLED(Z_PROBE_ALLEN_KEY)
|
|
|
|
|
#if ENABLED(Z_PROBE_ALLEN_KEY)
|
|
|
|
|
const bool stow_probe_after_each = false;
|
|
|
|
|
#else
|
|
|
|
|
bool stow_probe_after_each = code_seen('E');
|
|
|
|
|