1
0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2024-11-29 23:07:42 +00:00

🐛 Probe behavior corrections (#25631)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
Co-authored-by: David Fries <2767875+dfries@users.noreply.github.com>
This commit is contained in:
James Pearson 2023-04-28 23:30:15 +01:00 committed by GitHub
parent 7d95928cbb
commit c5a2e41647
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 113 additions and 82 deletions

View File

@ -1725,7 +1725,7 @@
//#define Z_CLEARANCE_FOR_HOMING 4 // (mm) Minimal Z height before homing (G28) for Z clearance above the bed, clamps, ...
// Be sure to have this much clearance over your Z_MAX_POS to prevent grinding.
//#define Z_AFTER_HOMING 10 // (mm) Height to move to after homing Z
//#define Z_AFTER_HOMING 10 // (mm) Height to move to after homing (if Z was homed)
// Direction of endstops when homing; 1=MAX, -1=MIN
// :[-1,1]

View File

@ -924,7 +924,7 @@
//#define QUICK_HOME // If G28 contains XY do a diagonal move first
//#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X
//#define HOME_Z_FIRST // Home Z first. Requires a Z-MIN endstop (not a probe).
//#define HOME_Z_FIRST // Home Z first. Requires a real endstop (not a probe).
//#define CODEPENDENT_XY_HOMING // If X/Y can't home without homing Y/X first
// @section bltouch

View File

@ -112,7 +112,7 @@
* If omitted, the nozzle will raise by Z_CLEARANCE_BETWEEN_PROBES.
*
* H # Offset With P4, 'H' specifies the Offset above the mesh height to place the nozzle.
* If omitted, Z_CLEARANCE_BETWEEN_PROBES will be used.
* If omitted, Z_TWEEN_SAFE_CLEARANCE will be used.
*
* I # Invalidate Invalidate the specified number of Mesh Points near the given 'X' 'Y'. If X or Y are omitted,
* the nozzle location is used. If no 'I' value is given, only the point nearest to the location
@ -790,10 +790,7 @@ void unified_bed_leveling::shift_mesh_height() {
if (best.pos.x >= 0) { // mesh point found and is reachable by probe
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_START));
const float measured_z = probe.probe_at_point(
best.meshpos(),
stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity
);
const float measured_z = probe.probe_at_point(best.meshpos(), stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity);
z_values[best.pos.x][best.pos.y] = measured_z;
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_FINISH);
@ -1034,9 +1031,9 @@ void set_message_with_feedback(FSTR_P const fstr) {
save_ubl_active_state_and_disable();
LCD_MESSAGE(MSG_UBL_FINE_TUNE_MESH);
ui.capture(); // Take over control of the LCD encoder
ui.capture(); // Take over control of the LCD encoder
do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_PROBES); // Move to the given XY with probe clearance
do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); // Move to the given XY with probe clearance
MeshFlags done_flags{0};
const xy_int8_t &lpos = location.pos;
@ -1053,7 +1050,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
done_flags.mark(lpos); // Mark this location as 'adjusted' so a new
// location is used on the next loop
const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_CLEARANCE_BETWEEN_PROBES };
const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_TWEEN_SAFE_CLEARANCE };
if (!position_is_reachable(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable)
@ -1063,7 +1060,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
KEEPALIVE_STATE(PAUSED_FOR_USER);
if (do_ubl_mesh_map) display_map(param.T_map_type); // Display the current point
if (do_ubl_mesh_map) display_map(param.T_map_type); // Display the current point
#if IS_TFTGLCD_PANEL
ui.ubl_plot(lpos.x, lpos.y); // update plot screen
@ -1093,7 +1090,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
// Button held down? Abort editing
if (_click_and_hold([]{
ui.return_to_status();
do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES);
do_z_clearance(Z_TWEEN_SAFE_CLEARANCE);
set_message_with_feedback(GET_TEXT_F(MSG_EDITING_STOPPED));
})) break;
@ -1113,7 +1110,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
if (do_ubl_mesh_map) display_map(param.T_map_type);
restore_ubl_active_state_and_leave();
do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_PROBES);
do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE);
LCD_MESSAGE(MSG_UBL_DONE_EDITING_MESH);
SERIAL_ECHOLNPGM("Done Editing Mesh");

