|
@@ -102,8 +102,6 @@
|
102
|
102
|
* specified height, no correction is applied and natural printer kenimatics take over. If no
|
103
|
103
|
* number is specified for the command, 10mm is assumed to be reasonable.
|
104
|
104
|
*
|
105
|
|
- * G # Grid * Perform a Grid Based Leveling of the current Mesh using a grid with n points on a side.
|
106
|
|
- *
|
107
|
105
|
* H # Height Specify the Height to raise the nozzle after each manual probe of the bed. The
|
108
|
106
|
* default is 5mm.
|
109
|
107
|
*
|
|
@@ -117,6 +115,10 @@
|
117
|
115
|
* the bed and use this feature to select the center of the area (or cell) you want to
|
118
|
116
|
* invalidate.
|
119
|
117
|
*
|
|
118
|
+ * J # Grid * Perform a Grid Based Leveling of the current Mesh using a grid with n points on a side.
|
|
119
|
+ *
|
|
120
|
+ * j EEPROM Dump This function probably goes away after debug is complete.
|
|
121
|
+ *
|
120
|
122
|
* K # Kompare Kompare current Mesh with stored Mesh # replacing current Mesh with the result. This
|
121
|
123
|
* command literally performs a diff between two Meshes.
|
122
|
124
|
*
|
|
@@ -303,7 +305,7 @@
|
303
|
305
|
|
304
|
306
|
// The simple parameter flags and values are 'static' so parameter parsing can be in a support routine.
|
305
|
307
|
static int g29_verbose_level, phase_value = -1, repetition_cnt,
|
306
|
|
- storage_slot = 0, map_type, grid_size_G ; //unlevel_value = -1;
|
|
308
|
+ storage_slot=0, map_type, grid_size;
|
307
|
309
|
static bool repeat_flag, c_flag, x_flag, y_flag;
|
308
|
310
|
static float x_pos, y_pos, measured_z, card_thickness = 0.0, ubl_constant = 0.0;
|
309
|
311
|
|
|
@@ -378,24 +380,9 @@
|
378
|
380
|
}
|
379
|
381
|
}
|
380
|
382
|
|
381
|
|
- /*
|
382
|
|
- if (code_seen('U')) {
|
383
|
|
- unlevel_value = code_value_int();
|
384
|
|
- //if (!WITHIN(unlevel_value, 0, 7)) {
|
385
|
|
- // SERIAL_PROTOCOLLNPGM("Invalid Unlevel value. (0-4)\n");
|
386
|
|
- // return;
|
387
|
|
- //}
|
388
|
|
- }
|
389
|
|
- */
|
390
|
|
-
|
391
|
|
- if (code_seen('G')) {
|
392
|
|
- uint8_t grid_size_G = code_has_value() ? code_value_int() : 3;
|
393
|
|
- if (grid_size_G < 2) {
|
394
|
|
- SERIAL_PROTOCOLLNPGM("ERROR - grid size must be 2 or more");
|
395
|
|
- return;
|
396
|
|
- }
|
397
|
|
- if (grid_size_G > GRID_MAX_POINTS_X || grid_size_G > GRID_MAX_POINTS_Y) {
|
398
|
|
- SERIAL_PROTOCOLLNPGM("ERROR - grid size can NOT exceed GRID_MAX_POINTS_X nor GRID_MAX_POINTS_Y");
|
|
383
|
+ if (code_seen('J')) {
|
|
384
|
+ if (grid_size<2 || grid_size>5) {
|
|
385
|
+ SERIAL_PROTOCOLLNPGM("ERROR - grid size must be between 2 and 5");
|
399
|
386
|
return;
|
400
|
387
|
}
|
401
|
388
|
tilt_mesh_based_on_probed_grid(code_seen('O') || code_seen('M'));
|
|
@@ -567,7 +554,7 @@
|
567
|
554
|
// When we are fully debugged, the EEPROM dump command will get deleted also. But
|
568
|
555
|
// right now, it is good to have the extra information. Soon... we prune this.
|
569
|
556
|
//
|
570
|
|
- if (code_seen('J')) g29_eeprom_dump(); // EEPROM Dump
|
|
557
|
+ if (code_seen('j')) g29_eeprom_dump(); // EEPROM Dump
|
571
|
558
|
|
572
|
559
|
//
|
573
|
560
|
// When we are fully debugged, this may go away. But there are some valid
|
|
@@ -692,11 +679,9 @@
|
692
|
679
|
|
693
|
680
|
LEAVE:
|
694
|
681
|
|
695
|
|
- #if ENABLED(ULTRA_LCD)
|
696
|
|
- lcd_reset_alert_level();
|
697
|
|
- LCD_MESSAGEPGM("");
|
698
|
|
- lcd_quick_feedback();
|
699
|
|
- #endif
|
|
682
|
+ lcd_reset_alert_level();
|
|
683
|
+ LCD_MESSAGEPGM("");
|
|
684
|
+ lcd_quick_feedback();
|
700
|
685
|
|
701
|
686
|
ubl.has_control_of_lcd_panel = false;
|
702
|
687
|
}
|
|
@@ -997,18 +982,26 @@
|
997
|
982
|
}
|
998
|
983
|
|
999
|
984
|
bool g29_parameter_parsing() {
|
1000
|
|
- #if ENABLED(ULTRA_LCD)
|
|
985
|
+ bool err_flag = false;
|
|
986
|
+
|
1001
|
987
|
LCD_MESSAGEPGM("Doing G29 UBL!");
|
1002
|
988
|
lcd_quick_feedback();
|
1003
|
|
- #endif
|
1004
|
989
|
|
1005
|
990
|
x_flag = code_seen('X') && code_has_value();
|
1006
|
|
- y_flag = code_seen('Y') && code_has_value();
|
1007
|
991
|
x_pos = x_flag ? code_value_float() : current_position[X_AXIS];
|
|
992
|
+
|
|
993
|
+ y_flag = code_seen('Y') && code_has_value();
|
1008
|
994
|
y_pos = y_flag ? code_value_float() : current_position[Y_AXIS];
|
1009
|
|
- repeat_flag = code_seen('R') ? code_value_bool() : false;
|
1010
|
995
|
|
1011
|
|
- bool err_flag = false;
|
|
996
|
+ repetition_cnt = 0;
|
|
997
|
+ repeat_flag = code_seen('R');
|
|
998
|
+ if (repeat_flag) {
|
|
999
|
+ repetition_cnt = code_has_value() ? code_value_int() : GRID_MAX_POINTS_X*GRID_MAX_POINTS_Y;
|
|
1000
|
+ if (repetition_cnt < 1) {
|
|
1001
|
+ SERIAL_PROTOCOLLNPGM("Invalid Repetition count.\n");
|
|
1002
|
+ return UBL_ERR;
|
|
1003
|
+ }
|
|
1004
|
+ }
|
1012
|
1005
|
|
1013
|
1006
|
g29_verbose_level = code_seen('V') ? code_value_int() : 0;
|
1014
|
1007
|
if (!WITHIN(g29_verbose_level, 0, 4)) {
|
|
@@ -1017,8 +1010,8 @@
|
1017
|
1010
|
}
|
1018
|
1011
|
|
1019
|
1012
|
if (code_seen('G')) {
|
1020
|
|
- grid_size_G = code_has_value() ? code_value_int() : 3;
|
1021
|
|
- if (!WITHIN(grid_size_G, 2, 10)) {
|
|
1013
|
+ grid_size = code_has_value() ? code_value_int() : 3;
|
|
1014
|
+ if (!WITHIN(grid_size, 2, 5)) {
|
1022
|
1015
|
SERIAL_PROTOCOLLNPGM("Invalid grid probe points specified.\n");
|
1023
|
1016
|
err_flag = true;
|
1024
|
1017
|
}
|
|
@@ -1032,11 +1025,27 @@
|
1032
|
1025
|
if (!WITHIN(RAW_X_POSITION(x_pos), X_MIN_POS, X_MAX_POS)) {
|
1033
|
1026
|
SERIAL_PROTOCOLLNPGM("Invalid X location specified.\n");
|
1034
|
1027
|
err_flag = true;
|
|
1028
|
+ SERIAL_PROTOCOLPAIR("\nx_flag = ", x_flag); // These print blocks are only useful because sometimes the
|
|
1029
|
+ SERIAL_PROTOCOLPAIR("\nx_pos = ", x_pos ); // data corruption causes x_pos and y_pos to be crazy. This gets deleted soon.
|
|
1030
|
+ SERIAL_PROTOCOLPAIR("\ncurrent[] = ", current_position[X_AXIS]);
|
|
1031
|
+ SERIAL_PROTOCOLPAIR("\nX_MIN_POS = ", X_MIN_POS);
|
|
1032
|
+ SERIAL_PROTOCOLPAIR("\nX_MAX_POS = ", X_MAX_POS);
|
|
1033
|
+ SERIAL_PROTOCOLPAIR("\nRAW_X_POSITION() = ", RAW_X_POSITION(x_pos));
|
|
1034
|
+ SERIAL_PROTOCOLPAIR("\nwithin() = ", WITHIN(RAW_X_POSITION(x_pos), X_MIN_POS, X_MAX_POS));
|
|
1035
|
+ SERIAL_PROTOCOL("\n");
|
1035
|
1036
|
}
|
1036
|
1037
|
|
1037
|
1038
|
if (!WITHIN(RAW_Y_POSITION(y_pos), Y_MIN_POS, Y_MAX_POS)) {
|
1038
|
1039
|
SERIAL_PROTOCOLLNPGM("Invalid Y location specified.\n");
|
1039
|
1040
|
err_flag = true;
|
|
1041
|
+ SERIAL_PROTOCOLPAIR("\ny_flag = ", y_flag); // These print blocks are only useful because sometimes the
|
|
1042
|
+ SERIAL_PROTOCOLPAIR("\ny_pos = ", y_pos ); // data corruption causes x_pos and y_pos to be crazy. This gets deleted soon.
|
|
1043
|
+ SERIAL_PROTOCOLPAIR("\ncurrent[] = ", current_position[Y_AXIS]);
|
|
1044
|
+ SERIAL_PROTOCOLPAIR("\nY_MIN_POS = ", Y_MIN_POS);
|
|
1045
|
+ SERIAL_PROTOCOLPAIR("\nY_MAX_POS = ", Y_MAX_POS);
|
|
1046
|
+ SERIAL_PROTOCOLPAIR("\nRAW_Y_POSITION() = ", RAW_Y_POSITION(y_pos));
|
|
1047
|
+ SERIAL_PROTOCOLPAIR("\nwithin() = ", WITHIN(RAW_Y_POSITION(y_pos), Y_MIN_POS, Y_MAX_POS));
|
|
1048
|
+ SERIAL_PROTOCOL("\n");
|
1040
|
1049
|
}
|
1041
|
1050
|
|
1042
|
1051
|
if (err_flag) return UBL_ERR;
|
|
@@ -1068,11 +1077,6 @@
|
1068
|
1077
|
}
|
1069
|
1078
|
#endif
|
1070
|
1079
|
|
1071
|
|
- repetition_cnt = repeat_flag ? (code_has_value() ? code_value_int() : 9999) : 1;
|
1072
|
|
- if (repetition_cnt < 1) {
|
1073
|
|
- SERIAL_PROTOCOLLNPGM("Invalid Repetition count.\n");
|
1074
|
|
- return UBL_ERR;
|
1075
|
|
- }
|
1076
|
1080
|
|
1077
|
1081
|
map_type = code_seen('O') && code_has_value() ? code_value_int() : 0;
|
1078
|
1082
|
if (!WITHIN(map_type, 0, 1)) {
|
|
@@ -1365,9 +1369,8 @@
|
1365
|
1369
|
}
|
1366
|
1370
|
|
1367
|
1371
|
void fine_tune_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map) {
|
1368
|
|
- // do all mesh points unless R option has a value of 1 or more
|
1369
|
|
- repetition_cnt = code_seen('R') && code_has_value() ? code_value_byte() : GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y;
|
1370
|
|
- if (repetition_cnt == 0) repetition_cnt = GRID_MAX_POINTS_X * GRID_MAX_POINTS_Y;
|
|
1372
|
+ if (!code_seen('R')) // fine_tune_mesh() is special. If no repetion count flag is specified
|
|
1373
|
+ repetition_cnt = 1; // we know to do exactly one mesh location. Otherwise we use what the parser decided.
|
1371
|
1374
|
|
1372
|
1375
|
mesh_index_pair location;
|
1373
|
1376
|
uint16_t not_done[16];
|
|
@@ -1448,7 +1451,7 @@
|
1448
|
1451
|
|
1449
|
1452
|
lcd_implementation_clear();
|
1450
|
1453
|
|
1451
|
|
- } while (location.x_index >= 0 && location.y_index >= 0 && --repetition_cnt);
|
|
1454
|
+ } while (location.x_index >= 0 && location.y_index >= 0 && (--repetition_cnt>0));
|
1452
|
1455
|
|
1453
|
1456
|
FINE_TUNE_EXIT:
|
1454
|
1457
|
|
|
@@ -1466,16 +1469,16 @@
|
1466
|
1469
|
}
|
1467
|
1470
|
|
1468
|
1471
|
void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map) {
|
1469
|
|
- int8_t grid_G_index_to_xpos[grid_size_G], // UBL MESH X index to be probed
|
1470
|
|
- grid_G_index_to_ypos[grid_size_G], // UBL MESH Y index to be probed
|
1471
|
|
- i, j ,k, xCount, yCount, G_X_index, G_Y_index; // counter variables
|
1472
|
|
- float z_values_G[grid_size_G][grid_size_G];
|
|
1472
|
+ int8_t grid_G_index_to_xpos[grid_size], // UBL MESH X index to be probed
|
|
1473
|
+ grid_G_index_to_ypos[grid_size], // UBL MESH Y index to be probed
|
|
1474
|
+ i, j ,k, xCount, yCount, xi, yi; // counter variables
|
|
1475
|
+ float z_values_G[grid_size][grid_size];
|
1473
|
1476
|
|
1474
|
1477
|
linear_fit *results;
|
1475
|
1478
|
|
1476
|
|
- for (G_Y_index = 0; G_Y_index < grid_size_G; G_Y_index++)
|
1477
|
|
- for (G_X_index = 0; G_X_index < grid_size_G; G_X_index++)
|
1478
|
|
- z_values_G[G_X_index][G_Y_index] = NAN;
|
|
1479
|
+ for (yi = 0; yi < grid_size; yi++)
|
|
1480
|
+ for (xi = 0; xi < grid_size; xi++)
|
|
1481
|
+ z_values_G[xi][yi] = NAN;
|
1479
|
1482
|
|
1480
|
1483
|
uint8_t x_min = GRID_MAX_POINTS_X - 1,
|
1481
|
1484
|
x_max = 0,
|
|
@@ -1494,26 +1497,26 @@
|
1494
|
1497
|
}
|
1495
|
1498
|
}
|
1496
|
1499
|
|
1497
|
|
- if (x_max - x_min + 1 < grid_size_G || y_max - y_min + 1 < grid_size_G) {
|
|
1500
|
+ if (x_max - x_min + 1 < grid_size || y_max - y_min + 1 < grid_size) {
|
1498
|
1501
|
SERIAL_ECHOPAIR("ERROR - probeable UBL MESH smaller than grid - X points: ", x_max - x_min + 1);
|
1499
|
1502
|
SERIAL_ECHOPAIR(" Y points: ", y_max - y_min + 1);
|
1500
|
|
- SERIAL_ECHOLNPAIR(" grid: ", grid_size_G);
|
|
1503
|
+ SERIAL_ECHOLNPAIR(" grid: ", grid_size);
|
1501
|
1504
|
return;
|
1502
|
1505
|
}
|
1503
|
1506
|
|
1504
|
1507
|
// populate X matrix
|
1505
|
|
- for (G_X_index = 0; G_X_index < grid_size_G; G_X_index++) {
|
1506
|
|
- grid_G_index_to_xpos[G_X_index] = x_min + G_X_index * (x_max - x_min) / (grid_size_G - 1);
|
1507
|
|
- if (G_X_index > 0 && grid_G_index_to_xpos[G_X_index - 1] == grid_G_index_to_xpos[G_X_index]) {
|
1508
|
|
- grid_G_index_to_xpos[G_X_index] = grid_G_index_to_xpos[G_X_index - 1] + 1;
|
|
1508
|
+ for (xi = 0; xi < grid_size; xi++) {
|
|
1509
|
+ grid_G_index_to_xpos[xi] = x_min + xi * (x_max - x_min) / (grid_size - 1);
|
|
1510
|
+ if (xi > 0 && grid_G_index_to_xpos[xi - 1] == grid_G_index_to_xpos[xi]) {
|
|
1511
|
+ grid_G_index_to_xpos[xi] = grid_G_index_to_xpos[xi - 1] + 1;
|
1509
|
1512
|
}
|
1510
|
1513
|
}
|
1511
|
1514
|
|
1512
|
1515
|
// populate Y matrix
|
1513
|
|
- for (G_Y_index = 0; G_Y_index < grid_size_G; G_Y_index++) {
|
1514
|
|
- grid_G_index_to_ypos[G_Y_index] = y_min + G_Y_index * (y_max - y_min) / (grid_size_G - 1);
|
1515
|
|
- if (G_Y_index > 0 && grid_G_index_to_ypos[G_Y_index - 1] == grid_G_index_to_ypos[G_Y_index]) {
|
1516
|
|
- grid_G_index_to_ypos[G_Y_index] = grid_G_index_to_ypos[G_Y_index - 1] + 1;
|
|
1516
|
+ for (yi = 0; yi < grid_size; yi++) {
|
|
1517
|
+ grid_G_index_to_ypos[yi] = y_min + yi * (y_max - y_min) / (grid_size - 1);
|
|
1518
|
+ if (yi > 0 && grid_G_index_to_ypos[yi - 1] == grid_G_index_to_ypos[yi]) {
|
|
1519
|
+ grid_G_index_to_ypos[yi] = grid_G_index_to_ypos[yi - 1] + 1;
|
1517
|
1520
|
}
|
1518
|
1521
|
}
|
1519
|
1522
|
|
|
@@ -1526,14 +1529,14 @@
|
1526
|
1529
|
#undef PROBE_Y_FIRST
|
1527
|
1530
|
#if ENABLED(PROBE_Y_FIRST)
|
1528
|
1531
|
#define PR_OUTER_VAR xCount
|
1529
|
|
- #define PR_OUTER_NUM grid_size_G
|
|
1532
|
+ #define PR_OUTER_NUM grid_size
|
1530
|
1533
|
#define PR_INNER_VAR yCount
|
1531
|
|
- #define PR_INNER_NUM grid_size_G
|
|
1534
|
+ #define PR_INNER_NUM grid_size
|
1532
|
1535
|
#else
|
1533
|
1536
|
#define PR_OUTER_VAR yCount
|
1534
|
|
- #define PR_OUTER_NUM grid_size_G
|
|
1537
|
+ #define PR_OUTER_NUM grid_size
|
1535
|
1538
|
#define PR_INNER_VAR xCount
|
1536
|
|
- #define PR_INNER_NUM grid_size_G
|
|
1539
|
+ #define PR_INNER_NUM grid_size
|
1537
|
1540
|
#endif
|
1538
|
1541
|
|
1539
|
1542
|
bool zig = PR_OUTER_NUM & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION
|
|
@@ -1601,9 +1604,9 @@
|
1601
|
1604
|
//do_blocking_move_to_xy(ubl.mesh_index_to_xpos[grid_G_index_to_xpos[0]], ubl.mesh_index_to_ypos[grid_G_index_to_ypos[0]]);
|
1602
|
1605
|
|
1603
|
1606
|
// least squares code
|
1604
|
|
- double xxx9[] = { 0,50,100,150,200, 20,70,120,165,195, 0,50,100,150,200, 0,55,100,150,200, 0,65,100,150,205 },
|
1605
|
|
- yyy9[] = { 0, 1, 2, 3, 4, 50, 51, 52, 53, 54, 100, 101,102,103,104, 150,151,152,153,154, 200,201,202,203,204 },
|
1606
|
|
- zzz9[] = { 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.012,0.01},
|
|
1607
|
+ double xxx5[] = { 0,50,100,150,200, 20,70,120,165,195, 0,50,100,150,200, 0,55,100,150,200, 0,65,100,150,205 },
|
|
1608
|
+ yyy5[] = { 0, 1, 2, 3, 4, 50, 51, 52, 53, 54, 100, 101,102,103,104, 150,151,152,153,154, 200,201,202,203,204 },
|
|
1609
|
+ zzz5[] = { 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.02,0, 0.01,.002,-.01,-.012,0.01},
|
1607
|
1610
|
xxx0[] = { 0.0, 0.0, 1.0 }, // Expect [0,0,0.1,0]
|
1608
|
1611
|
yyy0[] = { 0.0, 1.0, 0.0 },
|
1609
|
1612
|
zzz0[] = { 0.1, 0.1, 0.1 },
|
|
@@ -1611,10 +1614,10 @@
|
1611
|
1614
|
yyy[] = { 0.0, 1.0, 0.0, 1.0 },
|
1612
|
1615
|
zzz[] = { 0.05, 0.05, 0.15, 0.15 };
|
1613
|
1616
|
|
1614
|
|
- results = lsf_linear_fit(xxx9, yyy9, zzz9, COUNT(xxx9));
|
1615
|
|
- SERIAL_ECHOPAIR("\nxxx9->A =", results->A);
|
1616
|
|
- SERIAL_ECHOPAIR("\nxxx9->B =", results->B);
|
1617
|
|
- SERIAL_ECHOPAIR("\nxxx9->D =", results->D);
|
|
1617
|
+ results = lsf_linear_fit(xxx5, yyy5, zzz5, COUNT(xxx5));
|
|
1618
|
+ SERIAL_ECHOPAIR("\nxxx5->A =", results->A);
|
|
1619
|
+ SERIAL_ECHOPAIR("\nxxx5->B =", results->B);
|
|
1620
|
+ SERIAL_ECHOPAIR("\nxxx5->D =", results->D);
|
1618
|
1621
|
SERIAL_EOL;
|
1619
|
1622
|
|
1620
|
1623
|
results = lsf_linear_fit(xxx0, yyy0, zzz0, COUNT(xxx0));
|