diff --git a/.travis.yml b/.travis.yml
index 213b799b206ed2f783f145e510d9a5bf09214495..46b3560b5cf2ae44795c9243d4c66aed26191ca2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -73,11 +73,17 @@ script:
- opt_set ABL_GRID_POINTS_Y 16
- build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
#
- # Test a simple build of AUTO_BED_LEVELING_UBL
+ # Test a probeless build of AUTO_BED_LEVELING_UBL
#
- restore_configs
- - opt_enable AUTO_BED_LEVELING_UBL UBL_G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT BLTOUCH EEPROM_SETTINGS G3D_PANEL
- - opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_ZPROBE_OFFSET
+ - opt_enable AUTO_BED_LEVELING_UBL UBL_G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT EEPROM_SETTINGS G3D_PANEL
+ - opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING
+ - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
+ #
+ # ...and with a probe
+ #
+ - opt_enable BLTOUCH
+ - opt_enable_adv BABYSTEP_ZPROBE_OFFSET
- build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
#
# Test a Sled Z Probe
diff --git a/Marlin/src/feature/bedlevel/ubl/G26_Mesh_Validation_Tool.cpp b/Marlin/src/feature/bedlevel/ubl/G26_Mesh_Validation_Tool.cpp
index bab31d8a68150c80ee6ff4e792bb0be1974de534..19d1a1b942a6759cc706d128bd7291fae6656cb0 100644
--- a/Marlin/src/feature/bedlevel/ubl/G26_Mesh_Validation_Tool.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/G26_Mesh_Validation_Tool.cpp
@@ -135,17 +135,6 @@
extern char lcd_status_message[];
#endif
-// Remove this if all is well with Teensy compile:
-#if 0
-#if AVR_AT90USB1286_FAMILY // Teensyduino & Printrboard IDE extensions have compile errors without this
- inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); }
- inline void set_current_to_destination() { COPY(current_position, destination); }
-#else
- extern void sync_plan_position_e();
- extern void set_current_to_destination();
-#endif
-#endif
-
#if ENABLED(NEWPANEL)
void lcd_setstatusPGM(const char* const message, const int8_t level);
void chirp_at_user();
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h
index 3082a77b03463e24440a8f6d292ca63c9534ca4d..8791415a46dc0747f77ac4214e6504a1a7d19d5e 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl.h
+++ b/Marlin/src/feature/bedlevel/ubl/ubl.h
@@ -85,13 +85,16 @@ class unified_bed_leveling {
g29_phase_value,
g29_repetition_cnt,
g29_storage_slot,
- g29_map_type,
- g29_grid_size;
+ g29_map_type;
static bool g29_c_flag, g29_x_flag, g29_y_flag;
static float g29_x_pos, g29_y_pos,
g29_card_thickness,
g29_constant;
+ #if HAS_BED_PROBE
+ static int g29_grid_size;
+ #endif
+
#if ENABLED(UBL_G26_MESH_VALIDATION)
static float g26_extrusion_multiplier,
g26_retraction_multiplier,
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
index 8449050285bda5503646e101eb010173dd014bfe..1dd08992814e95f0bb1e21320422cd035004a35e 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
@@ -65,8 +65,7 @@
unified_bed_leveling::g29_phase_value,
unified_bed_leveling::g29_repetition_cnt,
unified_bed_leveling::g29_storage_slot = 0,
- unified_bed_leveling::g29_map_type,
- unified_bed_leveling::g29_grid_size;
+ unified_bed_leveling::g29_map_type;
bool unified_bed_leveling::g29_c_flag,
unified_bed_leveling::g29_x_flag,
unified_bed_leveling::g29_y_flag;
@@ -75,6 +74,10 @@
unified_bed_leveling::g29_card_thickness = 0.0,
unified_bed_leveling::g29_constant = 0.0;
+ #if HAS_BED_PROBE
+ int unified_bed_leveling::g29_grid_size;
+ #endif
+
/**
* G29: Unified Bed Leveling by Roxy
*
@@ -310,6 +313,8 @@
return;
}
+ if (g29_parameter_parsing()) return; // abort if parsing the simple parameters causes a problem,
+
// Check for commands that require the printer to be homed
if (axis_unhomed_error()) {
const int8_t p_val = parser.intval('P', -1);
@@ -317,8 +322,6 @@
gcode.home_all_axes();
}
- if (g29_parameter_parsing()) return; // abort if parsing the simple parameters causes a problem,
-
// Invalidate Mesh Points. This command is a little bit asymmetrical because
// it directly specifies the repetition count and does not use the 'R' parameter.
if (parser.seen('I')) {
@@ -381,40 +384,44 @@
}
}
- if (parser.seen('J')) {
- if (g29_grid_size) { // if not 0 it is a normal n x n grid being probed
- save_ubl_active_state_and_disable();
- tilt_mesh_based_on_probed_grid(parser.seen('T'));
- restore_ubl_active_state_and_leave();
- }
- else { // grid_size == 0 : A 3-Point leveling has been requested
- float z3, z2, z1 = probe_pt(LOGICAL_X_POSITION(UBL_PROBE_PT_1_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_1_Y), false, g29_verbose_level);
- if (!isnan(z1)) {
- z2 = probe_pt(LOGICAL_X_POSITION(UBL_PROBE_PT_2_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_2_Y), false, g29_verbose_level);
- if (!isnan(z2))
- z3 = probe_pt(LOGICAL_X_POSITION(UBL_PROBE_PT_3_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_3_Y), true, g29_verbose_level);
- }
+ #if HAS_BED_PROBE
- if (isnan(z1) || isnan(z2) || isnan(z3)) { // probe_pt will return NAN if unreachable
- SERIAL_ERROR_START();
- SERIAL_ERRORLNPGM("Attempt to probe off the bed.");
- goto LEAVE;
+ if (parser.seen('J')) {
+ if (g29_grid_size) { // if not 0 it is a normal n x n grid being probed
+ save_ubl_active_state_and_disable();
+ tilt_mesh_based_on_probed_grid(parser.seen('T'));
+ restore_ubl_active_state_and_leave();
}
+ else { // grid_size == 0 : A 3-Point leveling has been requested
+ float z3, z2, z1 = probe_pt(LOGICAL_X_POSITION(UBL_PROBE_PT_1_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_1_Y), false, g29_verbose_level);
+ if (!isnan(z1)) {
+ z2 = probe_pt(LOGICAL_X_POSITION(UBL_PROBE_PT_2_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_2_Y), false, g29_verbose_level);
+ if (!isnan(z2))
+ z3 = probe_pt(LOGICAL_X_POSITION(UBL_PROBE_PT_3_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_3_Y), true, g29_verbose_level);
+ }
- // Adjust z1, z2, z3 by the Mesh Height at these points. Just because they're non-zero
- // doesn't mean the Mesh is tilted! (Compensate each probe point by what the Mesh says
- // its height is.)
+ if (isnan(z1) || isnan(z2) || isnan(z3)) { // probe_pt will return NAN if unreachable
+ SERIAL_ERROR_START();
+ SERIAL_ERRORLNPGM("Attempt to probe off the bed.");
+ goto LEAVE;
+ }
- save_ubl_active_state_and_disable();
- z1 -= get_z_correction(LOGICAL_X_POSITION(UBL_PROBE_PT_1_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_1_Y)) /* + zprobe_zoffset */ ;
- z2 -= get_z_correction(LOGICAL_X_POSITION(UBL_PROBE_PT_2_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_2_Y)) /* + zprobe_zoffset */ ;
- z3 -= get_z_correction(LOGICAL_X_POSITION(UBL_PROBE_PT_3_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_3_Y)) /* + zprobe_zoffset */ ;
+ // Adjust z1, z2, z3 by the Mesh Height at these points. Just because they're non-zero
+ // doesn't mean the Mesh is tilted! (Compensate each probe point by what the Mesh says
+ // its height is.)
- do_blocking_move_to_xy(0.5 * (UBL_MESH_MAX_X - (UBL_MESH_MIN_X)), 0.5 * (UBL_MESH_MAX_Y - (UBL_MESH_MIN_Y)));
- tilt_mesh_based_on_3pts(z1, z2, z3);
- restore_ubl_active_state_and_leave();
+ save_ubl_active_state_and_disable();
+ z1 -= get_z_correction(LOGICAL_X_POSITION(UBL_PROBE_PT_1_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_1_Y)) /* + zprobe_zoffset */ ;
+ z2 -= get_z_correction(LOGICAL_X_POSITION(UBL_PROBE_PT_2_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_2_Y)) /* + zprobe_zoffset */ ;
+ z3 -= get_z_correction(LOGICAL_X_POSITION(UBL_PROBE_PT_3_X), LOGICAL_Y_POSITION(UBL_PROBE_PT_3_Y)) /* + zprobe_zoffset */ ;
+
+ do_blocking_move_to_xy(0.5 * (UBL_MESH_MAX_X - (UBL_MESH_MIN_X)), 0.5 * (UBL_MESH_MAX_Y - (UBL_MESH_MIN_Y)));
+ tilt_mesh_based_on_3pts(z1, z2, z3);
+ restore_ubl_active_state_and_leave();
+ }
}
- }
+
+ #endif // HAS_BED_PROBE
if (parser.seen('P')) {
if (WITHIN(g29_phase_value, 0, 1) && state.storage_slot == -1) {
@@ -431,23 +438,27 @@
SERIAL_PROTOCOLLNPGM("Mesh zeroed.");
break;
- case 1:
- //
- // Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
- //
- if (!parser.seen('C')) {
- invalidate();
- SERIAL_PROTOCOLLNPGM("Mesh invalidated. Probing mesh.");
- }
- if (g29_verbose_level > 1) {
- SERIAL_PROTOCOLPAIR("Probing Mesh Points Closest to (", g29_x_pos);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL(g29_y_pos);
- SERIAL_PROTOCOLLNPGM(").\n");
- }
- probe_entire_mesh(g29_x_pos + X_PROBE_OFFSET_FROM_EXTRUDER, g29_y_pos + Y_PROBE_OFFSET_FROM_EXTRUDER,
- parser.seen('T'), parser.seen('E'), parser.seen('U'));
- break;
+ #if HAS_BED_PROBE
+
+ case 1:
+ //
+ // Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
+ //
+ if (!parser.seen('C')) {
+ invalidate();
+ SERIAL_PROTOCOLLNPGM("Mesh invalidated. Probing mesh.");
+ }
+ if (g29_verbose_level > 1) {
+ SERIAL_PROTOCOLPAIR("Probing Mesh Points Closest to (", g29_x_pos);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL(g29_y_pos);
+ SERIAL_PROTOCOLLNPGM(").\n");
+ }
+ probe_entire_mesh(g29_x_pos + X_PROBE_OFFSET_FROM_EXTRUDER, g29_y_pos + Y_PROBE_OFFSET_FROM_EXTRUDER,
+ parser.seen('T'), parser.seen('E'), parser.seen('U'));
+ break;
+
+ #endif
case 2: {
#if ENABLED(NEWPANEL)
@@ -776,161 +787,166 @@
z_values[x][y] += g29_constant;
}
- /**
- * Probe all invalidated locations of the mesh that can be reached by the probe.
- * This attempts to fill in locations closest to the nozzle's start location first.
- */
- void unified_bed_leveling::probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool close_or_far) {
- mesh_index_pair location;
-
- has_control_of_lcd_panel = true;
- save_ubl_active_state_and_disable(); // we don't do bed level correction because we want the raw data when we probe
- DEPLOY_PROBE();
-
- uint16_t max_iterations = GRID_MAX_POINTS;
+ #if HAS_BED_PROBE
- do {
- #if ENABLED(NEWPANEL)
- if (ubl_lcd_clicked()) {
- SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.\n");
- lcd_quick_feedback();
- STOW_PROBE();
- while (ubl_lcd_clicked()) idle();
- has_control_of_lcd_panel = false;
- restore_ubl_active_state_and_leave();
- safe_delay(50); // Debounce the Encoder wheel
- return;
- }
- #endif
-
- location = find_closest_mesh_point_of_type(INVALID, lx, ly, USE_PROBE_AS_REFERENCE, NULL, close_or_far);
-
- if (location.x_index >= 0) { // mesh point found and is reachable by probe
- const float rawx = mesh_index_to_xpos(location.x_index),
- rawy = mesh_index_to_ypos(location.y_index);
+ /**
+ * Probe all invalidated locations of the mesh that can be reached by the probe.
+ * This attempts to fill in locations closest to the nozzle's start location first.
+ */
+ void unified_bed_leveling::probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool close_or_far) {
+ mesh_index_pair location;
- const float measured_z = probe_pt(LOGICAL_X_POSITION(rawx), LOGICAL_Y_POSITION(rawy), stow_probe, g29_verbose_level); // TODO: Needs error handling
- z_values[location.x_index][location.y_index] = measured_z;
- }
+ has_control_of_lcd_panel = true;
+ save_ubl_active_state_and_disable(); // we don't do bed level correction because we want the raw data when we probe
+ DEPLOY_PROBE();
- if (do_ubl_mesh_map) display_map(g29_map_type);
+ uint16_t max_iterations = GRID_MAX_POINTS;
- } while (location.x_index >= 0 && --max_iterations);
+ do {
+ #if ENABLED(NEWPANEL)
+ if (ubl_lcd_clicked()) {
+ SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.\n");
+ lcd_quick_feedback();
+ STOW_PROBE();
+ while (ubl_lcd_clicked()) idle();
+ has_control_of_lcd_panel = false;
+ restore_ubl_active_state_and_leave();
+ safe_delay(50); // Debounce the Encoder wheel
+ return;
+ }
+ #endif
- STOW_PROBE();
- restore_ubl_active_state_and_leave();
+ location = find_closest_mesh_point_of_type(INVALID, lx, ly, USE_PROBE_AS_REFERENCE, NULL, close_or_far);
- do_blocking_move_to_xy(
- constrain(lx - (X_PROBE_OFFSET_FROM_EXTRUDER), UBL_MESH_MIN_X, UBL_MESH_MAX_X),
- constrain(ly - (Y_PROBE_OFFSET_FROM_EXTRUDER), UBL_MESH_MIN_Y, UBL_MESH_MAX_Y)
- );
- }
+ if (location.x_index >= 0) { // mesh point found and is reachable by probe
+ const float rawx = mesh_index_to_xpos(location.x_index),
+ rawy = mesh_index_to_ypos(location.y_index);
- void unified_bed_leveling::tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3) {
- matrix_3x3 rotation;
- vector_3 v1 = vector_3( (UBL_PROBE_PT_1_X - UBL_PROBE_PT_2_X),
- (UBL_PROBE_PT_1_Y - UBL_PROBE_PT_2_Y),
- (z1 - z2) ),
+ const float measured_z = probe_pt(LOGICAL_X_POSITION(rawx), LOGICAL_Y_POSITION(rawy), stow_probe, g29_verbose_level); // TODO: Needs error handling
+ z_values[location.x_index][location.y_index] = measured_z;
+ }
- v2 = vector_3( (UBL_PROBE_PT_3_X - UBL_PROBE_PT_2_X),
- (UBL_PROBE_PT_3_Y - UBL_PROBE_PT_2_Y),
- (z3 - z2) ),
+ if (do_ubl_mesh_map) display_map(g29_map_type);
- normal = vector_3::cross(v1, v2);
+ } while (location.x_index >= 0 && --max_iterations);
- normal = normal.get_normal();
+ STOW_PROBE();
+ restore_ubl_active_state_and_leave();
- /**
- * This vector is normal to the tilted plane.
- * However, we don't know its direction. We need it to point up. So if
- * Z is negative, we need to invert the sign of all components of the vector
- */
- if (normal.z < 0.0) {
- normal.x = -normal.x;
- normal.y = -normal.y;
- normal.z = -normal.z;
+ do_blocking_move_to_xy(
+ constrain(lx - (X_PROBE_OFFSET_FROM_EXTRUDER), UBL_MESH_MIN_X, UBL_MESH_MAX_X),
+ constrain(ly - (Y_PROBE_OFFSET_FROM_EXTRUDER), UBL_MESH_MIN_Y, UBL_MESH_MAX_Y)
+ );
}
- rotation = matrix_3x3::create_look_at(vector_3(normal.x, normal.y, 1));
-
- if (g29_verbose_level > 2) {
- SERIAL_ECHOPGM("bed plane normal = [");
- SERIAL_PROTOCOL_F(normal.x, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(normal.y, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(normal.z, 7);
- SERIAL_ECHOLNPGM("]");
- rotation.debug(PSTR("rotation matrix:"));
- }
+ void unified_bed_leveling::tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3) {
+ matrix_3x3 rotation;
+ vector_3 v1 = vector_3( (UBL_PROBE_PT_1_X - UBL_PROBE_PT_2_X),
+ (UBL_PROBE_PT_1_Y - UBL_PROBE_PT_2_Y),
+ (z1 - z2) ),
+
+ v2 = vector_3( (UBL_PROBE_PT_3_X - UBL_PROBE_PT_2_X),
+ (UBL_PROBE_PT_3_Y - UBL_PROBE_PT_2_Y),
+ (z3 - z2) ),
+
+ normal = vector_3::cross(v1, v2);
+
+ normal = normal.get_normal();
+
+ /**
+ * This vector is normal to the tilted plane.
+ * However, we don't know its direction. We need it to point up. So if
+ * Z is negative, we need to invert the sign of all components of the vector
+ */
+ if (normal.z < 0.0) {
+ normal.x = -normal.x;
+ normal.y = -normal.y;
+ normal.z = -normal.z;
+ }
- //
- // All of 3 of these points should give us the same d constant
- //
+ rotation = matrix_3x3::create_look_at(vector_3(normal.x, normal.y, 1));
- float t = normal.x * (UBL_PROBE_PT_1_X) + normal.y * (UBL_PROBE_PT_1_Y),
- d = t + normal.z * z1;
+ if (g29_verbose_level > 2) {
+ SERIAL_ECHOPGM("bed plane normal = [");
+ SERIAL_PROTOCOL_F(normal.x, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(normal.y, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(normal.z, 7);
+ SERIAL_ECHOLNPGM("]");
+ rotation.debug(PSTR("rotation matrix:"));
+ }
- if (g29_verbose_level>2) {
- SERIAL_ECHOPGM("D constant: ");
- SERIAL_PROTOCOL_F(d, 7);
- SERIAL_ECHOLNPGM(" ");
- }
+ //
+ // All of 3 of these points should give us the same d constant
+ //
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- SERIAL_ECHOPGM("d from 1st point: ");
- SERIAL_ECHO_F(d, 6);
- SERIAL_EOL();
- t = normal.x * (UBL_PROBE_PT_2_X) + normal.y * (UBL_PROBE_PT_2_Y);
- d = t + normal.z * z2;
- SERIAL_ECHOPGM("d from 2nd point: ");
- SERIAL_ECHO_F(d, 6);
- SERIAL_EOL();
- t = normal.x * (UBL_PROBE_PT_3_X) + normal.y * (UBL_PROBE_PT_3_Y);
- d = t + normal.z * z3;
- SERIAL_ECHOPGM("d from 3rd point: ");
- SERIAL_ECHO_F(d, 6);
- SERIAL_EOL();
+ float t = normal.x * (UBL_PROBE_PT_1_X) + normal.y * (UBL_PROBE_PT_1_Y),
+ d = t + normal.z * z1;
+
+ if (g29_verbose_level>2) {
+ SERIAL_ECHOPGM("D constant: ");
+ SERIAL_PROTOCOL_F(d, 7);
+ SERIAL_ECHOLNPGM(" ");
}
- #endif
- for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
- for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
- float x_tmp = mesh_index_to_xpos(i),
- y_tmp = mesh_index_to_ypos(j),
- z_tmp = z_values[i][j];
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- SERIAL_ECHOPGM("before rotation = [");
- SERIAL_PROTOCOL_F(x_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(y_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(z_tmp, 7);
- SERIAL_ECHOPGM("] ---> ");
- safe_delay(20);
- }
- #endif
- apply_rotation_xyz(rotation, x_tmp, y_tmp, z_tmp);
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- SERIAL_ECHOPGM("after rotation = [");
- SERIAL_PROTOCOL_F(x_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(y_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(z_tmp, 7);
- SERIAL_ECHOLNPGM("]");
- safe_delay(55);
- }
- #endif
- z_values[i][j] += z_tmp - d;
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ SERIAL_ECHOPGM("d from 1st point: ");
+ SERIAL_ECHO_F(d, 6);
+ SERIAL_EOL();
+ t = normal.x * (UBL_PROBE_PT_2_X) + normal.y * (UBL_PROBE_PT_2_Y);
+ d = t + normal.z * z2;
+ SERIAL_ECHOPGM("d from 2nd point: ");
+ SERIAL_ECHO_F(d, 6);
+ SERIAL_EOL();
+ t = normal.x * (UBL_PROBE_PT_3_X) + normal.y * (UBL_PROBE_PT_3_Y);
+ d = t + normal.z * z3;
+ SERIAL_ECHOPGM("d from 3rd point: ");
+ SERIAL_ECHO_F(d, 6);
+ SERIAL_EOL();
+ }
+ #endif
+
+ for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
+ for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
+ float x_tmp = mesh_index_to_xpos(i),
+ y_tmp = mesh_index_to_ypos(j),
+ z_tmp = z_values[i][j];
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ SERIAL_ECHOPGM("before rotation = [");
+ SERIAL_PROTOCOL_F(x_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(y_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(z_tmp, 7);
+ SERIAL_ECHOPGM("] ---> ");
+ safe_delay(20);
+ }
+ #endif
+ apply_rotation_xyz(rotation, x_tmp, y_tmp, z_tmp);
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ SERIAL_ECHOPGM("after rotation = [");
+ SERIAL_PROTOCOL_F(x_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(y_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(z_tmp, 7);
+ SERIAL_ECHOLNPGM("]");
+ safe_delay(55);
+ }
+ #endif
+ z_values[i][j] += z_tmp - d;
+ }
}
}
- }
+
+ #endif // HAS_BED_PROBE
#if ENABLED(NEWPANEL)
+
float unified_bed_leveling::measure_point_with_encoder() {
while (ubl_lcd_clicked()) delay(50); // wait for user to release encoder wheel
@@ -1080,7 +1096,8 @@
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
do_blocking_move_to_xy(lx, ly);
}
- #endif
+
+ #endif // NEWPANEL
bool unified_bed_leveling::g29_parameter_parsing() {
bool err_flag = false;
@@ -1114,19 +1131,34 @@
}
if (parser.seen('P')) {
- g29_phase_value = parser.value_int();
- if (!WITHIN(g29_phase_value, 0, 6)) {
- SERIAL_PROTOCOLLNPGM("?(P)hase value invalid (0-6).\n");
- err_flag = true;
- }
+ const int pv = parser.value_int();
+ #if !HAS_BED_PROBE
+ if (pv == 1) {
+ SERIAL_PROTOCOLLNPGM("G29 P1 requires a probe.\n");
+ err_flag = true;
+ }
+ else
+ #endif
+ {
+ g29_phase_value = pv;
+ if (!WITHIN(g29_phase_value, 0, 6)) {
+ SERIAL_PROTOCOLLNPGM("?(P)hase value invalid (0-6).\n");
+ err_flag = true;
+ }
+ }
}
if (parser.seen('J')) {
- g29_grid_size = parser.has_value() ? parser.value_int() : 0;
- if (g29_grid_size && !WITHIN(g29_grid_size, 2, 9)) {
- SERIAL_PROTOCOLLNPGM("?Invalid grid size (J) specified (2-9).\n");
+ #if HAS_BED_PROBE
+ g29_grid_size = parser.has_value() ? parser.value_int() : 0;
+ if (g29_grid_size && !WITHIN(g29_grid_size, 2, 9)) {
+ SERIAL_PROTOCOLLNPGM("?Invalid grid size (J) specified (2-9).\n");
+ err_flag = true;
+ }
+ #else
+ SERIAL_PROTOCOLLNPGM("G29 J action requires a probe.\n");
err_flag = true;
- }
+ #endif
}
if (g29_x_flag != g29_y_flag) {
@@ -1624,128 +1656,66 @@
}
}
- void unified_bed_leveling::tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map) {
- constexpr int16_t x_min = max(MIN_PROBE_X, UBL_MESH_MIN_X),
- x_max = min(MAX_PROBE_X, UBL_MESH_MAX_X),
- y_min = max(MIN_PROBE_Y, UBL_MESH_MIN_Y),
- y_max = min(MAX_PROBE_Y, UBL_MESH_MAX_Y);
-
- const float dx = float(x_max - x_min) / (g29_grid_size - 1.0),
- dy = float(y_max - y_min) / (g29_grid_size - 1.0);
-
- struct linear_fit_data lsf_results;
- incremental_LSF_reset(&lsf_results);
-
- bool zig_zag = false;
- for (uint8_t ix = 0; ix < g29_grid_size; ix++) {
- const float x = float(x_min) + ix * dx;
- for (int8_t iy = 0; iy < g29_grid_size; iy++) {
- const float y = float(y_min) + dy * (zig_zag ? g29_grid_size - 1 - iy : iy);
- float measured_z = probe_pt(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y), parser.seen('E'), g29_verbose_level); // TODO: Needs error handling
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- SERIAL_CHAR('(');
- SERIAL_PROTOCOL_F(x, 7);
- SERIAL_CHAR(',');
- SERIAL_PROTOCOL_F(y, 7);
- SERIAL_ECHOPGM(") logical: ");
- SERIAL_CHAR('(');
- SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(x), 7);
- SERIAL_CHAR(',');
- SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(y), 7);
- SERIAL_ECHOPGM(") measured: ");
- SERIAL_PROTOCOL_F(measured_z, 7);
- SERIAL_ECHOPGM(" correction: ");
- SERIAL_PROTOCOL_F(get_z_correction(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y)), 7);
- }
- #endif
+ #if HAS_BED_PROBE
- measured_z -= get_z_correction(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y)) /* + zprobe_zoffset */ ;
-
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- SERIAL_ECHOPGM(" final >>>---> ");
- SERIAL_PROTOCOL_F(measured_z, 7);
- SERIAL_EOL();
- }
- #endif
-
- incremental_LSF(&lsf_results, x, y, measured_z);
- }
-
- zig_zag ^= true;
- }
-
- if (finish_incremental_LSF(&lsf_results)) {
- SERIAL_ECHOPGM("Could not complete LSF!");
- return;
- }
+ void unified_bed_leveling::tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map) {
+ constexpr int16_t x_min = max(MIN_PROBE_X, UBL_MESH_MIN_X),
+ x_max = min(MAX_PROBE_X, UBL_MESH_MAX_X),
+ y_min = max(MIN_PROBE_Y, UBL_MESH_MIN_Y),
+ y_max = min(MAX_PROBE_Y, UBL_MESH_MAX_Y);
- if (g29_verbose_level > 3) {
- SERIAL_ECHOPGM("LSF Results A=");
- SERIAL_PROTOCOL_F(lsf_results.A, 7);
- SERIAL_ECHOPGM(" B=");
- SERIAL_PROTOCOL_F(lsf_results.B, 7);
- SERIAL_ECHOPGM(" D=");
- SERIAL_PROTOCOL_F(lsf_results.D, 7);
- SERIAL_EOL();
- }
+ const float dx = float(x_max - x_min) / (g29_grid_size - 1.0),
+ dy = float(y_max - y_min) / (g29_grid_size - 1.0);
- vector_3 normal = vector_3(lsf_results.A, lsf_results.B, 1.0000).get_normal();
+ struct linear_fit_data lsf_results;
+ incremental_LSF_reset(&lsf_results);
+
+ bool zig_zag = false;
+ for (uint8_t ix = 0; ix < g29_grid_size; ix++) {
+ const float x = float(x_min) + ix * dx;
+ for (int8_t iy = 0; iy < g29_grid_size; iy++) {
+ const float y = float(y_min) + dy * (zig_zag ? g29_grid_size - 1 - iy : iy);
+ float measured_z = probe_pt(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y), parser.seen('E'), g29_verbose_level); // TODO: Needs error handling
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ SERIAL_CHAR('(');
+ SERIAL_PROTOCOL_F(x, 7);
+ SERIAL_CHAR(',');
+ SERIAL_PROTOCOL_F(y, 7);
+ SERIAL_ECHOPGM(") logical: ");
+ SERIAL_CHAR('(');
+ SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(x), 7);
+ SERIAL_CHAR(',');
+ SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(y), 7);
+ SERIAL_ECHOPGM(") measured: ");
+ SERIAL_PROTOCOL_F(measured_z, 7);
+ SERIAL_ECHOPGM(" correction: ");
+ SERIAL_PROTOCOL_F(get_z_correction(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y)), 7);
+ }
+ #endif
- if (g29_verbose_level > 2) {
- SERIAL_ECHOPGM("bed plane normal = [");
- SERIAL_PROTOCOL_F(normal.x, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(normal.y, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(normal.z, 7);
- SERIAL_ECHOLNPGM("]");
- }
+ measured_z -= get_z_correction(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y)) /* + zprobe_zoffset */ ;
- matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1));
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ SERIAL_ECHOPGM(" final >>>---> ");
+ SERIAL_PROTOCOL_F(measured_z, 7);
+ SERIAL_EOL();
+ }
+ #endif
- for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
- for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
- float x_tmp = mesh_index_to_xpos(i),
- y_tmp = mesh_index_to_ypos(j),
- z_tmp = z_values[i][j];
-
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- SERIAL_ECHOPGM("before rotation = [");
- SERIAL_PROTOCOL_F(x_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(y_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(z_tmp, 7);
- SERIAL_ECHOPGM("] ---> ");
- safe_delay(20);
- }
- #endif
+ incremental_LSF(&lsf_results, x, y, measured_z);
+ }
- apply_rotation_xyz(rotation, x_tmp, y_tmp, z_tmp);
-
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- SERIAL_ECHOPGM("after rotation = [");
- SERIAL_PROTOCOL_F(x_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(y_tmp, 7);
- SERIAL_PROTOCOLCHAR(',');
- SERIAL_PROTOCOL_F(z_tmp, 7);
- SERIAL_ECHOLNPGM("]");
- safe_delay(55);
- }
- #endif
+ zig_zag ^= true;
+ }
- z_values[i][j] += z_tmp - lsf_results.D;
+ if (finish_incremental_LSF(&lsf_results)) {
+ SERIAL_ECHOPGM("Could not complete LSF!");
+ return;
}
- }
- #if ENABLED(DEBUG_LEVELING_FEATURE)
- if (DEBUGGING(LEVELING)) {
- rotation.debug(PSTR("rotation matrix:"));
+ if (g29_verbose_level > 3) {
SERIAL_ECHOPGM("LSF Results A=");
SERIAL_PROTOCOL_F(lsf_results.A, 7);
SERIAL_ECHOPGM(" B=");
@@ -1753,21 +1723,87 @@
SERIAL_ECHOPGM(" D=");
SERIAL_PROTOCOL_F(lsf_results.D, 7);
SERIAL_EOL();
- safe_delay(55);
+ }
+ vector_3 normal = vector_3(lsf_results.A, lsf_results.B, 1.0000).get_normal();
+
+ if (g29_verbose_level > 2) {
SERIAL_ECHOPGM("bed plane normal = [");
SERIAL_PROTOCOL_F(normal.x, 7);
SERIAL_PROTOCOLCHAR(',');
SERIAL_PROTOCOL_F(normal.y, 7);
SERIAL_PROTOCOLCHAR(',');
SERIAL_PROTOCOL_F(normal.z, 7);
- SERIAL_ECHOPGM("]\n");
- SERIAL_EOL();
+ SERIAL_ECHOLNPGM("]");
}
- #endif
- if (do_ubl_mesh_map) display_map(g29_map_type);
- }
+ matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1));
+
+ for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
+ for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
+ float x_tmp = mesh_index_to_xpos(i),
+ y_tmp = mesh_index_to_ypos(j),
+ z_tmp = z_values[i][j];
+
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ SERIAL_ECHOPGM("before rotation = [");
+ SERIAL_PROTOCOL_F(x_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(y_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(z_tmp, 7);
+ SERIAL_ECHOPGM("] ---> ");
+ safe_delay(20);
+ }
+ #endif
+
+ apply_rotation_xyz(rotation, x_tmp, y_tmp, z_tmp);
+
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ SERIAL_ECHOPGM("after rotation = [");
+ SERIAL_PROTOCOL_F(x_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(y_tmp, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(z_tmp, 7);
+ SERIAL_ECHOLNPGM("]");
+ safe_delay(55);
+ }
+ #endif
+
+ z_values[i][j] += z_tmp - lsf_results.D;
+ }
+ }
+
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ if (DEBUGGING(LEVELING)) {
+ rotation.debug(PSTR("rotation matrix:"));
+ SERIAL_ECHOPGM("LSF Results A=");
+ SERIAL_PROTOCOL_F(lsf_results.A, 7);
+ SERIAL_ECHOPGM(" B=");
+ SERIAL_PROTOCOL_F(lsf_results.B, 7);
+ SERIAL_ECHOPGM(" D=");
+ SERIAL_PROTOCOL_F(lsf_results.D, 7);
+ SERIAL_EOL();
+ safe_delay(55);
+
+ SERIAL_ECHOPGM("bed plane normal = [");
+ SERIAL_PROTOCOL_F(normal.x, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(normal.y, 7);
+ SERIAL_PROTOCOLCHAR(',');
+ SERIAL_PROTOCOL_F(normal.z, 7);
+ SERIAL_ECHOPGM("]\n");
+ SERIAL_EOL();
+ }
+ #endif
+
+ if (do_ubl_mesh_map) display_map(g29_map_type);
+ }
+
+ #endif // HAS_BED_PROBE
#if ENABLED(UBL_G29_P31)
void unified_bed_leveling::smart_fill_wlsf(const float &weight_factor) {
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index e3b430f6a30565fec57c9151d3d4e4c65a5ba031..326d30b947d57366781d12725da43e7e6c575891 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -647,9 +647,7 @@ static_assert(1 >= 0
/**
* Require some kind of probe for bed leveling and probe testing
*/
- #if ENABLED(AUTO_BED_LEVELING_UBL)
- #error "Unified Bed Leveling requires a probe: FIX_MOUNTED_PROBE, BLTOUCH, SOLENOID_PROBE, Z_PROBE_ALLEN_KEY, Z_PROBE_SLED, or Z Servo."
- #elif HAS_ABL
+ #if HAS_ABL && DISABLED(AUTO_BED_LEVELING_UBL)
#error "Auto Bed Leveling requires one of these: PROBE_MANUALLY, FIX_MOUNTED_PROBE, BLTOUCH, SOLENOID_PROBE, Z_PROBE_ALLEN_KEY, Z_PROBE_SLED, or a Z Servo."
#endif