Map clean up of UBL
UBL's maps are cleaner. And with a 1 value, G29 O 1 will generate a map suitable to be Cut & Pasted into Excel so a Suface Map can be generated.
This commit is contained in:
parent
9a1949a91e
commit
9d3ac66f73
@ -42,13 +42,13 @@
|
||||
bool axis_unhomed_error(bool, bool, bool);
|
||||
void dump(char * const str, const float &f);
|
||||
bool ubl_lcd_clicked();
|
||||
void probe_entire_mesh(const float&, const float&, const bool, const bool);
|
||||
void probe_entire_mesh(const float&, const float&, const bool, const bool, const bool);
|
||||
void debug_current_and_destination(char *title);
|
||||
void ubl_line_to_destination(const float&, const float&, const float&, const float&, const float&, uint8_t);
|
||||
void manually_probe_remaining_mesh(const float&, const float&, const float&, const float&, const bool);
|
||||
vector_3 tilt_mesh_based_on_3pts(const float&, const float&, const float&);
|
||||
float measure_business_card_thickness(const float&);
|
||||
mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, unsigned int[16]);
|
||||
mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, unsigned int[16], bool);
|
||||
void find_mean_mesh_height();
|
||||
void shift_mesh_height();
|
||||
bool g29_parameter_parsing();
|
||||
|
@ -166,32 +166,34 @@
|
||||
int8_t i, j;
|
||||
UNUSED(map_type);
|
||||
|
||||
SERIAL_PROTOCOLLNPGM("\nBed Topography Report:\n");
|
||||
if (map_type==0) {
|
||||
SERIAL_PROTOCOLLNPGM("\nBed Topography Report:\n");
|
||||
|
||||
SERIAL_ECHOPAIR("(", 0);
|
||||
SERIAL_ECHOPAIR(", ", UBL_MESH_NUM_Y_POINTS - 1);
|
||||
SERIAL_ECHOPGM(") ");
|
||||
SERIAL_ECHOPAIR("(", 0);
|
||||
SERIAL_ECHOPAIR(", ", UBL_MESH_NUM_Y_POINTS - 1);
|
||||
SERIAL_ECHOPGM(") ");
|
||||
}
|
||||
|
||||
current_xi = ubl.get_cell_index_x(current_position[X_AXIS] + (MESH_X_DIST) / 2.0);
|
||||
current_yi = ubl.get_cell_index_y(current_position[Y_AXIS] + (MESH_Y_DIST) / 2.0);
|
||||
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
|
||||
SERIAL_ECHOPGM(" ");
|
||||
#if TX_BUFFER_SIZE>0
|
||||
MYSERIAL.flushTX();
|
||||
#endif
|
||||
delay(15);
|
||||
}
|
||||
if (map_type==0) {
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
|
||||
SERIAL_ECHOPGM(" ");
|
||||
#if TX_BUFFER_SIZE>0
|
||||
MYSERIAL.flushTX();
|
||||
#endif
|
||||
delay(15);
|
||||
}
|
||||
|
||||
SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS - 1);
|
||||
SERIAL_ECHOPAIR(",", UBL_MESH_NUM_Y_POINTS - 1);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
|
||||
// if (map_type || 1) {
|
||||
SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS - 1);
|
||||
SERIAL_ECHOPAIR(",", UBL_MESH_NUM_Y_POINTS - 1);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
|
||||
SERIAL_ECHOPAIR("(", UBL_MESH_MIN_X);
|
||||
SERIAL_ECHOPAIR(",", UBL_MESH_MAX_Y);
|
||||
SERIAL_CHAR(')');
|
||||
delay(15);
|
||||
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
|
||||
SERIAL_ECHOPGM(" ");
|
||||
@ -204,75 +206,82 @@
|
||||
SERIAL_ECHOPAIR("(", UBL_MESH_MAX_X);
|
||||
SERIAL_ECHOPAIR(",", UBL_MESH_MAX_Y);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
|
||||
// }
|
||||
delay(15);
|
||||
}
|
||||
|
||||
for (j = UBL_MESH_NUM_Y_POINTS - 1; j >= 0; j--) {
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS; i++) {
|
||||
f = z_values[i][j];
|
||||
|
||||
// is the nozzle here? if so, mark the number
|
||||
SERIAL_CHAR(i == current_xi && j == current_yi ? '[' : ' ');
|
||||
if (map_type==0)
|
||||
SERIAL_CHAR(i == current_xi && j == current_yi ? '[' : ' ');
|
||||
|
||||
if (isnan(f))
|
||||
SERIAL_PROTOCOLPGM(" . ");
|
||||
if (map_type==0) {
|
||||
SERIAL_PROTOCOLPGM(" . ");
|
||||
} else
|
||||
SERIAL_PROTOCOLPGM("NAN");
|
||||
else {
|
||||
// if we don't do this, the columns won't line up nicely
|
||||
if (f >= 0.0) SERIAL_CHAR(' ');
|
||||
if (f>=0.0 && map_type==0) SERIAL_CHAR(' ');
|
||||
SERIAL_PROTOCOL_F(f, 3);
|
||||
idle();
|
||||
}
|
||||
if (map_type!=0 && i<UBL_MESH_NUM_X_POINTS-1)
|
||||
SERIAL_PROTOCOLPGM(",");
|
||||
|
||||
#if TX_BUFFER_SIZE>0
|
||||
MYSERIAL.flushTX();
|
||||
#endif
|
||||
delay(15);
|
||||
if (i == current_xi && j == current_yi) // is the nozzle here? if so, finish marking the number
|
||||
SERIAL_CHAR(']');
|
||||
else
|
||||
SERIAL_PROTOCOL(" ");
|
||||
|
||||
SERIAL_CHAR(' ');
|
||||
if (map_type==0) {
|
||||
if (i == current_xi && j == current_yi) // is the nozzle here? if so, finish marking the number
|
||||
SERIAL_CHAR(']');
|
||||
else
|
||||
SERIAL_PROTOCOL(" ");
|
||||
SERIAL_CHAR(' ');
|
||||
}
|
||||
}
|
||||
SERIAL_EOL;
|
||||
if (j) { // we want the (0,0) up tight against the block of numbers
|
||||
if (j && map_type==0) { // we want the (0,0) up tight against the block of numbers
|
||||
SERIAL_CHAR(' ');
|
||||
SERIAL_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// if (map_type) {
|
||||
SERIAL_ECHOPAIR("(", int(UBL_MESH_MIN_X));
|
||||
SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
|
||||
SERIAL_ECHOPGM(") ");
|
||||
if (map_type==0) {
|
||||
SERIAL_ECHOPAIR("(", int(UBL_MESH_MIN_X));
|
||||
SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
|
||||
SERIAL_ECHOPGM(") ");
|
||||
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
|
||||
SERIAL_ECHOPGM(" ");
|
||||
#if TX_BUFFER_SIZE>0
|
||||
MYSERIAL.flushTX();
|
||||
#endif
|
||||
delay(15);
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
|
||||
SERIAL_ECHOPGM(" ");
|
||||
#if TX_BUFFER_SIZE>0
|
||||
MYSERIAL.flushTX();
|
||||
#endif
|
||||
delay(15);
|
||||
}
|
||||
SERIAL_ECHOPAIR("(", int(UBL_MESH_MAX_X));
|
||||
SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
|
||||
SERIAL_CHAR(')');
|
||||
SERIAL_EOL;
|
||||
|
||||
SERIAL_ECHOPAIR("(", 0);
|
||||
SERIAL_ECHOPAIR(",", 0);
|
||||
SERIAL_ECHOPGM(") ");
|
||||
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
|
||||
SERIAL_ECHOPGM(" ");
|
||||
#if TX_BUFFER_SIZE>0
|
||||
MYSERIAL.flushTX();
|
||||
#endif
|
||||
delay(15);
|
||||
}
|
||||
SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS-1);
|
||||
SERIAL_ECHOPAIR(",", 0);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
}
|
||||
|
||||
SERIAL_ECHOPAIR("(", int(UBL_MESH_MAX_X));
|
||||
SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
|
||||
SERIAL_CHAR(')');
|
||||
SERIAL_EOL;
|
||||
|
||||
SERIAL_ECHOPAIR("(", 0);
|
||||
SERIAL_ECHOPAIR(",", 0);
|
||||
SERIAL_ECHOPGM(") ");
|
||||
|
||||
for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
|
||||
SERIAL_ECHOPGM(" ");
|
||||
#if TX_BUFFER_SIZE>0
|
||||
MYSERIAL.flushTX();
|
||||
#endif
|
||||
delay(15);
|
||||
}
|
||||
|
||||
SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS-1);
|
||||
SERIAL_ECHOPAIR(",", 0);
|
||||
SERIAL_ECHOLNPGM(")");
|
||||
}
|
||||
|
||||
bool unified_bed_leveling::sanity_check() {
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user