|
|
|
@ -125,7 +125,10 @@
|
|
|
|
|
* O Map * Display the Mesh Map Topology.
|
|
|
|
|
* The parameter can be specified alone (ie. G29 O) or in combination with many of the
|
|
|
|
|
* other commands. The Mesh Map option works with all of the Phase
|
|
|
|
|
* commands (ie. G29 P4 R 5 X 50 Y100 C -.1 O)
|
|
|
|
|
* commands (ie. G29 P4 R 5 X 50 Y100 C -.1 O) The Map parameter can also of a Map Type
|
|
|
|
|
* specified. A map type of 0 is the default is user readable. A map type of 1 can
|
|
|
|
|
* be specified and is suitable to Cut & Paste into Excel to allow graphing of the user's
|
|
|
|
|
* mesh.
|
|
|
|
|
*
|
|
|
|
|
* N No Home G29 normally insists that a G28 has been performed. You can over rule this with an
|
|
|
|
|
* N option. In general, you should not do this. This can only be done safely with
|
|
|
|
@ -250,6 +253,10 @@
|
|
|
|
|
*
|
|
|
|
|
* T 3-Point Perform a 3 Point Bed Leveling on the current Mesh
|
|
|
|
|
*
|
|
|
|
|
* U Unlevel Perform a probe of the outer perimeter to assist in physically leveling unlevel beds.
|
|
|
|
|
* Only used for G29 P1 O U It will speed up the probing of the edge of the bed. This
|
|
|
|
|
* is useful when the entire bed does not need to be probed because it will be adjusted.
|
|
|
|
|
*
|
|
|
|
|
* W What? Display valuable data the Unified Bed Leveling System knows.
|
|
|
|
|
*
|
|
|
|
|
* X # * * X Location for this line of commands
|
|
|
|
@ -297,7 +304,7 @@
|
|
|
|
|
|
|
|
|
|
// The simple parameter flags and values are 'static' so parameter parsing can be in a support routine.
|
|
|
|
|
static int g29_verbose_level = 0, phase_value = -1, repetition_cnt = 1,
|
|
|
|
|
storage_slot = 0, test_pattern = 0;
|
|
|
|
|
storage_slot = 0, map_type = 0, test_pattern = 0, unlevel_value = -1;
|
|
|
|
|
static bool repeat_flag = UBL_OK, c_flag = false, x_flag = UBL_OK, y_flag = UBL_OK, statistics_flag = UBL_OK, business_card_mode = false;
|
|
|
|
|
static float x_pos = 0.0, y_pos = 0.0, height_value = 5.0, measured_z, card_thickness = 0.0, constant = 0.0;
|
|
|
|
|
|
|
|
|
@ -331,7 +338,7 @@
|
|
|
|
|
if (code_seen('I')) {
|
|
|
|
|
repetition_cnt = code_has_value() ? code_value_int() : 1;
|
|
|
|
|
while (repetition_cnt--) {
|
|
|
|
|
const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, x_pos, y_pos, 0, NULL); // The '0' says we want to use the nozzle's position
|
|
|
|
|
const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, x_pos, y_pos, 0, NULL, false); // The '0' says we want to use the nozzle's position
|
|
|
|
|
if (location.x_index < 0) {
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("Entire Mesh invalidated.\n");
|
|
|
|
|
break; // No more invalid Mesh Points to populate
|
|
|
|
@ -381,6 +388,16 @@
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if (code_seen('U')) {
|
|
|
|
|
unlevel_value = code_value_int();
|
|
|
|
|
// if (unlevel_value < 0 || unlevel_value > 7) {
|
|
|
|
|
// SERIAL_PROTOCOLLNPGM("Invalid Unlevel value. (0-4)\n");
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (code_seen('P')) {
|
|
|
|
|
phase_value = code_value_int();
|
|
|
|
|
if (phase_value < 0 || phase_value > 7) {
|
|
|
|
@ -410,7 +427,7 @@
|
|
|
|
|
SERIAL_PROTOCOLLNPGM(")\n");
|
|
|
|
|
}
|
|
|
|
|
probe_entire_mesh(x_pos + X_PROBE_OFFSET_FROM_EXTRUDER, y_pos + Y_PROBE_OFFSET_FROM_EXTRUDER,
|
|
|
|
|
code_seen('O') || code_seen('M'), code_seen('E'));
|
|
|
|
|
code_seen('O') || code_seen('M'), code_seen('E'), code_seen('U'));
|
|
|
|
|
break;
|
|
|
|
|
//
|
|
|
|
|
// Manually Probe Mesh in areas that can not be reached by the probe
|
|
|
|
@ -455,7 +472,7 @@
|
|
|
|
|
// If no repetition is specified, do the whole Mesh
|
|
|
|
|
if (!repeat_flag) repetition_cnt = 9999;
|
|
|
|
|
while (repetition_cnt--) {
|
|
|
|
|
const mesh_index_pair location = find_closest_mesh_point_of_type(INVALID, x_pos, y_pos, 0, NULL); // The '0' says we want to use the nozzle's position
|
|
|
|
|
const mesh_index_pair location = find_closest_mesh_point_of_type(INVALID, x_pos, y_pos, 0, NULL, false); // The '0' says we want to use the nozzle's position
|
|
|
|
|
if (location.x_index < 0) break; // No more invalid Mesh Points to populate
|
|
|
|
|
z_values[location.x_index][location.y_index] = height_value;
|
|
|
|
|
}
|
|
|
|
@ -700,7 +717,7 @@
|
|
|
|
|
* 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 probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe) {
|
|
|
|
|
void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool do_furthest) {
|
|
|
|
|
mesh_index_pair location;
|
|
|
|
|
|
|
|
|
|
ubl_has_control_of_lcd_panel++;
|
|
|
|
@ -721,7 +738,7 @@
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
location = find_closest_mesh_point_of_type(INVALID, lx, ly, 1, NULL); // the '1' says we want the location to be relative to the probe
|
|
|
|
|
location = find_closest_mesh_point_of_type(INVALID, lx, ly, 1, NULL, do_furthest ); // the '1' says we want the location to be relative to the probe
|
|
|
|
|
if (location.x_index >= 0 && location.y_index >= 0) {
|
|
|
|
|
const float xProbe = ubl.map_x_index_to_bed_location(location.x_index),
|
|
|
|
|
yProbe = ubl.map_y_index_to_bed_location(location.y_index);
|
|
|
|
@ -734,7 +751,7 @@
|
|
|
|
|
z_values[location.x_index][location.y_index] = measured_z + Z_PROBE_OFFSET_FROM_EXTRUDER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(1);
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(map_type);
|
|
|
|
|
|
|
|
|
|
} while (location.x_index >= 0 && location.y_index >= 0);
|
|
|
|
|
|
|
|
|
@ -862,9 +879,9 @@
|
|
|
|
|
float last_x = -9999.99, last_y = -9999.99;
|
|
|
|
|
mesh_index_pair location;
|
|
|
|
|
do {
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(1);
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(map_type);
|
|
|
|
|
|
|
|
|
|
location = find_closest_mesh_point_of_type(INVALID, lx, ly, 0, NULL); // The '0' says we want to use the nozzle's position
|
|
|
|
|
location = find_closest_mesh_point_of_type(INVALID, lx, ly, 0, NULL, false); // The '0' says we want to use the nozzle's position
|
|
|
|
|
// It doesn't matter if the probe can not reach the
|
|
|
|
|
// NAN location. This is a manual probe.
|
|
|
|
|
if (location.x_index < 0 && location.y_index < 0) continue;
|
|
|
|
@ -923,7 +940,7 @@
|
|
|
|
|
}
|
|
|
|
|
} while (location.x_index >= 0 && location.y_index >= 0);
|
|
|
|
|
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(1);
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(map_type);
|
|
|
|
|
|
|
|
|
|
LEAVE:
|
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
|
@ -941,6 +958,7 @@
|
|
|
|
|
x_pos = current_position[X_AXIS];
|
|
|
|
|
y_pos = current_position[Y_AXIS];
|
|
|
|
|
x_flag = y_flag = repeat_flag = false;
|
|
|
|
|
map_type = 0;
|
|
|
|
|
constant = 0.0;
|
|
|
|
|
repetition_cnt = 1;
|
|
|
|
|
|
|
|
|
@ -1008,6 +1026,23 @@
|
|
|
|
|
return UBL_ERR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (code_seen('O')) { // Check if a map type was specified
|
|
|
|
|
map_type = code_value_int() ? code_has_value() : 0;
|
|
|
|
|
if ( map_type<0 || map_type>1) {
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("Invalid map type.\n");
|
|
|
|
|
return UBL_ERR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (code_seen('M')) { // Check if a map type was specified
|
|
|
|
|
map_type = code_value_int() ? code_has_value() : 0;
|
|
|
|
|
if ( map_type<0 || map_type>1) {
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("Invalid map type.\n");
|
|
|
|
|
return UBL_ERR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return UBL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1217,9 +1252,9 @@
|
|
|
|
|
z_values[x][y] = z_values[x][y] - tmp_z_values[x][y];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType type, const float &lx, const float &ly, const bool probe_as_reference, unsigned int bits[16]) {
|
|
|
|
|
int i, j;
|
|
|
|
|
float closest = 99999.99;
|
|
|
|
|
mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType type, const float &lx, const float &ly, const bool probe_as_reference, unsigned int bits[16], bool far_flag) {
|
|
|
|
|
int i, j, k, l;
|
|
|
|
|
float distance, closest = far_flag ? -99999.99 : 99999.99;
|
|
|
|
|
mesh_index_pair return_val;
|
|
|
|
|
|
|
|
|
|
return_val.x_index = return_val.y_index = -1;
|
|
|
|
@ -1254,9 +1289,21 @@
|
|
|
|
|
|
|
|
|
|
// We can get to it. Let's see if it is the closest location to the nozzle.
|
|
|
|
|
// Add in a weighting factor that considers the current location of the nozzle.
|
|
|
|
|
const float distance = HYPOT(px - mx, py - my) + HYPOT(current_x - mx, current_y - my) * 0.01;
|
|
|
|
|
|
|
|
|
|
if (distance < closest) {
|
|
|
|
|
distance = HYPOT(px - mx, py - my) + HYPOT(current_x - mx, current_y - my) * 0.1;
|
|
|
|
|
|
|
|
|
|
if (far_flag) { // If doing the far_flag action, we want to be as far as possible
|
|
|
|
|
for (k = 0; k < UBL_MESH_NUM_X_POINTS; k++) { // from the starting point and from any other probed points. We
|
|
|
|
|
for (l = 0; j < UBL_MESH_NUM_Y_POINTS; l++) { // want the next point spread out and filling in any blank spaces
|
|
|
|
|
if ( !isnan(z_values[k][l])) { // in the mesh. So we add in some of the distance to every probed
|
|
|
|
|
distance += (i-k)*(i-k)*MESH_X_DIST*.05; // point we can find.
|
|
|
|
|
distance += (j-l)*(j-l)*MESH_Y_DIST*.05;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (!far_flag&&(distance < closest)) || (far_flag&&(distance > closest)) ) { // if far_flag, look for furthest away point
|
|
|
|
|
closest = distance; // We found a closer location with
|
|
|
|
|
return_val.x_index = i; // the specified type of mesh value.
|
|
|
|
|
return_val.y_index = j;
|
|
|
|
@ -1283,9 +1330,9 @@
|
|
|
|
|
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
|
|
|
|
|
do_blocking_move_to_xy(lx, ly);
|
|
|
|
|
do {
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(1);
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(map_type);
|
|
|
|
|
|
|
|
|
|
location = find_closest_mesh_point_of_type( SET_IN_BITMAP, lx, ly, 0, not_done); // The '0' says we want to use the nozzle's position
|
|
|
|
|
location = find_closest_mesh_point_of_type( SET_IN_BITMAP, lx, ly, 0, not_done, false); // The '0' says we want to use the nozzle's position
|
|
|
|
|
// It doesn't matter if the probe can not reach this
|
|
|
|
|
// location. This is a manual edit of the Mesh Point.
|
|
|
|
|
if (location.x_index < 0 && location.y_index < 0) continue; // abort if we can't find any more points.
|
|
|
|
@ -1356,7 +1403,7 @@
|
|
|
|
|
|
|
|
|
|
ubl_has_control_of_lcd_panel = false;
|
|
|
|
|
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(1);
|
|
|
|
|
if (do_ubl_mesh_map) ubl.display_map(map_type);
|
|
|
|
|
restore_ubl_active_state_and_leave();
|
|
|
|
|
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
|
|
|
|
|
|
|
|
|
|