View File

@ -98,7 +98,7 @@ void GcodeSuite::G35() {
// Probe all positions
LOOP_L_N(i, G35_PROBE_COUNT) {
const float z_probed_height = probe.probe_at_point(tramming_points[i], PROBE_PT_RAISE, 0, true);
const float z_probed_height = probe.probe_at_point(tramming_points[i], PROBE_PT_RAISE);
if (isnan(z_probed_height)) {
SERIAL_ECHOPGM("G35 failed at point ", i + 1, " (");
SERIAL_ECHOPGM_P((char *)pgm_read_ptr(&tramming_point_name[i]));

View File

@ -356,6 +356,8 @@ void GcodeSuite::G28() {
endstops.enable(true); // Enable endstops for next homing move
bool finalRaiseZ = false;
#if ENABLED(DELTA)
constexpr bool doZ = true; // for NANODLP_Z_SYNC if your DLP is on a DELTA
@ -407,8 +409,9 @@ void GcodeSuite::G28() {
UNUSED(needZ); UNUSED(homeZZ);
// Z may home first, e.g., when homing away from the bed
TERN_(HOME_Z_FIRST, if (doZ) homeaxis(Z_AXIS));
// Z may home first, e.g., when homing away from the bed.
// This is also permitted when homing with a Z endstop.
if (TERN0(HOME_Z_FIRST, doZ)) homeaxis(Z_AXIS);
// 'R' to specify a specific raise. 'R0' indicates no raise, e.g., for recovery.resume
// When 'R0' is used, there should already be adequate clearance, e.g., from homing Z to max.
@ -517,7 +520,10 @@ void GcodeSuite::G28() {
#else
homeaxis(Z_AXIS);
#endif
do_move_after_z_homing();
#if EITHER(Z_HOME_TO_MIN, ALLOW_Z_AFTER_HOMING)
finalRaiseZ = true;
#endif
}
#endif
@ -575,18 +581,6 @@ void GcodeSuite::G28() {
// Clear endstop state for polled stallGuard endstops
TERN_(SPI_ENDSTOPS, endstops.clear_endstop_state());
// Move to a height where we can use the full xy-area
TERN_(DELTA_HOME_TO_SAFE_ZONE, do_blocking_move_to_z(delta_clip_start_height));
TERN_(CAN_SET_LEVELING_AFTER_G28, if (leveling_restore_state) set_bed_leveling_enabled());
restore_feedrate_and_scaling();
// Restore the active tool after homing
#if HAS_MULTI_HOTEND && (DISABLED(DELTA) || ENABLED(DELTA_HOME_TO_SAFE_ZONE))
tool_change(old_tool_index, TERN(PARKING_EXTRUDER, !pe_final_change_must_unpark, DISABLED(DUAL_X_CARRIAGE))); // Do move if one of these
#endif
#if HAS_HOMING_CURRENT
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Restore driver current...");
#if HAS_CURRENT_HOME(X)
@ -627,6 +621,23 @@ void GcodeSuite::G28() {
#endif
#endif // HAS_HOMING_CURRENT
// Move to a height where we can use the full xy-area
TERN_(DELTA_HOME_TO_SAFE_ZONE, do_blocking_move_to_z(delta_clip_start_height));
// Move to the configured Z only if Z was homed to MIN, because machines that
// home to MAX historically expect 'G28 Z' to be safe to use at the end of a
// print, and do_move_after_z_homing is not very nuanced.
if (finalRaiseZ) do_move_after_z_homing();
TERN_(CAN_SET_LEVELING_AFTER_G28, if (leveling_restore_state) set_bed_leveling_enabled());
// Restore the active tool after homing
#if HAS_MULTI_HOTEND && (DISABLED(DELTA) || ENABLED(DELTA_HOME_TO_SAFE_ZONE))
tool_change(old_tool_index, TERN(PARKING_EXTRUDER, !pe_final_change_must_unpark, DISABLED(DUAL_X_CARRIAGE))); // Do move if one of these
#endif
restore_feedrate_and_scaling();
ui.refresh();
TERN_(HAS_DWIN_E3V2_BASIC, DWIN_HomingDone());

View File

@ -170,7 +170,7 @@ static float std_dev_points(float z_pt[NPP + 1], const bool _0p_cal, const bool
*/
static float calibration_probe(const xy_pos_t &xy, const bool stow, const bool probe_at_offset) {
#if HAS_BED_PROBE
return probe.probe_at_point(xy, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, probe_at_offset, false);
return probe.probe_at_point(xy, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, probe_at_offset, false, Z_PROBE_LOW_POINT, Z_TWEEN_SAFE_CLEARANCE, true);
#else
UNUSED(stow);
return lcd_probe_pt(xy);

View File

@ -153,7 +153,8 @@ void GcodeSuite::G34() {
const xy_pos_t diff = z_stepper_align.xy[i] - z_stepper_align.xy[j];
return HYPOT2(diff.x, diff.y);
};
float z_probe = (Z_PROBE_SAFE_CLEARANCE) + (G34_MAX_GRADE) * 0.01f * SQRT(_MAX(0, magnitude2(0, 1)
const float zoffs = (probe.offset.z < 0) ? -probe.offset.z : 0.0f;
float z_probe = (Z_TWEEN_SAFE_CLEARANCE + zoffs) + (G34_MAX_GRADE) * 0.01f * SQRT(_MAX(0, magnitude2(0, 1)
#if TRIPLE_Z
, magnitude2(2, 1), magnitude2(2, 0)
#if QUAD_Z
@ -165,12 +166,6 @@ void GcodeSuite::G34() {
// Home before the alignment procedure
home_if_needed();
// Move the Z coordinate realm towards the positive - dirty trick
current_position.z += z_probe * 0.5f;
sync_plan_position();
// Now, the Z origin lies below the build plate. That allows to probe deeper, before run_z_probe throws an error.
// This hack is un-done at the end of G34 - either by re-homing, or by using the probed heights of the last iteration.
#if !HAS_Z_STEPPER_ALIGN_STEPPER_XY
float last_z_align_move[NUM_Z_STEPPERS] = ARRAY_N_1(NUM_Z_STEPPERS, 10000.0f);
#else
@ -213,20 +208,16 @@ void GcodeSuite::G34() {
// iteration odd/even --> downward / upward stepper sequence
const uint8_t iprobe = (iteration & 1) ? NUM_Z_STEPPERS - 1 - i : i;
// Safe clearance even on an incline
if ((iteration == 0 || i > 0) && z_probe > current_position.z) do_blocking_move_to_z(z_probe);
xy_pos_t &ppos = z_stepper_align.xy[iprobe];
if (DEBUGGING(LEVELING))
DEBUG_ECHOLNPGM_P(PSTR("Probing X"), ppos.x, SP_Y_STR, ppos.y);
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM_P(PSTR("Probing X"), ppos.x, SP_Y_STR, ppos.y);
// Probe a Z height for each stepper.
// Probing sanity check is disabled, as it would trigger even in normal cases because
// current_position.z has been manually altered in the "dirty trick" above.
const float z_probed_height = probe.probe_at_point(DIFF_TERN(HAS_HOME_OFFSET, ppos, xy_pos_t(home_offset)), raise_after, 0, true, false);
const float z_probed_height = probe.probe_at_point(DIFF_TERN(HAS_HOME_OFFSET, ppos, xy_pos_t(home_offset)), raise_after, 0, true, false, (Z_PROBE_LOW_POINT) - z_probe * 0.5f, z_probe * 0.5f);
if (isnan(z_probed_height)) {
SERIAL_ECHOLNPGM("Probing failed");
SERIAL_ECHOLNPGM(STR_ERR_PROBING_FAILED);
LCD_MESSAGE(MSG_LCD_PROBING_FAILED);
err_break = true;
break;
@ -234,7 +225,7 @@ void GcodeSuite::G34() {
// Add height to each value, to provide a more useful target height for
// the next iteration of probing. This allows adjustments to be made away from the bed.
z_measured[iprobe] = z_probed_height + (Z_CLEARANCE_BETWEEN_PROBES);
z_measured[iprobe] = z_probed_height + (Z_TWEEN_SAFE_CLEARANCE + zoffs); //do we need to add the clearance to this?
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> Z", iprobe + 1, " measured position is ", z_measured[iprobe]);
@ -248,7 +239,7 @@ void GcodeSuite::G34() {
// Adapt the next probe clearance height based on the new measurements.
// Safe_height = lowest distance to bed (= highest measurement) plus highest measured misalignment.
z_maxdiff = z_measured_max - z_measured_min;
z_probe = (Z_PROBE_SAFE_CLEARANCE) + z_measured_max + z_maxdiff;
z_probe = (Z_TWEEN_SAFE_CLEARANCE + zoffs) + z_measured_max + z_maxdiff; //Not sure we need z_maxdiff, but leaving it in for safety.
#if HAS_Z_STEPPER_ALIGN_STEPPER_XY
// Replace the initial values in z_measured with calculated heights at
@ -428,15 +419,13 @@ void GcodeSuite::G34() {
IF_DISABLED(TOUCH_MI_PROBE, probe.stow());
#if ENABLED(HOME_AFTER_G34)
// After this operation the z position needs correction
set_axis_never_homed(Z_AXIS);
// Home Z after the alignment procedure
process_subcommands_now(F("G28Z"));
#else
// Use the probed height from the last iteration to determine the Z height.
// z_measured_min is used, because all steppers are aligned to z_measured_min.
// Ideally, this would be equal to the 'z_probe * 0.5f' which was added earlier.
current_position.z -= z_measured_min - float(Z_CLEARANCE_BETWEEN_PROBES);
current_position.z -= z_measured_min - (Z_TWEEN_SAFE_CLEARANCE + zoffs); //we shouldn't want to subtract the clearance from here right? (Depends if we added it further up)
sync_plan_position();
#endif

View File

@ -223,7 +223,7 @@ void GcodeSuite::M48() {
} // n_legs
// Probe a single point
const float pz = probe.probe_at_point(test_position, raise_after, 0);
const float pz = probe.probe_at_point(test_position, raise_after);
// Break the loop if the probe fails
probing_good = !isnan(pz);

View File

@ -77,7 +77,7 @@ void GcodeSuite::G30() {
const ProbePtRaise raise_after = parser.boolval('E', true) ? PROBE_PT_STOW : PROBE_PT_NONE;
TERN_(HAS_PTC, ptc.set_enabled(!parser.seen('C') || parser.value_bool()));
const float measured_z = probe.probe_at_point(probepos, raise_after, 1);
const float measured_z = probe.probe_at_point(probepos, raise_after);
TERN_(HAS_PTC, ptc.set_enabled(true));
if (!isnan(measured_z)) {
SERIAL_ECHOLNPGM("Bed X: ", probepos.asLogical().x, " Y: ", probepos.asLogical().y, " Z: ", measured_z);

View File

@ -2350,6 +2350,10 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#error "HOME_Z_FIRST can't be used when homing Z with a probe."
#endif
#if Z_HOME_TO_MAX && defined(Z_AFTER_HOMING) && DISABLED(ALLOW_Z_AFTER_HOMING)
#error "Z_AFTER_HOMING shouldn't be used with Z max homing to keep 'G28 Z' safe for end-of-print usage. Define ALLOW_Z_AFTER_HOMING to allow this at your own risk."
#endif
// Dual/multiple endstops requirements
#if ENABLED(X_DUAL_ENDSTOPS)
#if ENABLED(DELTA)

View File

@ -1409,6 +1409,13 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item
static float mlev_z_pos = 0;
static bool use_probe = false;
#if HAS_BED_PROBE
constexpr float probe_x_min = _MAX(0 + corner_pos, X_MIN_POS + probe.offset.x, X_MIN_POS + PROBING_MARGIN) - probe.offset.x,
probe_x_max = _MIN((X_BED_SIZE + X_MIN_POS) - corner_pos, X_MAX_POS + probe.offset.x, X_MAX_POS - PROBING_MARGIN) - probe.offset.x,
probe_y_min = _MAX(0 + corner_pos, Y_MIN_POS + probe.offset.y, Y_MIN_POS + PROBING_MARGIN) - probe.offset.y,
probe_y_max = _MIN((Y_BED_SIZE + Y_MIN_POS) - corner_pos, Y_MAX_POS + probe.offset.y, Y_MAX_POS - PROBING_MARGIN) - probe.offset.y;
#endif
switch (item) {
case MLEVEL_BACK:
if (draw)
@ -1425,19 +1432,22 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item
Draw_Checkbox(row, use_probe);
}
else {
use_probe = !use_probe;
use_probe ^= true;
Draw_Checkbox(row, use_probe);
if (use_probe) {
Popup_Handler(Level);
constexpr struct { xy_pos_t p, ProbePtRaise r } points[] = {
{ { probe_x_min, probe_y_min }, PROBE_PT_RAISE },
{ { probe_x_min, probe_y_max }, PROBE_PT_RAISE },
{ { probe_x_max, probe_y_max }, PROBE_PT_RAISE },
{ { probe_x_max, probe_y_min }, PROBE_PT_STOW }
};
corner_avg = 0;
#define PROBE_X_MIN _MAX(0 + corner_pos, X_MIN_POS + probe.offset.x, X_MIN_POS + PROBING_MARGIN) - probe.offset.x
#define PROBE_X_MAX _MIN((X_BED_SIZE + X_MIN_POS) - corner_pos, X_MAX_POS + probe.offset.x, X_MAX_POS - PROBING_MARGIN) - probe.offset.x
#define PROBE_Y_MIN _MAX(0 + corner_pos, Y_MIN_POS + probe.offset.y, Y_MIN_POS + PROBING_MARGIN) - probe.offset.y
#define PROBE_Y_MAX _MIN((Y_BED_SIZE + Y_MIN_POS) - corner_pos, Y_MAX_POS + probe.offset.y, Y_MAX_POS - PROBING_MARGIN) - probe.offset.y
corner_avg += probe.probe_at_point(PROBE_X_MIN, PROBE_Y_MIN, PROBE_PT_RAISE, 0, false);
corner_avg += probe.probe_at_point(PROBE_X_MIN, PROBE_Y_MAX, PROBE_PT_RAISE, 0, false);
corner_avg += probe.probe_at_point(PROBE_X_MAX, PROBE_Y_MAX, PROBE_PT_RAISE, 0, false);
corner_avg += probe.probe_at_point(PROBE_X_MAX, PROBE_Y_MIN, PROBE_PT_STOW, 0, false);
for (uint8_t i = 0; i < COUNT(points); i++) {
const float mz = probe.probe_at_point(points[i].p, points[i].r, 0, false);
if (isnan(mz)) { corner_avg = 0; break; }
corner_avg += mz;
}
corner_avg /= 4;
Redraw_Menu();
}
@ -1451,7 +1461,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item
Popup_Handler(MoveWait);
if (use_probe) {
#if HAS_BED_PROBE
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MIN, 1, 3, str_1), dtostrf(PROBE_Y_MIN, 1, 3, str_2));
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_min, 1, 3, str_1), dtostrf(probe_y_min, 1, 3, str_2));
gcode.process_subcommands_now(cmd);
planner.synchronize();
Popup_Handler(ManualProbing);
@ -1472,7 +1482,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item
Popup_Handler(MoveWait);
if (use_probe) {
#if HAS_BED_PROBE
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MIN, 1, 3, str_1), dtostrf(PROBE_Y_MAX, 1, 3, str_2));
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_min, 1, 3, str_1), dtostrf(probe_y_max, 1, 3, str_2));
gcode.process_subcommands_now(cmd);
planner.synchronize();
Popup_Handler(ManualProbing);
@ -1493,7 +1503,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item
Popup_Handler(MoveWait);
if (use_probe) {
#if HAS_BED_PROBE
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MAX, 1, 3, str_1), dtostrf(PROBE_Y_MAX, 1, 3, str_2));
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_max, 1, 3, str_1), dtostrf(probe_y_max, 1, 3, str_2));
gcode.process_subcommands_now(cmd);
planner.synchronize();
Popup_Handler(ManualProbing);
@ -1514,7 +1524,7 @@ void CrealityDWINClass::Menu_Item_Handler(const uint8_t menu, const uint8_t item
Popup_Handler(MoveWait);
if (use_probe) {
#if HAS_BED_PROBE
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(PROBE_X_MAX, 1, 3, str_1), dtostrf(PROBE_Y_MIN, 1, 3, str_2));
sprintf_P(cmd, PSTR("G0 F4000\nG0 Z10\nG0 X%s Y%s"), dtostrf(probe_x_max, 1, 3, str_1), dtostrf(probe_y_min, 1, 3, str_2));
gcode.process_subcommands_now(cmd);
planner.synchronize();
Popup_Handler(ManualProbing);

View File

@ -102,7 +102,7 @@ void prepare_for_probe_offset_wizard() {
// Probe for Z reference
ui.wait_for_move = true;
z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_RAISE, 0, true);
z_offset_ref = probe.probe_at_point(wizard_pos, PROBE_PT_RAISE);
ui.wait_for_move = false;
// Stow the probe, as the last call to probe.probe_at_point(...) left

View File

@ -53,7 +53,7 @@ static int8_t reference_index; // = 0
#endif
static bool probe_single_point() {
const float z_probed_height = probe.probe_at_point(tramming_points[tram_index], PROBE_PT_RAISE, 0, true);
const float z_probed_height = probe.probe_at_point(tramming_points[tram_index], PROBE_PT_RAISE);
z_measured[tram_index] = z_probed_height;
if (reference_index < 0) reference_index = tram_index;
move_to_tramming_wait_pos();

View File

@ -522,7 +522,7 @@ bool Probe::set_deployed(const bool deploy, const bool no_return/*=false*/) {
#endif
if (z_raise_wanted) {
const float zdest = DIFF_TERN(HAS_HOTEND_OFFSET, _MAX(Z_CLEARANCE_BETWEEN_PROBES, Z_CLEARANCE_DEPLOY_PROBE), hotend_offset[active_extruder].z);
const float zdest = DIFF_TERN(HAS_HOTEND_OFFSET, Z_CLEARANCE_DEPLOY_PROBE, hotend_offset[active_extruder].z);
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z to ", zdest);
do_z_clearance(zdest);
}
@ -716,10 +716,12 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
* @param sanity_check Flag to compare the probe result with the expected result
* based on the probe Z offset. If the result is too far away
* (more than 2mm too early) then consider it an error.
* @param z_min_point Override the minimum probing height (-2mm), to allow deeper probing.
* @param z_clearance Z clearance to apply on probe failure.
*
* @return The Z position of the bed at the current XY or NAN on error.
*/
float Probe::run_z_probe(const bool sanity_check/*=true*/) {
float Probe::run_z_probe(const bool sanity_check/*=true*/, const_float_t z_min_point/*=Z_PROBE_LOW_POINT*/, const_float_t z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/) {
DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING));
const float zoffs = SUM_TERN(HAS_HOTEND_OFFSET, -offset.z, hotend_offset[active_extruder].z);
@ -750,9 +752,8 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
};
// Stop the probe before it goes too low to prevent damage.
// For known Z probe below the expected trigger point, otherwise -10mm.
const float z_probe_low_point = axis_is_trusted(Z_AXIS) ? zoffs + Z_PROBE_LOW_POINT : -10.0f;
// For known Z probe below the expected trigger point, otherwise -10mm lower.
const float z_probe_low_point = zoffs + z_min_point -float((!axis_is_trusted(Z_AXIS)) * 10);
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Probe Low Point: ", z_probe_low_point);
// Double-probing does a fast probe followed by a slow probe
@ -768,7 +769,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", z1);
// Raise to give the probe clearance
do_z_clearance(Z_CLEARANCE_MULTI_PROBE);
do_z_clearance(z1 + (Z_CLEARANCE_MULTI_PROBE), false);
#elif Z_PROBE_FEEDRATE_FAST != Z_PROBE_FEEDRATE_SLOW
@ -778,7 +779,7 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
if (current_position.z > z) {
// Probe down fast. If the probe never triggered, raise for probe clearance
if (!probe_down_to_z(z, z_probe_fast_mm_s))
do_z_clearance(Z_PROBE_SAFE_CLEARANCE);
do_z_clearance(z_clearance);
}
#endif
@ -911,7 +912,11 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/) {
* with the previously active tool.
*
*/
float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after/*=PROBE_PT_NONE*/, const uint8_t verbose_level/*=0*/, const bool probe_relative/*=true*/, const bool sanity_check/*=true*/) {
float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after/*=PROBE_PT_NONE*/,
const uint8_t verbose_level/*=0*/, const bool probe_relative/*=true*/, const bool sanity_check/*=true*/,
const_float_t z_min_point/*=Z_PROBE_LOW_POINT*/, const_float_t z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/,
const bool raise_after_is_relative/*=false*/
) {
DEBUG_SECTION(log_probe, "Probe::probe_at_point", DEBUGGING(LEVELING));
if (DEBUGGING(LEVELING)) {
@ -930,7 +935,7 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
#endif
// Use a safe Z height for the XY move
const float safe_z = _MAX(current_position.z, Z_PROBE_SAFE_CLEARANCE);
const float safe_z = _MAX(current_position.z, z_clearance);
// On delta keep Z below clip height or do_blocking_move_to will abort
xyz_pos_t npos = NUM_AXIS_ARRAY(
@ -959,7 +964,7 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
#else // !BD_SENSOR
float measured_z = deploy() ? NAN : run_z_probe(sanity_check) + offset.z;
float measured_z = deploy() ? NAN : run_z_probe(sanity_check, z_min_point, z_clearance) + offset.z;
// Deploy succeeded and a successful measurement was done.
// Raise and/or stow the probe depending on 'raise_after' and settings.
@ -967,7 +972,10 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
switch (raise_after) {
default: break;
case PROBE_PT_RAISE:
do_z_clearance(Z_PROBE_SAFE_CLEARANCE);
if (raise_after_is_relative)
do_z_clearance(current_position.z + z_clearance, false);
else
do_z_clearance(z_clearance);
break;
case PROBE_PT_STOW: case PROBE_PT_LAST_STOW:
if (stow()) measured_z = NAN; // Error on stow?

View File

@ -29,6 +29,10 @@
#include "motion.h"
#if ENABLED(BLTOUCH)
#include "../feature/bltouch.h"
#endif
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
#include "../core/debug_out.h"
@ -48,7 +52,7 @@
#endif
// In BLTOUCH HS mode, the probe travels in a deployed state.
#define Z_PROBE_SAFE_CLEARANCE SUM_TERN(BLTOUCH, Z_CLEARANCE_BETWEEN_PROBES, bltouch.z_extra_clearance())
#define Z_TWEEN_SAFE_CLEARANCE SUM_TERN(BLTOUCH, Z_CLEARANCE_BETWEEN_PROBES, bltouch.z_extra_clearance())
#if ENABLED(PREHEAT_BEFORE_LEVELING)
#ifndef LEVELING_NOZZLE_TEMP
@ -159,9 +163,17 @@ public:
#endif // !IS_KINEMATIC
static float probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true);
static float probe_at_point(const xy_pos_t &pos, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true) {
return probe_at_point(pos.x, pos.y, raise_after, verbose_level, probe_relative, sanity_check);
static float probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRaise raise_after=PROBE_PT_NONE,
const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true,
const_float_t z_min_point=Z_PROBE_LOW_POINT, const_float_t z_clearance=Z_TWEEN_SAFE_CLEARANCE,
const bool raise_after_is_relative=false);
static float probe_at_point(const xy_pos_t &pos, const ProbePtRaise raise_after=PROBE_PT_NONE,
const uint8_t verbose_level=0, const bool probe_relative=true, const bool sanity_check=true,
const_float_t z_min_point=Z_PROBE_LOW_POINT, float z_clearance=Z_TWEEN_SAFE_CLEARANCE,
const bool raise_after_is_relative=false
) {
return probe_at_point(pos.x, pos.y, raise_after, verbose_level, probe_relative, sanity_check, z_min_point, z_clearance, raise_after_is_relative);
}
#else // !HAS_BED_PROBE
@ -330,7 +342,7 @@ public:
private:
static bool probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s);
static float run_z_probe(const bool sanity_check=true);
static float run_z_probe(const bool sanity_check=true, const_float_t z_min_point=Z_PROBE_LOW_POINT, const_float_t z_clearance=Z_TWEEN_SAFE_CLEARANCE);
};
extern Probe probe;