|
@@ -125,7 +125,10 @@
|
125
|
125
|
* O Map * Display the Mesh Map Topology.
|
126
|
126
|
* The parameter can be specified alone (ie. G29 O) or in combination with many of the
|
127
|
127
|
* other commands. The Mesh Map option works with all of the Phase
|
128
|
|
- * commands (ie. G29 P4 R 5 X 50 Y100 C -.1 O)
|
|
128
|
+ * commands (ie. G29 P4 R 5 X 50 Y100 C -.1 O) The Map parameter can also of a Map Type
|
|
129
|
+ * specified. A map type of 0 is the default is user readable. A map type of 1 can
|
|
130
|
+ * be specified and is suitable to Cut & Paste into Excel to allow graphing of the user's
|
|
131
|
+ * mesh.
|
129
|
132
|
*
|
130
|
133
|
* N No Home G29 normally insists that a G28 has been performed. You can over rule this with an
|
131
|
134
|
* N option. In general, you should not do this. This can only be done safely with
|
|
@@ -250,6 +253,10 @@
|
250
|
253
|
*
|
251
|
254
|
* T 3-Point Perform a 3 Point Bed Leveling on the current Mesh
|
252
|
255
|
*
|
|
256
|
+ * U Unlevel Perform a probe of the outer perimeter to assist in physically leveling unlevel beds.
|
|
257
|
+ * Only used for G29 P1 O U It will speed up the probing of the edge of the bed. This
|
|
258
|
+ * is useful when the entire bed does not need to be probed because it will be adjusted.
|
|
259
|
+ *
|
253
|
260
|
* W What? Display valuable data the Unified Bed Leveling System knows.
|
254
|
261
|
*
|
255
|
262
|
* X # * * X Location for this line of commands
|
|
@@ -297,7 +304,7 @@
|
297
|
304
|
|
298
|
305
|
// The simple parameter flags and values are 'static' so parameter parsing can be in a support routine.
|
299
|
306
|
static int g29_verbose_level = 0, phase_value = -1, repetition_cnt = 1,
|
300
|
|
- storage_slot = 0, test_pattern = 0;
|
|
307
|
+ storage_slot = 0, map_type = 0, test_pattern = 0, unlevel_value = -1;
|
301
|
308
|
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;
|
302
|
309
|
static float x_pos = 0.0, y_pos = 0.0, height_value = 5.0, measured_z, card_thickness = 0.0, constant = 0.0;
|
303
|
310
|
|
|
@@ -331,7 +338,7 @@
|
331
|
338
|
if (code_seen('I')) {
|
332
|
339
|
repetition_cnt = code_has_value() ? code_value_int() : 1;
|
333
|
340
|
while (repetition_cnt--) {
|
334
|
|
- 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
|
|
341
|
+ 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
|
335
|
342
|
if (location.x_index < 0) {
|
336
|
343
|
SERIAL_PROTOCOLLNPGM("Entire Mesh invalidated.\n");
|
337
|
344
|
break; // No more invalid Mesh Points to populate
|
|
@@ -381,6 +388,16 @@
|
381
|
388
|
}
|
382
|
389
|
}
|
383
|
390
|
|
|
391
|
+/*
|
|
392
|
+ if (code_seen('U')) {
|
|
393
|
+ unlevel_value = code_value_int();
|
|
394
|
+// if (unlevel_value < 0 || unlevel_value > 7) {
|
|
395
|
+// SERIAL_PROTOCOLLNPGM("Invalid Unlevel value. (0-4)\n");
|
|
396
|
+// return;
|
|
397
|
+// }
|
|
398
|
+ }
|
|
399
|
+*/
|
|
400
|
+
|
384
|
401
|
if (code_seen('P')) {
|
385
|
402
|
phase_value = code_value_int();
|
386
|
403
|
if (phase_value < 0 || phase_value > 7) {
|
|
@@ -410,7 +427,7 @@
|
410
|
427
|
SERIAL_PROTOCOLLNPGM(")\n");
|
411
|
428
|
}
|
412
|
429
|
probe_entire_mesh(x_pos + X_PROBE_OFFSET_FROM_EXTRUDER, y_pos + Y_PROBE_OFFSET_FROM_EXTRUDER,
|
413
|
|
- code_seen('O') || code_seen('M'), code_seen('E'));
|
|
430
|
+ code_seen('O') || code_seen('M'), code_seen('E'), code_seen('U'));
|
414
|
431
|
break;
|
415
|
432
|
//
|
416
|
433
|
// Manually Probe Mesh in areas that can not be reached by the probe
|
|
@@ -455,7 +472,7 @@
|
455
|
472
|
// If no repetition is specified, do the whole Mesh
|
456
|
473
|
if (!repeat_flag) repetition_cnt = 9999;
|
457
|
474
|
while (repetition_cnt--) {
|
458
|
|
- 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
|
|
475
|
+ 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
|
459
|
476
|
if (location.x_index < 0) break; // No more invalid Mesh Points to populate
|
460
|
477
|
z_values[location.x_index][location.y_index] = height_value;
|
461
|
478
|
}
|
|
@@ -700,7 +717,7 @@
|
700
|
717
|
* Probe all invalidated locations of the mesh that can be reached by the probe.
|
701
|
718
|
* This attempts to fill in locations closest to the nozzle's start location first.
|
702
|
719
|
*/
|
703
|
|
- void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe) {
|
|
720
|
+ void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool do_furthest) {
|
704
|
721
|
mesh_index_pair location;
|
705
|
722
|
|
706
|
723
|
ubl_has_control_of_lcd_panel++;
|
|
@@ -721,7 +738,7 @@
|
721
|
738
|
return;
|
722
|
739
|
}
|
723
|
740
|
|
724
|
|
- 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
|
|
741
|
+ 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
|
725
|
742
|
if (location.x_index >= 0 && location.y_index >= 0) {
|
726
|
743
|
const float xProbe = ubl.map_x_index_to_bed_location(location.x_index),
|
727
|
744
|
yProbe = ubl.map_y_index_to_bed_location(location.y_index);
|
|
@@ -734,7 +751,7 @@
|
734
|
751
|
z_values[location.x_index][location.y_index] = measured_z + Z_PROBE_OFFSET_FROM_EXTRUDER;
|
735
|
752
|
}
|
736
|
753
|
|
737
|
|
- if (do_ubl_mesh_map) ubl.display_map(1);
|
|
754
|
+ if (do_ubl_mesh_map) ubl.display_map(map_type);
|
738
|
755
|
|
739
|
756
|
} while (location.x_index >= 0 && location.y_index >= 0);
|
740
|
757
|
|
|
@@ -862,9 +879,9 @@
|
862
|
879
|
float last_x = -9999.99, last_y = -9999.99;
|
863
|
880
|
mesh_index_pair location;
|
864
|
881
|
do {
|
865
|
|
- if (do_ubl_mesh_map) ubl.display_map(1);
|
|
882
|
+ if (do_ubl_mesh_map) ubl.display_map(map_type);
|
866
|
883
|
|
867
|
|
- location = find_closest_mesh_point_of_type(INVALID, lx, ly, 0, NULL); // The '0' says we want to use the nozzle's position
|
|
884
|
+ location = find_closest_mesh_point_of_type(INVALID, lx, ly, 0, NULL, false); // The '0' says we want to use the nozzle's position
|
868
|
885
|
// It doesn't matter if the probe can not reach the
|
869
|
886
|
// NAN location. This is a manual probe.
|
870
|
887
|
if (location.x_index < 0 && location.y_index < 0) continue;
|
|
@@ -923,7 +940,7 @@
|
923
|
940
|
}
|
924
|
941
|
} while (location.x_index >= 0 && location.y_index >= 0);
|
925
|
942
|
|
926
|
|
- if (do_ubl_mesh_map) ubl.display_map(1);
|
|
943
|
+ if (do_ubl_mesh_map) ubl.display_map(map_type);
|
927
|
944
|
|
928
|
945
|
LEAVE:
|
929
|
946
|
restore_ubl_active_state_and_leave();
|
|
@@ -941,6 +958,7 @@
|
941
|
958
|
x_pos = current_position[X_AXIS];
|
942
|
959
|
y_pos = current_position[Y_AXIS];
|
943
|
960
|
x_flag = y_flag = repeat_flag = false;
|
|
961
|
+ map_type = 0;
|
944
|
962
|
constant = 0.0;
|
945
|
963
|
repetition_cnt = 1;
|
946
|
964
|
|
|
@@ -1008,6 +1026,23 @@
|
1008
|
1026
|
return UBL_ERR;
|
1009
|
1027
|
}
|
1010
|
1028
|
}
|
|
1029
|
+
|
|
1030
|
+ if (code_seen('O')) { // Check if a map type was specified
|
|
1031
|
+ map_type = code_value_int() ? code_has_value() : 0;
|
|
1032
|
+ if ( map_type<0 || map_type>1) {
|
|
1033
|
+ SERIAL_PROTOCOLLNPGM("Invalid map type.\n");
|
|
1034
|
+ return UBL_ERR;
|
|
1035
|
+ }
|
|
1036
|
+ }
|
|
1037
|
+
|
|
1038
|
+ if (code_seen('M')) { // Check if a map type was specified
|
|
1039
|
+ map_type = code_value_int() ? code_has_value() : 0;
|
|
1040
|
+ if ( map_type<0 || map_type>1) {
|
|
1041
|
+ SERIAL_PROTOCOLLNPGM("Invalid map type.\n");
|
|
1042
|
+ return UBL_ERR;
|
|
1043
|
+ }
|
|
1044
|
+ }
|
|
1045
|
+
|
1011
|
1046
|
return UBL_OK;
|
1012
|
1047
|
}
|
1013
|
1048
|
|
|
@@ -1217,9 +1252,9 @@
|
1217
|
1252
|
z_values[x][y] = z_values[x][y] - tmp_z_values[x][y];
|
1218
|
1253
|
}
|
1219
|
1254
|
|
1220
|
|
- 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]) {
|
1221
|
|
- int i, j;
|
1222
|
|
- float closest = 99999.99;
|
|
1255
|
+ 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) {
|
|
1256
|
+ int i, j, k, l;
|
|
1257
|
+ float distance, closest = far_flag ? -99999.99 : 99999.99;
|
1223
|
1258
|
mesh_index_pair return_val;
|
1224
|
1259
|
|
1225
|
1260
|
return_val.x_index = return_val.y_index = -1;
|
|
@@ -1254,9 +1289,21 @@
|
1254
|
1289
|
|
1255
|
1290
|
// We can get to it. Let's see if it is the closest location to the nozzle.
|
1256
|
1291
|
// Add in a weighting factor that considers the current location of the nozzle.
|
1257
|
|
- const float distance = HYPOT(px - mx, py - my) + HYPOT(current_x - mx, current_y - my) * 0.01;
|
1258
|
1292
|
|
1259
|
|
- if (distance < closest) {
|
|
1293
|
+ distance = HYPOT(px - mx, py - my) + HYPOT(current_x - mx, current_y - my) * 0.1;
|
|
1294
|
+
|
|
1295
|
+ if (far_flag) { // If doing the far_flag action, we want to be as far as possible
|
|
1296
|
+ for (k = 0; k < UBL_MESH_NUM_X_POINTS; k++) { // from the starting point and from any other probed points. We
|
|
1297
|
+ for (l = 0; j < UBL_MESH_NUM_Y_POINTS; l++) { // want the next point spread out and filling in any blank spaces
|
|
1298
|
+ if ( !isnan(z_values[k][l])) { // in the mesh. So we add in some of the distance to every probed
|
|
1299
|
+ distance += (i-k)*(i-k)*MESH_X_DIST*.05; // point we can find.
|
|
1300
|
+ distance += (j-l)*(j-l)*MESH_Y_DIST*.05;
|
|
1301
|
+ }
|
|
1302
|
+ }
|
|
1303
|
+ }
|
|
1304
|
+ }
|
|
1305
|
+
|
|
1306
|
+ if ( (!far_flag&&(distance < closest)) || (far_flag&&(distance > closest)) ) { // if far_flag, look for furthest away point
|
1260
|
1307
|
closest = distance; // We found a closer location with
|
1261
|
1308
|
return_val.x_index = i; // the specified type of mesh value.
|
1262
|
1309
|
return_val.y_index = j;
|
|
@@ -1283,9 +1330,9 @@
|
1283
|
1330
|
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
|
1284
|
1331
|
do_blocking_move_to_xy(lx, ly);
|
1285
|
1332
|
do {
|
1286
|
|
- if (do_ubl_mesh_map) ubl.display_map(1);
|
|
1333
|
+ if (do_ubl_mesh_map) ubl.display_map(map_type);
|
1287
|
1334
|
|
1288
|
|
- 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
|
|
1335
|
+ 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
|
1289
|
1336
|
// It doesn't matter if the probe can not reach this
|
1290
|
1337
|
// location. This is a manual edit of the Mesh Point.
|
1291
|
1338
|
if (location.x_index < 0 && location.y_index < 0) continue; // abort if we can't find any more points.
|
|
@@ -1356,7 +1403,7 @@
|
1356
|
1403
|
|
1357
|
1404
|
ubl_has_control_of_lcd_panel = false;
|
1358
|
1405
|
|
1359
|
|
- if (do_ubl_mesh_map) ubl.display_map(1);
|
|
1406
|
+ if (do_ubl_mesh_map) ubl.display_map(map_type);
|
1360
|
1407
|
restore_ubl_active_state_and_leave();
|
1361
|
1408
|
do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
|
1362
|
1409
|
|