|
@@ -31,6 +31,9 @@
|
31
|
31
|
|
32
|
32
|
#ifdef ENABLE_AUTO_BED_LEVELING
|
33
|
33
|
#include "vector_3.h"
|
|
34
|
+ #ifdef ACCURATE_BED_LEVELING
|
|
35
|
+ #include "qr_solve.h"
|
|
36
|
+ #endif
|
34
|
37
|
#endif // ENABLE_AUTO_BED_LEVELING
|
35
|
38
|
|
36
|
39
|
#include "ultralcd.h"
|
|
@@ -798,6 +801,35 @@ static void axis_is_at_home(int axis) {
|
798
|
801
|
}
|
799
|
802
|
|
800
|
803
|
#ifdef ENABLE_AUTO_BED_LEVELING
|
|
804
|
+#ifdef ACCURATE_BED_LEVELING
|
|
805
|
+static void set_bed_level_equation_lsq(double *plane_equation_coefficients)
|
|
806
|
+{
|
|
807
|
+ vector_3 planeNormal = vector_3(-plane_equation_coefficients[0], -plane_equation_coefficients[1], 1);
|
|
808
|
+ planeNormal.debug("planeNormal");
|
|
809
|
+ plan_bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
|
|
810
|
+ //bedLevel.debug("bedLevel");
|
|
811
|
+
|
|
812
|
+ plan_bed_level_matrix.debug("bed level before");
|
|
813
|
+ //vector_3 uncorrected_position = plan_get_position_mm();
|
|
814
|
+ //uncorrected_position.debug("position before");
|
|
815
|
+
|
|
816
|
+ // and set our bed level equation to do the right thing
|
|
817
|
+// plan_bed_level_matrix = matrix_3x3::create_inverse(bedLevel);
|
|
818
|
+// plan_bed_level_matrix.debug("bed level after");
|
|
819
|
+
|
|
820
|
+ vector_3 corrected_position = plan_get_position();
|
|
821
|
+// corrected_position.debug("position after");
|
|
822
|
+ current_position[X_AXIS] = corrected_position.x;
|
|
823
|
+ current_position[Y_AXIS] = corrected_position.y;
|
|
824
|
+ current_position[Z_AXIS] = corrected_position.z;
|
|
825
|
+
|
|
826
|
+ // but the bed at 0 so we don't go below it.
|
|
827
|
+ current_position[Z_AXIS] = -Z_PROBE_OFFSET_FROM_EXTRUDER; // in the lsq we reach here after raising the extruder due to the loop structure
|
|
828
|
+
|
|
829
|
+ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
|
|
830
|
+}
|
|
831
|
+
|
|
832
|
+#else
|
801
|
833
|
static void set_bed_level_equation(float z_at_xLeft_yFront, float z_at_xRight_yFront, float z_at_xLeft_yBack) {
|
802
|
834
|
plan_bed_level_matrix.set_to_identity();
|
803
|
835
|
|
|
@@ -832,6 +864,7 @@ static void set_bed_level_equation(float z_at_xLeft_yFront, float z_at_xRight_yF
|
832
|
864
|
|
833
|
865
|
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
|
834
|
866
|
}
|
|
867
|
+#endif // ACCURATE_BED_LEVELING
|
835
|
868
|
|
836
|
869
|
static void run_z_probe() {
|
837
|
870
|
plan_bed_level_matrix.set_to_identity();
|
|
@@ -1320,7 +1353,82 @@ void process_commands()
|
1320
|
1353
|
setup_for_endstop_move();
|
1321
|
1354
|
|
1322
|
1355
|
feedrate = homing_feedrate[Z_AXIS];
|
1323
|
|
-
|
|
1356
|
+#ifdef ACCURATE_BED_LEVELING
|
|
1357
|
+
|
|
1358
|
+ int xGridSpacing = (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION) / (ACCURATE_BED_LEVELING_POINTS-1);
|
|
1359
|
+ int yGridSpacing = (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION) / (ACCURATE_BED_LEVELING_POINTS-1);
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+ // solve the plane equation ax + by + d = z
|
|
1363
|
+ // A is the matrix with rows [x y 1] for all the probed points
|
|
1364
|
+ // B is the vector of the Z positions
|
|
1365
|
+ // the normal vector to the plane is formed by the coefficients of the plane equation in the standard form, which is Vx*x+Vy*y+Vz*z+d = 0
|
|
1366
|
+ // so Vx = -a Vy = -b Vz = 1 (we want the vector facing towards positive Z
|
|
1367
|
+
|
|
1368
|
+ // "A" matrix of the linear system of equations
|
|
1369
|
+ double eqnAMatrix[ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS*3];
|
|
1370
|
+ // "B" vector of Z points
|
|
1371
|
+ double eqnBVector[ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS];
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+ int probePointCounter = 0;
|
|
1375
|
+
|
|
1376
|
+ for (int xProbe=LEFT_PROBE_BED_POSITION; xProbe <= RIGHT_PROBE_BED_POSITION; xProbe += xGridSpacing)
|
|
1377
|
+ {
|
|
1378
|
+ for (int yProbe=FRONT_PROBE_BED_POSITION; yProbe <= BACK_PROBE_BED_POSITION; yProbe += yGridSpacing)
|
|
1379
|
+ {
|
|
1380
|
+ if (probePointCounter == 0)
|
|
1381
|
+ {
|
|
1382
|
+ // raise before probing
|
|
1383
|
+ do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_RAISE_BEFORE_PROBING);
|
|
1384
|
+ } else
|
|
1385
|
+ {
|
|
1386
|
+ // raise extruder
|
|
1387
|
+ do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS);
|
|
1388
|
+ }
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+ do_blocking_move_to(xProbe - X_PROBE_OFFSET_FROM_EXTRUDER, yProbe - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[Z_AXIS]);
|
|
1392
|
+
|
|
1393
|
+ engage_z_probe(); // Engage Z Servo endstop if available
|
|
1394
|
+ run_z_probe();
|
|
1395
|
+ eqnBVector[probePointCounter] = current_position[Z_AXIS];
|
|
1396
|
+ retract_z_probe();
|
|
1397
|
+
|
|
1398
|
+ SERIAL_PROTOCOLPGM("Bed x: ");
|
|
1399
|
+ SERIAL_PROTOCOL(xProbe);
|
|
1400
|
+ SERIAL_PROTOCOLPGM(" y: ");
|
|
1401
|
+ SERIAL_PROTOCOL(yProbe);
|
|
1402
|
+ SERIAL_PROTOCOLPGM(" z: ");
|
|
1403
|
+ SERIAL_PROTOCOL(current_position[Z_AXIS]);
|
|
1404
|
+ SERIAL_PROTOCOLPGM("\n");
|
|
1405
|
+
|
|
1406
|
+ eqnAMatrix[probePointCounter + 0*ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS] = xProbe;
|
|
1407
|
+ eqnAMatrix[probePointCounter + 1*ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS] = yProbe;
|
|
1408
|
+ eqnAMatrix[probePointCounter + 2*ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS] = 1;
|
|
1409
|
+ probePointCounter++;
|
|
1410
|
+ }
|
|
1411
|
+ }
|
|
1412
|
+ clean_up_after_endstop_move();
|
|
1413
|
+
|
|
1414
|
+ // solve lsq problem
|
|
1415
|
+ double *plane_equation_coefficients = qr_solve(ACCURATE_BED_LEVELING_POINTS*ACCURATE_BED_LEVELING_POINTS, 3, eqnAMatrix, eqnBVector);
|
|
1416
|
+
|
|
1417
|
+ SERIAL_PROTOCOLPGM("Eqn coefficients: a: ");
|
|
1418
|
+ SERIAL_PROTOCOL(plane_equation_coefficients[0]);
|
|
1419
|
+ SERIAL_PROTOCOLPGM(" b: ");
|
|
1420
|
+ SERIAL_PROTOCOL(plane_equation_coefficients[1]);
|
|
1421
|
+ SERIAL_PROTOCOLPGM(" d: ");
|
|
1422
|
+ SERIAL_PROTOCOLLN(plane_equation_coefficients[2]);
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+ set_bed_level_equation_lsq(plane_equation_coefficients);
|
|
1426
|
+
|
|
1427
|
+ free(plane_equation_coefficients);
|
|
1428
|
+
|
|
1429
|
+#else // ACCURATE_BED_LEVELING not defined
|
|
1430
|
+
|
|
1431
|
+
|
1324
|
1432
|
// prob 1
|
1325
|
1433
|
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_RAISE_BEFORE_PROBING);
|
1326
|
1434
|
do_blocking_move_to(LEFT_PROBE_BED_POSITION - X_PROBE_OFFSET_FROM_EXTRUDER, BACK_PROBE_BED_POSITION - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[Z_AXIS]);
|
|
@@ -1376,7 +1484,9 @@ void process_commands()
|
1376
|
1484
|
clean_up_after_endstop_move();
|
1377
|
1485
|
|
1378
|
1486
|
set_bed_level_equation(z_at_xLeft_yFront, z_at_xRight_yFront, z_at_xLeft_yBack);
|
1379
|
|
-
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+#endif // ACCURATE_BED_LEVELING
|
1380
|
1490
|
st_synchronize();
|
1381
|
1491
|
|
1382
|
1492
|
// The following code correct the Z height difference from z-probe position and hotend tip position.
|