|
@@ -332,7 +332,7 @@
|
332
|
332
|
else {
|
333
|
333
|
while (g29_repetition_cnt--) {
|
334
|
334
|
if (cnt > 20) { cnt = 0; idle(); }
|
335
|
|
- const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, g29_x_pos, g29_y_pos, USE_NOZZLE_AS_REFERENCE, NULL, false);
|
|
335
|
+ const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, g29_x_pos, g29_y_pos, USE_NOZZLE_AS_REFERENCE, NULL);
|
336
|
336
|
if (location.x_index < 0) {
|
337
|
337
|
// No more REACHABLE mesh points to invalidate, so we ASSUME the user
|
338
|
338
|
// meant to invalidate the ENTIRE mesh, which cannot be done with
|
|
@@ -528,7 +528,7 @@
|
528
|
528
|
}
|
529
|
529
|
else {
|
530
|
530
|
while (g29_repetition_cnt--) { // this only populates reachable mesh points near
|
531
|
|
- const mesh_index_pair location = find_closest_mesh_point_of_type(INVALID, g29_x_pos, g29_y_pos, USE_NOZZLE_AS_REFERENCE, NULL, false);
|
|
531
|
+ const mesh_index_pair location = find_closest_mesh_point_of_type(INVALID, g29_x_pos, g29_y_pos, USE_NOZZLE_AS_REFERENCE, NULL);
|
532
|
532
|
if (location.x_index < 0) {
|
533
|
533
|
// No more REACHABLE INVALID mesh points to populate, so we ASSUME
|
534
|
534
|
// user meant to populate ALL INVALID mesh points to value
|
|
@@ -667,7 +667,7 @@
|
667
|
667
|
}
|
668
|
668
|
|
669
|
669
|
if (parser.seen('T'))
|
670
|
|
- display_map(parser.has_value() ? parser.value_int() : 0);
|
|
670
|
+ display_map(g29_map_type);
|
671
|
671
|
|
672
|
672
|
LEAVE:
|
673
|
673
|
|
|
@@ -742,6 +742,8 @@
|
742
|
742
|
uint16_t max_iterations = GRID_MAX_POINTS;
|
743
|
743
|
|
744
|
744
|
do {
|
|
745
|
+ if (do_ubl_mesh_map) display_map(g29_map_type);
|
|
746
|
+
|
745
|
747
|
#if ENABLED(NEWPANEL)
|
746
|
748
|
if (ubl_lcd_clicked()) {
|
747
|
749
|
SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.\n");
|
|
@@ -755,7 +757,10 @@
|
755
|
757
|
}
|
756
|
758
|
#endif
|
757
|
759
|
|
758
|
|
- location = find_closest_mesh_point_of_type(INVALID, rx, ry, USE_PROBE_AS_REFERENCE, NULL, close_or_far);
|
|
760
|
+ if (close_or_far)
|
|
761
|
+ location = find_furthest_invalid_mesh_point();
|
|
762
|
+ else
|
|
763
|
+ location = find_closest_mesh_point_of_type(INVALID, rx, ry, USE_PROBE_AS_REFERENCE, NULL);
|
759
|
764
|
|
760
|
765
|
if (location.x_index >= 0) { // mesh point found and is reachable by probe
|
761
|
766
|
const float rawx = mesh_index_to_xpos(location.x_index),
|
|
@@ -765,7 +770,6 @@
|
765
|
770
|
z_values[location.x_index][location.y_index] = measured_z;
|
766
|
771
|
}
|
767
|
772
|
|
768
|
|
- if (do_ubl_mesh_map) display_map(g29_map_type);
|
769
|
773
|
|
770
|
774
|
} while (location.x_index >= 0 && --max_iterations);
|
771
|
775
|
|
|
@@ -958,7 +962,7 @@
|
958
|
962
|
|
959
|
963
|
mesh_index_pair location;
|
960
|
964
|
do {
|
961
|
|
- location = find_closest_mesh_point_of_type(INVALID, rx, ry, USE_NOZZLE_AS_REFERENCE, NULL, false);
|
|
965
|
+ location = find_closest_mesh_point_of_type(INVALID, rx, ry, USE_NOZZLE_AS_REFERENCE, NULL);
|
962
|
966
|
// It doesn't matter if the probe can't reach the NAN location. This is a manual probe.
|
963
|
967
|
if (location.x_index < 0 && location.y_index < 0) continue;
|
964
|
968
|
|
|
@@ -1228,7 +1232,7 @@
|
1228
|
1232
|
|
1229
|
1233
|
SERIAL_PROTOCOLPGM("X-Axis Mesh Points at: ");
|
1230
|
1234
|
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
|
1231
|
|
- SERIAL_PROTOCOL_F(mesh_index_to_xpos(i), 3);
|
|
1235
|
+ SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(mesh_index_to_xpos(i)), 3);
|
1232
|
1236
|
SERIAL_PROTOCOLPGM(" ");
|
1233
|
1237
|
safe_delay(25);
|
1234
|
1238
|
}
|
|
@@ -1236,7 +1240,7 @@
|
1236
|
1240
|
|
1237
|
1241
|
SERIAL_PROTOCOLPGM("Y-Axis Mesh Points at: ");
|
1238
|
1242
|
for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; i++) {
|
1239
|
|
- SERIAL_PROTOCOL_F(mesh_index_to_ypos(i), 3);
|
|
1243
|
+ SERIAL_PROTOCOL_F(LOGICAL_Y_POSITION(mesh_index_to_ypos(i)), 3);
|
1240
|
1244
|
SERIAL_PROTOCOLPGM(" ");
|
1241
|
1245
|
safe_delay(25);
|
1242
|
1246
|
}
|
|
@@ -1284,7 +1288,7 @@
|
1284
|
1288
|
*/
|
1285
|
1289
|
void unified_bed_leveling::g29_eeprom_dump() {
|
1286
|
1290
|
unsigned char cccc;
|
1287
|
|
- uint16_t kkkk;
|
|
1291
|
+ unsigned int kkkk; // Needs to be of unspecfied size to compile clean on all platforms
|
1288
|
1292
|
|
1289
|
1293
|
SERIAL_ECHO_START();
|
1290
|
1294
|
SERIAL_ECHOLNPGM("EEPROM Dump:");
|
|
@@ -1294,7 +1298,7 @@
|
1294
|
1298
|
SERIAL_ECHOPGM(": ");
|
1295
|
1299
|
for (uint16_t j = 0; j < 16; j++) {
|
1296
|
1300
|
kkkk = i + j;
|
1297
|
|
- eeprom_read_block(&cccc, (void *)kkkk, 1);
|
|
1301
|
+ eeprom_read_block(&cccc, (const void *) kkkk, sizeof(unsigned char));
|
1298
|
1302
|
print_hex_byte(cccc);
|
1299
|
1303
|
SERIAL_ECHO(' ');
|
1300
|
1304
|
}
|
|
@@ -1340,18 +1344,84 @@
|
1340
|
1344
|
z_values[x][y] -= tmp_z_values[x][y];
|
1341
|
1345
|
}
|
1342
|
1346
|
|
1343
|
|
- mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const float &rx, const float &ry, const bool probe_as_reference, unsigned int bits[16], const bool far_flag) {
|
|
1347
|
+
|
|
1348
|
+ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
|
|
1349
|
+
|
|
1350
|
+ bool found_a_NAN = false;
|
|
1351
|
+ bool found_a_real = false;
|
|
1352
|
+ mesh_index_pair out_mesh;
|
|
1353
|
+ out_mesh.x_index = out_mesh.y_index = -1;
|
|
1354
|
+ out_mesh.distance = -99999.99;
|
|
1355
|
+
|
|
1356
|
+ for (int8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
|
|
1357
|
+ for (int8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
|
|
1358
|
+
|
|
1359
|
+ if ( isnan(z_values[i][j])) { // Check to see if this location holds an invalid mesh point
|
|
1360
|
+
|
|
1361
|
+ const float mx = mesh_index_to_xpos(i),
|
|
1362
|
+ my = mesh_index_to_ypos(j);
|
|
1363
|
+
|
|
1364
|
+ if ( !position_is_reachable_by_probe(mx, my)) // make sure the probe can get to the mesh point
|
|
1365
|
+ continue;
|
|
1366
|
+
|
|
1367
|
+ found_a_NAN = true;
|
|
1368
|
+
|
|
1369
|
+ int8_t closest_x=-1, closest_y=-1;
|
|
1370
|
+ float d1, d2 = 99999.9;
|
|
1371
|
+ for (int8_t k = 0; k < GRID_MAX_POINTS_X; k++) {
|
|
1372
|
+ for (int8_t l = 0; l < GRID_MAX_POINTS_Y; l++) {
|
|
1373
|
+ if (!isnan(z_values[k][l])) {
|
|
1374
|
+ found_a_real = true;
|
|
1375
|
+
|
|
1376
|
+ // Add in a random weighting factor that scrambles the probing of the
|
|
1377
|
+ // last half of the mesh (when every unprobed mesh point is one index
|
|
1378
|
+ // from a probed location).
|
|
1379
|
+
|
|
1380
|
+ d1 = HYPOT(i - k, j - l) + (1.0 / ((millis() % 47) + 13));
|
|
1381
|
+
|
|
1382
|
+ if (d1 < d2) { // found a closer distance from invalid mesh point at (i,j) to defined mesh point at (k,l)
|
|
1383
|
+ d2 = d1; // found a closer location with
|
|
1384
|
+ closest_x = i; // an assigned mesh point value
|
|
1385
|
+ closest_y = j;
|
|
1386
|
+ }
|
|
1387
|
+ }
|
|
1388
|
+ }
|
|
1389
|
+ }
|
|
1390
|
+
|
|
1391
|
+ //
|
|
1392
|
+ // at this point d2 should have the closest defined mesh point to invalid mesh point (i,j)
|
|
1393
|
+ //
|
|
1394
|
+
|
|
1395
|
+ if (found_a_real && (closest_x >= 0) && (d2 > out_mesh.distance)) {
|
|
1396
|
+ out_mesh.distance = d2; // found an invalid location with a greater distance
|
|
1397
|
+ out_mesh.x_index = closest_x; // to a defined mesh point
|
|
1398
|
+ out_mesh.y_index = closest_y;
|
|
1399
|
+ }
|
|
1400
|
+ }
|
|
1401
|
+ } // for j
|
|
1402
|
+ } // for i
|
|
1403
|
+
|
|
1404
|
+ if (!found_a_real && found_a_NAN) { // if the mesh is totally unpopulated, start the probing
|
|
1405
|
+ out_mesh.x_index = GRID_MAX_POINTS_X / 2;
|
|
1406
|
+ out_mesh.y_index = GRID_MAX_POINTS_Y / 2;
|
|
1407
|
+ out_mesh.distance = 1.0;
|
|
1408
|
+ }
|
|
1409
|
+ return out_mesh;
|
|
1410
|
+ }
|
|
1411
|
+
|
|
1412
|
+ mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const float &rx, const float &ry, const bool probe_as_reference, uint16_t bits[16]) {
|
1344
|
1413
|
mesh_index_pair out_mesh;
|
1345
|
1414
|
out_mesh.x_index = out_mesh.y_index = -1;
|
|
1415
|
+ out_mesh.distance = -99999.9;
|
1346
|
1416
|
|
1347
|
1417
|
// Get our reference position. Either the nozzle or probe location.
|
1348
|
1418
|
const float px = rx - (probe_as_reference == USE_PROBE_AS_REFERENCE ? X_PROBE_OFFSET_FROM_EXTRUDER : 0),
|
1349
|
1419
|
py = ry - (probe_as_reference == USE_PROBE_AS_REFERENCE ? Y_PROBE_OFFSET_FROM_EXTRUDER : 0);
|
1350
|
1420
|
|
1351
|
|
- float best_so_far = far_flag ? -99999.99 : 99999.99;
|
|
1421
|
+ float best_so_far = 99999.99;
|
1352
|
1422
|
|
1353
|
|
- for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
|
1354
|
|
- for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
|
|
1423
|
+ for (int8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
|
|
1424
|
+ for (int8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
|
1355
|
1425
|
|
1356
|
1426
|
if ( (type == INVALID && isnan(z_values[i][j])) // Check to see if this location holds the right thing
|
1357
|
1427
|
|| (type == REAL && !isnan(z_values[i][j]))
|
|
@@ -1370,35 +1440,15 @@
|
1370
|
1440
|
continue;
|
1371
|
1441
|
|
1372
|
1442
|
// Reachable. Check if it's the best_so_far location to the nozzle.
|
1373
|
|
- // Add in a weighting factor that considers the current location of the nozzle.
|
1374
|
1443
|
|
1375
|
1444
|
float distance = HYPOT(px - mx, py - my);
|
1376
|
1445
|
|
1377
|
|
- /**
|
1378
|
|
- * If doing the far_flag action, we want to be as far as possible
|
1379
|
|
- * from the starting point and from any other probed points. We
|
1380
|
|
- * want the next point spread out and filling in any blank spaces
|
1381
|
|
- * in the mesh. So we add in some of the distance to every probed
|
1382
|
|
- * point we can find.
|
1383
|
|
- */
|
1384
|
|
- if (far_flag) {
|
1385
|
|
- for (uint8_t k = 0; k < GRID_MAX_POINTS_X; k++) {
|
1386
|
|
- for (uint8_t l = 0; l < GRID_MAX_POINTS_Y; l++) {
|
1387
|
|
- if (i != k && j != l && !isnan(z_values[k][l])) {
|
1388
|
|
- //distance += pow((float) abs(i - k) * (MESH_X_DIST), 2) + pow((float) abs(j - l) * (MESH_Y_DIST), 2); // working here
|
1389
|
|
- distance += HYPOT(MESH_X_DIST, MESH_Y_DIST) / log(HYPOT((i - k) * (MESH_X_DIST) + .001, (j - l) * (MESH_Y_DIST)) + .001);
|
1390
|
|
- }
|
1391
|
|
- }
|
1392
|
|
- }
|
1393
|
|
- }
|
1394
|
|
- else
|
1395
|
1446
|
// factor in the distance from the current location for the normal case
|
1396
|
1447
|
// so the nozzle isn't running all over the bed.
|
1397
|
1448
|
distance += HYPOT(current_position[X_AXIS] - mx, current_position[Y_AXIS] - my) * 0.1;
|
1398
|
1449
|
|
1399
|
|
- // if far_flag, look for farthest point
|
1400
|
|
- if (far_flag == (distance > best_so_far) && distance != best_so_far) {
|
1401
|
|
- best_so_far = distance; // We found a closer/farther location with
|
|
1450
|
+ if (distance < best_so_far) {
|
|
1451
|
+ best_so_far = distance; // We found a closer location with
|
1402
|
1452
|
out_mesh.x_index = i; // the specified type of mesh value.
|
1403
|
1453
|
out_mesh.y_index = j;
|
1404
|
1454
|
out_mesh.distance = best_so_far;
|
|
@@ -1442,7 +1492,7 @@
|
1442
|
1492
|
uint16_t not_done[16];
|
1443
|
1493
|
memset(not_done, 0xFF, sizeof(not_done));
|
1444
|
1494
|
do {
|
1445
|
|
- location = find_closest_mesh_point_of_type(SET_IN_BITMAP, rx, ry, USE_NOZZLE_AS_REFERENCE, not_done, false);
|
|
1495
|
+ location = find_closest_mesh_point_of_type(SET_IN_BITMAP, rx, ry, USE_NOZZLE_AS_REFERENCE, not_done);
|
1446
|
1496
|
|
1447
|
1497
|
if (location.x_index < 0) break; // stop when we can't find any more reachable points.
|
1448
|
1498
|
|
|
@@ -1566,16 +1616,10 @@
|
1566
|
1616
|
info3 PROGMEM = { GRID_MAX_POINTS_X - 1, 0, 0, GRID_MAX_POINTS_Y, true }; // Right side of the mesh looking left
|
1567
|
1617
|
static const smart_fill_info * const info[] PROGMEM = { &info0, &info1, &info2, &info3 };
|
1568
|
1618
|
|
1569
|
|
- // static const smart_fill_info info[] PROGMEM = {
|
1570
|
|
- // { 0, GRID_MAX_POINTS_X, 0, GRID_MAX_POINTS_Y - 2, false } PROGMEM, // Bottom of the mesh looking up
|
1571
|
|
- // { 0, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y - 1, 0, false } PROGMEM, // Top of the mesh looking down
|
1572
|
|
- // { 0, GRID_MAX_POINTS_X - 2, 0, GRID_MAX_POINTS_Y, true } PROGMEM, // Left side of the mesh looking right
|
1573
|
|
- // { GRID_MAX_POINTS_X - 1, 0, 0, GRID_MAX_POINTS_Y, true } PROGMEM // Right side of the mesh looking left
|
1574
|
|
- // };
|
1575
|
1619
|
for (uint8_t i = 0; i < COUNT(info); ++i) {
|
1576
|
|
- const smart_fill_info *f = (smart_fill_info*)pgm_read_word(&info[i]);
|
1577
|
|
- const int8_t sx = pgm_read_word(&f->sx), sy = pgm_read_word(&f->sy),
|
1578
|
|
- ex = pgm_read_word(&f->ex), ey = pgm_read_word(&f->ey);
|
|
1620
|
+ const smart_fill_info *f = (smart_fill_info*)pgm_read_ptr(&info[i]);
|
|
1621
|
+ const int8_t sx = pgm_read_byte(&f->sx), sy = pgm_read_byte(&f->sy),
|
|
1622
|
+ ex = pgm_read_byte(&f->ex), ey = pgm_read_byte(&f->ey);
|
1579
|
1623
|
if (pgm_read_byte(&f->yfirst)) {
|
1580
|
1624
|
const int8_t dir = ex > sx ? 1 : -1;
|
1581
|
1625
|
for (uint8_t y = sy; y != ey; ++y)
|
|
@@ -1614,9 +1658,9 @@
|
1614
|
1658
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
1615
|
1659
|
if (DEBUGGING(LEVELING)) {
|
1616
|
1660
|
SERIAL_CHAR('(');
|
1617
|
|
- SERIAL_PROTOCOL_F(x, 7);
|
|
1661
|
+ SERIAL_PROTOCOL_F(rx, 7);
|
1618
|
1662
|
SERIAL_CHAR(',');
|
1619
|
|
- SERIAL_PROTOCOL_F(y, 7);
|
|
1663
|
+ SERIAL_PROTOCOL_F(ry, 7);
|
1620
|
1664
|
SERIAL_ECHOPGM(") logical: ");
|
1621
|
1665
|
SERIAL_CHAR('(');
|
1622
|
1666
|
SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(rx), 7);
|