|
@@ -2437,6 +2437,102 @@ static void clean_up_after_endstop_or_probe_move() {
|
2437
|
2437
|
SERIAL_EOL;
|
2438
|
2438
|
}
|
2439
|
2439
|
|
|
2440
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
2441
|
+ #define ABL_GRID_POINTS_VIRT_X (ABL_GRID_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1
|
|
2442
|
+ #define ABL_GRID_POINTS_VIRT_Y (ABL_GRID_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1
|
|
2443
|
+ float bed_level_grid_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
|
|
2444
|
+ float bed_level_grid_virt_temp[ABL_GRID_POINTS_X + 2][ABL_GRID_POINTS_Y + 2]; //temporary for calculation (maybe dynamical?)
|
|
2445
|
+ int bilinear_grid_spacing_virt[2] = { 0 };
|
|
2446
|
+
|
|
2447
|
+ static void bed_level_virt_print() {
|
|
2448
|
+ SERIAL_ECHOLNPGM("Subdivided with CATMULL ROM Leveling Grid:");
|
|
2449
|
+ for (uint8_t x = 0; x < ABL_GRID_POINTS_VIRT_X; x++) {
|
|
2450
|
+ SERIAL_PROTOCOLPGM(" ");
|
|
2451
|
+ if (x < 10) SERIAL_PROTOCOLCHAR(' ');
|
|
2452
|
+ SERIAL_PROTOCOL((int)x);
|
|
2453
|
+ }
|
|
2454
|
+ SERIAL_EOL;
|
|
2455
|
+ for (uint8_t y = 0; y < ABL_GRID_POINTS_VIRT_Y; y++) {
|
|
2456
|
+ if (y < 10) SERIAL_PROTOCOLCHAR(' ');
|
|
2457
|
+ SERIAL_PROTOCOL((int)y);
|
|
2458
|
+ for (uint8_t x = 0; x < ABL_GRID_POINTS_VIRT_X; x++) {
|
|
2459
|
+ SERIAL_PROTOCOLCHAR(' ');
|
|
2460
|
+ float offset = bed_level_grid_virt[x][y];
|
|
2461
|
+ if (offset < 999.0) {
|
|
2462
|
+ if (offset > 0) SERIAL_CHAR('+');
|
|
2463
|
+ SERIAL_PROTOCOL_F(offset, 5);
|
|
2464
|
+ }
|
|
2465
|
+ else
|
|
2466
|
+ SERIAL_PROTOCOLPGM(" ====");
|
|
2467
|
+ }
|
|
2468
|
+ SERIAL_EOL;
|
|
2469
|
+ }
|
|
2470
|
+ SERIAL_EOL;
|
|
2471
|
+ }
|
|
2472
|
+ #define LINEAR_EXTRAPOLATION(E, I) (E * 2 - I)
|
|
2473
|
+ static void bed_level_virt_prepare() {
|
|
2474
|
+ for (uint8_t y = 1; y <= ABL_GRID_POINTS_Y; y++) {
|
|
2475
|
+
|
|
2476
|
+ for (uint8_t x = 1; x <= ABL_GRID_POINTS_X; x++)
|
|
2477
|
+ bed_level_grid_virt_temp[x][y] = bed_level_grid[x - 1][y - 1];
|
|
2478
|
+
|
|
2479
|
+ bed_level_grid_virt_temp[0][y] = LINEAR_EXTRAPOLATION(
|
|
2480
|
+ bed_level_grid_virt_temp[1][y],
|
|
2481
|
+ bed_level_grid_virt_temp[2][y]
|
|
2482
|
+ );
|
|
2483
|
+
|
|
2484
|
+ bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 1][y] =
|
|
2485
|
+ LINEAR_EXTRAPOLATION(
|
|
2486
|
+ bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 2][y],
|
|
2487
|
+ bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 3][y]
|
|
2488
|
+ );
|
|
2489
|
+ }
|
|
2490
|
+ for (uint8_t x = 0; x < ABL_GRID_POINTS_X + 2; x++) {
|
|
2491
|
+ bed_level_grid_virt_temp[x][0] = LINEAR_EXTRAPOLATION(
|
|
2492
|
+ bed_level_grid_virt_temp[x][1],
|
|
2493
|
+ bed_level_grid_virt_temp[x][2]
|
|
2494
|
+ );
|
|
2495
|
+ bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 1] =
|
|
2496
|
+ LINEAR_EXTRAPOLATION(
|
|
2497
|
+ bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 2],
|
|
2498
|
+ bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 3]
|
|
2499
|
+ );
|
|
2500
|
+ }
|
|
2501
|
+ }
|
|
2502
|
+ static float bed_level_virt_cmr(const float p[4], const uint8_t i, const float t) {
|
|
2503
|
+ return (
|
|
2504
|
+ p[i-1] * -t * sq(1 - t)
|
|
2505
|
+ + p[i] * (2 - 5 * sq(t) + 3 * t * sq(t))
|
|
2506
|
+ + p[i+1] * t * (1 + 4 * t - 3 * sq(t))
|
|
2507
|
+ - p[i+2] * sq(t) * (1 - t)
|
|
2508
|
+ ) * 0.5;
|
|
2509
|
+ }
|
|
2510
|
+ static float bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const float &tx, const float &ty) {
|
|
2511
|
+ float row[4], column[4];
|
|
2512
|
+ for (uint8_t i = 0; i < 4; i++) {
|
|
2513
|
+ for (uint8_t j = 0; j < 4; j++) // can be memcopy or through memory access
|
|
2514
|
+ column[j] = bed_level_grid_virt_temp[i + x - 1][j + y - 1];
|
|
2515
|
+ row[i] = bed_level_virt_cmr(column, 1, ty);
|
|
2516
|
+ }
|
|
2517
|
+ return bed_level_virt_cmr(row, 1, tx);
|
|
2518
|
+ }
|
|
2519
|
+ static void bed_level_virt_interpolate() {
|
|
2520
|
+ for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++)
|
|
2521
|
+ for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++)
|
|
2522
|
+ for (uint8_t ty = 0; ty < BILINEAR_SUBDIVISIONS; ty++)
|
|
2523
|
+ for (uint8_t tx = 0; tx < BILINEAR_SUBDIVISIONS; tx++) {
|
|
2524
|
+ if ((ty && y == ABL_GRID_POINTS_Y - 1) || (tx && x == ABL_GRID_POINTS_X - 1))
|
|
2525
|
+ continue;
|
|
2526
|
+ bed_level_grid_virt[x * (BILINEAR_SUBDIVISIONS) + tx][y * (BILINEAR_SUBDIVISIONS) + ty] =
|
|
2527
|
+ bed_level_virt_2cmr(
|
|
2528
|
+ x + 1,
|
|
2529
|
+ y + 1,
|
|
2530
|
+ (float)tx / (BILINEAR_SUBDIVISIONS),
|
|
2531
|
+ (float)ty / (BILINEAR_SUBDIVISIONS)
|
|
2532
|
+ );
|
|
2533
|
+ }
|
|
2534
|
+ }
|
|
2535
|
+ #endif // ABL_BILINEAR_SUBDIVISION
|
2440
|
2536
|
#endif // AUTO_BED_LEVELING_BILINEAR
|
2441
|
2537
|
|
2442
|
2538
|
|
|
@@ -3922,6 +4018,10 @@ inline void gcode_G28() {
|
3922
|
4018
|
|| front_probe_bed_position != bilinear_start[Y_AXIS]
|
3923
|
4019
|
) {
|
3924
|
4020
|
reset_bed_level();
|
|
4021
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
4022
|
+ bilinear_grid_spacing_virt[X_AXIS] = xGridSpacing / (BILINEAR_SUBDIVISIONS);
|
|
4023
|
+ bilinear_grid_spacing_virt[Y_AXIS] = yGridSpacing / (BILINEAR_SUBDIVISIONS);
|
|
4024
|
+ #endif
|
3925
|
4025
|
bilinear_grid_spacing[X_AXIS] = xGridSpacing;
|
3926
|
4026
|
bilinear_grid_spacing[Y_AXIS] = yGridSpacing;
|
3927
|
4027
|
bilinear_start[X_AXIS] = RAW_X_POSITION(left_probe_bed_position);
|
|
@@ -4092,6 +4192,12 @@ inline void gcode_G28() {
|
4092
|
4192
|
if (!dryrun) extrapolate_unprobed_bed_level();
|
4093
|
4193
|
print_bed_level();
|
4094
|
4194
|
|
|
4195
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
4196
|
+ bed_level_virt_prepare();
|
|
4197
|
+ bed_level_virt_interpolate();
|
|
4198
|
+ bed_level_virt_print();
|
|
4199
|
+ #endif
|
|
4200
|
+
|
4095
|
4201
|
#elif ENABLED(AUTO_BED_LEVELING_LINEAR)
|
4096
|
4202
|
|
4097
|
4203
|
// For LINEAR leveling calculate matrix, print reports, correct the position
|
|
@@ -8631,6 +8737,18 @@ void ok_to_send() {
|
8631
|
8737
|
|
8632
|
8738
|
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
8633
|
8739
|
|
|
8740
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
8741
|
+ #define ABL_BG_SPACING(A) bilinear_grid_spacing_virt[A]
|
|
8742
|
+ #define ABL_BG_POINTS_X ABL_GRID_POINTS_VIRT_X
|
|
8743
|
+ #define ABL_BG_POINTS_Y ABL_GRID_POINTS_VIRT_Y
|
|
8744
|
+ #define ABL_BG_GRID(X,Y) bed_level_grid_virt[X][Y]
|
|
8745
|
+ #else
|
|
8746
|
+ #define ABL_BG_SPACING(A) bilinear_grid_spacing[A]
|
|
8747
|
+ #define ABL_BG_POINTS_X ABL_GRID_POINTS_X
|
|
8748
|
+ #define ABL_BG_POINTS_Y ABL_GRID_POINTS_Y
|
|
8749
|
+ #define ABL_BG_GRID(X,Y) bed_level_grid[X][Y]
|
|
8750
|
+ #endif
|
|
8751
|
+
|
8634
|
8752
|
// Get the Z adjustment for non-linear bed leveling
|
8635
|
8753
|
float bilinear_z_offset(float cartesian[XYZ]) {
|
8636
|
8754
|
|
|
@@ -8639,14 +8757,14 @@ void ok_to_send() {
|
8639
|
8757
|
y = RAW_Y_POSITION(cartesian[Y_AXIS]) - bilinear_start[Y_AXIS];
|
8640
|
8758
|
|
8641
|
8759
|
// Convert to grid box units
|
8642
|
|
- float ratio_x = x / bilinear_grid_spacing[X_AXIS],
|
8643
|
|
- ratio_y = y / bilinear_grid_spacing[Y_AXIS];
|
|
8760
|
+ float ratio_x = x / ABL_BG_SPACING(X_AXIS),
|
|
8761
|
+ ratio_y = y / ABL_BG_SPACING(Y_AXIS);
|
8644
|
8762
|
|
8645
|
8763
|
// Whole units for the grid line indices. Constrained within bounds.
|
8646
|
|
- const int gridx = constrain(floor(ratio_x), 0, ABL_GRID_POINTS_X - 1),
|
8647
|
|
- gridy = constrain(floor(ratio_y), 0, ABL_GRID_POINTS_Y - 1),
|
8648
|
|
- nextx = min(gridx + 1, ABL_GRID_POINTS_X - 1),
|
8649
|
|
- nexty = min(gridy + 1, ABL_GRID_POINTS_Y - 1);
|
|
8764
|
+ const int gridx = constrain(floor(ratio_x), 0, ABL_BG_POINTS_X - 1),
|
|
8765
|
+ gridy = constrain(floor(ratio_y), 0, ABL_BG_POINTS_Y - 1),
|
|
8766
|
+ nextx = min(gridx + 1, ABL_BG_POINTS_X - 1),
|
|
8767
|
+ nexty = min(gridy + 1, ABL_BG_POINTS_Y - 1);
|
8650
|
8768
|
|
8651
|
8769
|
// Subtract whole to get the ratio within the grid box
|
8652
|
8770
|
ratio_x -= gridx; ratio_y -= gridy;
|
|
@@ -8655,10 +8773,10 @@ void ok_to_send() {
|
8655
|
8773
|
NOLESS(ratio_x, 0); NOLESS(ratio_y, 0);
|
8656
|
8774
|
|
8657
|
8775
|
// Z at the box corners
|
8658
|
|
- const float z1 = bed_level_grid[gridx][gridy], // left-front
|
8659
|
|
- z2 = bed_level_grid[gridx][nexty], // left-back
|
8660
|
|
- z3 = bed_level_grid[nextx][gridy], // right-front
|
8661
|
|
- z4 = bed_level_grid[nextx][nexty], // right-back
|
|
8776
|
+ const float z1 = ABL_BG_GRID(gridx, gridy), // left-front
|
|
8777
|
+ z2 = ABL_BG_GRID(gridx, nexty), // left-back
|
|
8778
|
+ z3 = ABL_BG_GRID(nextx, gridy), // right-front
|
|
8779
|
+ z4 = ABL_BG_GRID(nextx, nexty), // right-back
|
8662
|
8780
|
|
8663
|
8781
|
// Bilinear interpolate
|
8664
|
8782
|
L = z1 + (z2 - z1) * ratio_y, // Linear interp. LF -> LB
|
|
@@ -9006,7 +9124,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
9006
|
9124
|
|
9007
|
9125
|
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) && !IS_KINEMATIC
|
9008
|
9126
|
|
9009
|
|
- #define CELL_INDEX(A,V) ((RAW_##A##_POSITION(V) - bilinear_start[A##_AXIS]) / bilinear_grid_spacing[A##_AXIS])
|
|
9127
|
+ #define CELL_INDEX(A,V) ((RAW_##A##_POSITION(V) - bilinear_start[A##_AXIS]) / ABL_BG_SPACING(A##_AXIS))
|
9010
|
9128
|
|
9011
|
9129
|
/**
|
9012
|
9130
|
* Prepare a bilinear-leveled linear move on Cartesian,
|
|
@@ -9017,10 +9135,10 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
9017
|
9135
|
cy1 = CELL_INDEX(Y, current_position[Y_AXIS]),
|
9018
|
9136
|
cx2 = CELL_INDEX(X, destination[X_AXIS]),
|
9019
|
9137
|
cy2 = CELL_INDEX(Y, destination[Y_AXIS]);
|
9020
|
|
- cx1 = constrain(cx1, 0, ABL_GRID_POINTS_X - 2);
|
9021
|
|
- cy1 = constrain(cy1, 0, ABL_GRID_POINTS_Y - 2);
|
9022
|
|
- cx2 = constrain(cx2, 0, ABL_GRID_POINTS_X - 2);
|
9023
|
|
- cy2 = constrain(cy2, 0, ABL_GRID_POINTS_Y - 2);
|
|
9138
|
+ cx1 = constrain(cx1, 0, ABL_BG_POINTS_X - 2);
|
|
9139
|
+ cy1 = constrain(cy1, 0, ABL_BG_POINTS_Y - 2);
|
|
9140
|
+ cx2 = constrain(cx2, 0, ABL_BG_POINTS_X - 2);
|
|
9141
|
+ cy2 = constrain(cy2, 0, ABL_BG_POINTS_Y - 2);
|
9024
|
9142
|
|
9025
|
9143
|
if (cx1 == cx2 && cy1 == cy2) {
|
9026
|
9144
|
// Start and end on same mesh square
|
|
@@ -9037,14 +9155,14 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
9037
|
9155
|
int8_t gcx = max(cx1, cx2), gcy = max(cy1, cy2);
|
9038
|
9156
|
if (cx2 != cx1 && TEST(x_splits, gcx)) {
|
9039
|
9157
|
memcpy(end, destination, sizeof(end));
|
9040
|
|
- destination[X_AXIS] = LOGICAL_X_POSITION(bilinear_start[X_AXIS] + bilinear_grid_spacing[X_AXIS] * gcx);
|
|
9158
|
+ destination[X_AXIS] = LOGICAL_X_POSITION(bilinear_start[X_AXIS] + ABL_BG_SPACING(X_AXIS) * gcx);
|
9041
|
9159
|
normalized_dist = (destination[X_AXIS] - current_position[X_AXIS]) / (end[X_AXIS] - current_position[X_AXIS]);
|
9042
|
9160
|
destination[Y_AXIS] = LINE_SEGMENT_END(Y);
|
9043
|
9161
|
CBI(x_splits, gcx);
|
9044
|
9162
|
}
|
9045
|
9163
|
else if (cy2 != cy1 && TEST(y_splits, gcy)) {
|
9046
|
9164
|
memcpy(end, destination, sizeof(end));
|
9047
|
|
- destination[Y_AXIS] = LOGICAL_Y_POSITION(bilinear_start[Y_AXIS] + bilinear_grid_spacing[Y_AXIS] * gcy);
|
|
9165
|
+ destination[Y_AXIS] = LOGICAL_Y_POSITION(bilinear_start[Y_AXIS] + ABL_BG_SPACING(Y_AXIS) * gcy);
|
9048
|
9166
|
normalized_dist = (destination[Y_AXIS] - current_position[Y_AXIS]) / (end[Y_AXIS] - current_position[Y_AXIS]);
|
9049
|
9167
|
destination[X_AXIS] = LINE_SEGMENT_END(X);
|
9050
|
9168
|
CBI(y_splits, gcy);
|