|
|
|
@ -56,6 +56,13 @@
|
|
|
|
|
float last_z;
|
|
|
|
|
int good_points;
|
|
|
|
|
bool corner_probing_done, wait_for_probe;
|
|
|
|
|
|
|
|
|
|
#if HAS_MARLINUI_U8GLIB
|
|
|
|
|
#include "../dogm/marlinui_DOGM.h"
|
|
|
|
|
#endif
|
|
|
|
|
#define GOOD_POINTS_TO_STR(N) ui8tostr2(N)
|
|
|
|
|
#define LAST_Z_TO_STR(N) ftostr53_63(N) //ftostr42_52(N)
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static_assert(LEVEL_CORNERS_Z_HOP >= 0, "LEVEL_CORNERS_Z_HOP must be >= 0. Please update your configuration.");
|
|
|
|
@ -66,12 +73,89 @@ extern const char G28_STR[];
|
|
|
|
|
static bool leveling_was_active = false;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int8_t bed_corner;
|
|
|
|
|
#ifndef LEVEL_CORNERS_LEVELING_ORDER
|
|
|
|
|
#define LEVEL_CORNERS_LEVELING_ORDER { LF, RF, LB, RB } // Default
|
|
|
|
|
//#define LEVEL_CORNERS_LEVELING_ORDER { LF, LB, RF } // 3 hard-coded points
|
|
|
|
|
//#define LEVEL_CORNERS_LEVELING_ORDER { LF, RF } // 3-Point tramming - Rear
|
|
|
|
|
//#define LEVEL_CORNERS_LEVELING_ORDER { LF, LB } // 3-Point tramming - Right
|
|
|
|
|
//#define LEVEL_CORNERS_LEVELING_ORDER { RF, RB } // 3-Point tramming - Left
|
|
|
|
|
//#define LEVEL_CORNERS_LEVELING_ORDER { LB, RB } // 3-Point tramming - Front
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define LF 1
|
|
|
|
|
#define RF 2
|
|
|
|
|
#define RB 3
|
|
|
|
|
#define LB 4
|
|
|
|
|
constexpr int lco[] = LEVEL_CORNERS_LEVELING_ORDER;
|
|
|
|
|
constexpr bool level_corners_3_points = COUNT(lco) == 2;
|
|
|
|
|
static_assert(level_corners_3_points || COUNT(lco) == 4, "LEVEL_CORNERS_LEVELING_ORDER must have exactly 2 or 4 corners.");
|
|
|
|
|
|
|
|
|
|
constexpr int lcodiff = abs(lco[0] - lco[1]);
|
|
|
|
|
static_assert(COUNT(lco) == 4 || lcodiff == 1 || lcodiff == 3, "The first two LEVEL_CORNERS_LEVELING_ORDER corners must be on the same edge.");
|
|
|
|
|
|
|
|
|
|
constexpr int nr_edge_points = level_corners_3_points ? 3 : 4;
|
|
|
|
|
constexpr int available_points = nr_edge_points + ENABLED(LEVEL_CENTER_TOO);
|
|
|
|
|
constexpr int center_index = TERN(LEVEL_CENTER_TOO, available_points - 1, -1);
|
|
|
|
|
constexpr float inset_lfrb[4] = LEVEL_CORNERS_INSET_LFRB;
|
|
|
|
|
constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1] },
|
|
|
|
|
rb { (X_MAX_BED) - inset_lfrb[2], (Y_MAX_BED) - inset_lfrb[3] };
|
|
|
|
|
|
|
|
|
|
static int8_t bed_corner;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Select next corner coordinates
|
|
|
|
|
*/
|
|
|
|
|
static inline void _lcd_level_bed_corners_get_next_position() {
|
|
|
|
|
|
|
|
|
|
if (level_corners_3_points) {
|
|
|
|
|
if (bed_corner >= available_points) bed_corner = 0; // Above max position -> move back to first corner
|
|
|
|
|
switch (bed_corner) {
|
|
|
|
|
case 0 ... 1:
|
|
|
|
|
// First two corners set explicitly by the configuration
|
|
|
|
|
current_position = lf; // Left front
|
|
|
|
|
switch (lco[bed_corner]) {
|
|
|
|
|
case RF: current_position.x = rb.x; break; // Right Front
|
|
|
|
|
case RB: current_position = rb; break; // Right Back
|
|
|
|
|
case LB: current_position.y = rb.y; break; // Left Back
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
// Determine which edge to probe for 3rd point
|
|
|
|
|
current_position.set(lf.x + (rb.x - lf.x) / 2, lf.y + (rb.y - lf.y) / 2);
|
|
|
|
|
if ((lco[0] == LB && lco[1] == RB) || (lco[0] == RB && lco[1] == LB)) current_position.y = lf.y; // Front Center
|
|
|
|
|
if ((lco[0] == LF && lco[1] == LB) || (lco[0] == LB && lco[1] == LF)) current_position.x = rb.x; // Center Right
|
|
|
|
|
if ((lco[0] == RF && lco[1] == RB) || (lco[0] == RB && lco[1] == RF)) current_position.x = lf.x; // Left Center
|
|
|
|
|
if ((lco[0] == LF && lco[1] == RF) || (lco[0] == RF && lco[1] == LF)) current_position.y = rb.y; // Center Back
|
|
|
|
|
#if DISABLED(LEVEL_CENTER_TOO) && ENABLED(LEVEL_CORNERS_USE_PROBE)
|
|
|
|
|
bed_corner++; // Must increment the count to ensure it resets the loop if the 3rd point is out of tolerance
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
#if ENABLED(LEVEL_CENTER_TOO)
|
|
|
|
|
case 3:
|
|
|
|
|
current_position.set(X_CENTER, Y_CENTER);
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// Four-Corner Bed Tramming with optional center
|
|
|
|
|
if (TERN0(LEVEL_CENTER_TOO, bed_corner == center_index)) {
|
|
|
|
|
current_position.set(X_CENTER, Y_CENTER);
|
|
|
|
|
TERN_(LEVEL_CORNERS_USE_PROBE, good_points--); // Decrement to allow one additional probe point
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
current_position = lf; // Left front
|
|
|
|
|
switch (lco[bed_corner]) {
|
|
|
|
|
case RF: current_position.x = rb.x; break; // Right front
|
|
|
|
|
case RB: current_position = rb; break; // Right rear
|
|
|
|
|
case LB: current_position.y = rb.y; break; // Left rear
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Level corners, starting in the front-left corner.
|
|
|
|
|
*/
|
|
|
|
@ -82,8 +166,37 @@ constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1]
|
|
|
|
|
VALIDATE_POINT(lf.x, Y_CENTER, "left"); VALIDATE_POINT(X_CENTER, lf.y, "front");
|
|
|
|
|
VALIDATE_POINT(rb.x, Y_CENTER, "right"); VALIDATE_POINT(X_CENTER, rb.y, "back");
|
|
|
|
|
|
|
|
|
|
#ifndef PAGE_CONTAINS
|
|
|
|
|
#define PAGE_CONTAINS(...) true
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void _lcd_draw_probing() {
|
|
|
|
|
if (ui.should_draw()) MenuItem_static::draw((LCD_HEIGHT - 1) / 2, GET_TEXT(MSG_PROBING_MESH));
|
|
|
|
|
if (!ui.should_draw()) return;
|
|
|
|
|
|
|
|
|
|
TERN_(HAS_MARLINUI_U8GLIB, ui.set_font(FONT_MENU)); // Set up the font for extra info
|
|
|
|
|
|
|
|
|
|
MenuItem_static::draw(0, GET_TEXT(MSG_PROBING_MESH), SS_INVERT); // "Probing Mesh" heading
|
|
|
|
|
|
|
|
|
|
uint8_t cy = LCD_HEIGHT - 1, y = LCD_ROW_Y(cy);
|
|
|
|
|
|
|
|
|
|
// Display # of good points found vs total needed
|
|
|
|
|
if (PAGE_CONTAINS(y - (MENU_FONT_HEIGHT), y)) {
|
|
|
|
|
SETCURSOR(0, cy);
|
|
|
|
|
lcd_put_u8str_P(GET_TEXT(MSG_LEVEL_CORNERS_GOOD_POINTS));
|
|
|
|
|
lcd_put_u8str(GOOD_POINTS_TO_STR(good_points));
|
|
|
|
|
lcd_put_wchar('/');
|
|
|
|
|
lcd_put_u8str(GOOD_POINTS_TO_STR(nr_edge_points));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--cy;
|
|
|
|
|
y -= MENU_FONT_HEIGHT;
|
|
|
|
|
|
|
|
|
|
// Display the Last Z value
|
|
|
|
|
if (PAGE_CONTAINS(y - (MENU_FONT_HEIGHT), y)) {
|
|
|
|
|
SETCURSOR(0, cy);
|
|
|
|
|
lcd_put_u8str_P(GET_TEXT(MSG_LEVEL_CORNERS_LAST_Z));
|
|
|
|
|
lcd_put_u8str(LAST_Z_TO_STR(last_z));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _lcd_draw_raise() {
|
|
|
|
@ -112,7 +225,7 @@ constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1]
|
|
|
|
|
bool _lcd_level_bed_corners_probe(bool verify=false) {
|
|
|
|
|
if (verify) do_blocking_move_to_z(current_position.z + LEVEL_CORNERS_Z_HOP); // do clearance if needed
|
|
|
|
|
TERN_(BLTOUCH_SLOW_MODE, bltouch.deploy()); // Deploy in LOW SPEED MODE on every probe action
|
|
|
|
|
do_blocking_move_to_z(last_z - LEVEL_CORNERS_PROBE_TOLERANCE, manual_feedrate_mm_s.z); // Move down to lower tolerance
|
|
|
|
|
do_blocking_move_to_z(last_z - LEVEL_CORNERS_PROBE_TOLERANCE, MMM_TO_MMS(Z_PROBE_SPEED_SLOW)); // Move down to lower tolerance
|
|
|
|
|
if (TEST(endstops.trigger_state(), TERN(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, Z_MIN, Z_MIN_PROBE))) { // check if probe triggered
|
|
|
|
|
endstops.hit_on_purpose();
|
|
|
|
|
set_current_from_steppers_for_axis(Z_AXIS);
|
|
|
|
@ -149,25 +262,18 @@ constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _lcd_test_corners() {
|
|
|
|
|
ui.goto_screen(_lcd_draw_probing);
|
|
|
|
|
bed_corner = TERN(LEVEL_CENTER_TOO, 4, 0);
|
|
|
|
|
bed_corner = TERN(LEVEL_CENTER_TOO, center_index, 0);
|
|
|
|
|
last_z = LEVEL_CORNERS_HEIGHT;
|
|
|
|
|
endstops.enable_z_probe(true);
|
|
|
|
|
good_points = 0;
|
|
|
|
|
|
|
|
|
|
ui.goto_screen(_lcd_draw_probing);
|
|
|
|
|
do {
|
|
|
|
|
ui.refresh(LCDVIEW_REDRAW_NOW);
|
|
|
|
|
_lcd_draw_probing(); //update screen with # of good points
|
|
|
|
|
do_blocking_move_to_z(current_position.z + LEVEL_CORNERS_Z_HOP); // clearance
|
|
|
|
|
// Select next corner coordinates
|
|
|
|
|
xy_pos_t plf = lf - probe.offset_xy, prb = rb - probe.offset_xy;
|
|
|
|
|
switch (bed_corner) {
|
|
|
|
|
case 0: current_position = plf; break; // copy xy
|
|
|
|
|
case 1: current_position.x = prb.x; break;
|
|
|
|
|
case 2: current_position.y = prb.y; break;
|
|
|
|
|
case 3: current_position.x = plf.x; break;
|
|
|
|
|
#if ENABLED(LEVEL_CENTER_TOO)
|
|
|
|
|
case 4: current_position.set(X_CENTER - probe.offset_xy.x, Y_CENTER - probe.offset_xy.y); break;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_lcd_level_bed_corners_get_next_position(); // Select next corner coordinates
|
|
|
|
|
current_position -= probe.offset_xy; // Account for probe offsets
|
|
|
|
|
do_blocking_move_to_xy(current_position); // Goto corner
|
|
|
|
|
|
|
|
|
|
if (!_lcd_level_bed_corners_probe()) { // Probe down to tolerance
|
|
|
|
@ -185,10 +291,10 @@ constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1]
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bed_corner != 4) good_points++; // ignore center
|
|
|
|
|
if (bed_corner != center_index) good_points++; // ignore center
|
|
|
|
|
if (++bed_corner > 3) bed_corner = 0;
|
|
|
|
|
|
|
|
|
|
} while (good_points < 4); // loop until all corners whitin tolerance
|
|
|
|
|
} while (good_points < nr_edge_points); // loop until all points within tolerance
|
|
|
|
|
|
|
|
|
|
ui.goto_screen(_lcd_draw_level_prompt); // prompt for bed leveling
|
|
|
|
|
ui.set_selection(true);
|
|
|
|
@ -198,18 +304,13 @@ constexpr xy_pos_t lf { (X_MIN_BED) + inset_lfrb[0], (Y_MIN_BED) + inset_lfrb[1]
|
|
|
|
|
|
|
|
|
|
static inline void _lcd_goto_next_corner() {
|
|
|
|
|
line_to_z(LEVEL_CORNERS_Z_HOP);
|
|
|
|
|
switch (bed_corner) {
|
|
|
|
|
case 0: current_position = lf; break; // copy xy
|
|
|
|
|
case 1: current_position.x = rb.x; break;
|
|
|
|
|
case 2: current_position.y = rb.y; break;
|
|
|
|
|
case 3: current_position.x = lf.x; break;
|
|
|
|
|
#if ENABLED(LEVEL_CENTER_TOO)
|
|
|
|
|
case 4: current_position.set(X_CENTER, Y_CENTER); break;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Select next corner coordinates
|
|
|
|
|
_lcd_level_bed_corners_get_next_position();
|
|
|
|
|
|
|
|
|
|
line_to_current_position(manual_feedrate_mm_s.x);
|
|
|
|
|
line_to_z(LEVEL_CORNERS_HEIGHT);
|
|
|
|
|
if (++bed_corner > 3 + ENABLED(LEVEL_CENTER_TOO)) bed_corner = 0;
|
|
|
|
|
if (++bed_corner >= available_points) bed_corner = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // !LEVEL_CORNERS_USE_PROBE
|
|
|
|
|