|
@@ -575,8 +575,9 @@ static uint8_t target_extruder;
|
575
|
575
|
#endif
|
576
|
576
|
|
577
|
577
|
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
578
|
|
- int bilinear_grid_spacing[2] = { 0 }, bilinear_start[2] = { 0 };
|
579
|
|
- float bed_level_grid[ABL_GRID_POINTS_X][ABL_GRID_POINTS_Y];
|
|
578
|
+ #define UNPROBED 9999.0f
|
|
579
|
+ int bilinear_grid_spacing[2], bilinear_start[2];
|
|
580
|
+ float bed_level_grid[ABL_GRID_MAX_POINTS_X][ABL_GRID_MAX_POINTS_Y];
|
580
|
581
|
#endif
|
581
|
582
|
|
582
|
583
|
#if IS_SCARA
|
|
@@ -2228,7 +2229,7 @@ static void clean_up_after_endstop_or_probe_move() {
|
2228
|
2229
|
* Disable: Current position = physical position
|
2229
|
2230
|
* Enable: Current position = "unleveled" physical position
|
2230
|
2231
|
*/
|
2231
|
|
- void set_bed_leveling_enabled(bool enable=true) {
|
|
2232
|
+ void set_bed_leveling_enabled(bool enable/*=true*/) {
|
2232
|
2233
|
#if ENABLED(MESH_BED_LEVELING)
|
2233
|
2234
|
|
2234
|
2235
|
if (enable != mbl.active()) {
|
|
@@ -2243,7 +2244,13 @@ static void clean_up_after_endstop_or_probe_move() {
|
2243
|
2244
|
|
2244
|
2245
|
#elif HAS_ABL
|
2245
|
2246
|
|
2246
|
|
- if (enable != planner.abl_enabled) {
|
|
2247
|
+ #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
2248
|
+ const bool can_change = (!enable || (bilinear_grid_spacing[0] && bilinear_grid_spacing[1]));
|
|
2249
|
+ #else
|
|
2250
|
+ constexpr bool can_change = true;
|
|
2251
|
+ #endif
|
|
2252
|
+
|
|
2253
|
+ if (can_change && enable != planner.abl_enabled) {
|
2247
|
2254
|
planner.abl_enabled = enable;
|
2248
|
2255
|
if (!enable)
|
2249
|
2256
|
set_current_from_steppers_for_axis(
|
|
@@ -2289,23 +2296,24 @@ static void clean_up_after_endstop_or_probe_move() {
|
2289
|
2296
|
* Reset calibration results to zero.
|
2290
|
2297
|
*/
|
2291
|
2298
|
void reset_bed_level() {
|
|
2299
|
+ set_bed_leveling_enabled(false);
|
2292
|
2300
|
#if ENABLED(MESH_BED_LEVELING)
|
2293
|
2301
|
if (mbl.has_mesh()) {
|
2294
|
|
- set_bed_leveling_enabled(false);
|
2295
|
2302
|
mbl.reset();
|
2296
|
2303
|
mbl.set_has_mesh(false);
|
2297
|
2304
|
}
|
2298
|
2305
|
#else
|
2299
|
|
- planner.abl_enabled = false;
|
2300
|
2306
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
2301
|
2307
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("reset_bed_level");
|
2302
|
2308
|
#endif
|
2303
|
2309
|
#if ABL_PLANAR
|
2304
|
2310
|
planner.bed_level_matrix.set_to_identity();
|
2305
|
2311
|
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
2306
|
|
- for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++)
|
2307
|
|
- for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++)
|
2308
|
|
- bed_level_grid[x][y] = 1000.0;
|
|
2312
|
+ bilinear_start[X_AXIS] = bilinear_start[Y_AXIS] =
|
|
2313
|
+ bilinear_grid_spacing[X_AXIS] = bilinear_grid_spacing[Y_AXIS] = 0;
|
|
2314
|
+ for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; x++)
|
|
2315
|
+ for (uint8_t y = 0; y < ABL_GRID_MAX_POINTS_Y; y++)
|
|
2316
|
+ bed_level_grid[x][y] = UNPROBED;
|
2309
|
2317
|
#endif
|
2310
|
2318
|
#endif
|
2311
|
2319
|
}
|
|
@@ -2331,7 +2339,7 @@ static void clean_up_after_endstop_or_probe_move() {
|
2331
|
2339
|
SERIAL_CHAR(']');
|
2332
|
2340
|
}
|
2333
|
2341
|
#endif
|
2334
|
|
- if (bed_level_grid[x][y] < 999.0) {
|
|
2342
|
+ if (bed_level_grid[x][y] != UNPROBED) {
|
2335
|
2343
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
2336
|
2344
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM(" (done)");
|
2337
|
2345
|
#endif
|
|
@@ -2345,13 +2353,13 @@ static void clean_up_after_endstop_or_probe_move() {
|
2345
|
2353
|
c1 = bed_level_grid[x + xdir][y + ydir], c2 = bed_level_grid[x + xdir * 2][y + ydir * 2];
|
2346
|
2354
|
|
2347
|
2355
|
// Treat far unprobed points as zero, near as equal to far
|
2348
|
|
- if (a2 > 999.0) a2 = 0.0; if (a1 > 999.0) a1 = a2;
|
2349
|
|
- if (b2 > 999.0) b2 = 0.0; if (b1 > 999.0) b1 = b2;
|
2350
|
|
- if (c2 > 999.0) c2 = 0.0; if (c1 > 999.0) c1 = c2;
|
|
2356
|
+ if (a2 == UNPROBED) a2 = 0.0; if (a1 == UNPROBED) a1 = a2;
|
|
2357
|
+ if (b2 == UNPROBED) b2 = 0.0; if (b1 == UNPROBED) b1 = b2;
|
|
2358
|
+ if (c2 == UNPROBED) c2 = 0.0; if (c1 == UNPROBED) c1 = c2;
|
2351
|
2359
|
|
2352
|
2360
|
float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2;
|
2353
|
2361
|
|
2354
|
|
- // Take the average intstead of the median
|
|
2362
|
+ // Take the average instead of the median
|
2355
|
2363
|
bed_level_grid[x][y] = (a + b + c) / 3.0;
|
2356
|
2364
|
|
2357
|
2365
|
// Median is robust (ignores outliers).
|
|
@@ -2363,9 +2371,9 @@ static void clean_up_after_endstop_or_probe_move() {
|
2363
|
2371
|
//#define EXTRAPOLATE_FROM_EDGE
|
2364
|
2372
|
|
2365
|
2373
|
#if ENABLED(EXTRAPOLATE_FROM_EDGE)
|
2366
|
|
- #if ABL_GRID_POINTS_X < ABL_GRID_POINTS_Y
|
|
2374
|
+ #if ABL_GRID_MAX_POINTS_X < ABL_GRID_MAX_POINTS_Y
|
2367
|
2375
|
#define HALF_IN_X
|
2368
|
|
- #elif ABL_GRID_POINTS_Y < ABL_GRID_POINTS_X
|
|
2376
|
+ #elif ABL_GRID_MAX_POINTS_Y < ABL_GRID_MAX_POINTS_X
|
2369
|
2377
|
#define HALF_IN_Y
|
2370
|
2378
|
#endif
|
2371
|
2379
|
#endif
|
|
@@ -2376,18 +2384,18 @@ static void clean_up_after_endstop_or_probe_move() {
|
2376
|
2384
|
*/
|
2377
|
2385
|
static void extrapolate_unprobed_bed_level() {
|
2378
|
2386
|
#ifdef HALF_IN_X
|
2379
|
|
- const uint8_t ctrx2 = 0, xlen = ABL_GRID_POINTS_X - 1;
|
|
2387
|
+ const uint8_t ctrx2 = 0, xlen = ABL_GRID_MAX_POINTS_X - 1;
|
2380
|
2388
|
#else
|
2381
|
|
- const uint8_t ctrx1 = (ABL_GRID_POINTS_X - 1) / 2, // left-of-center
|
2382
|
|
- ctrx2 = ABL_GRID_POINTS_X / 2, // right-of-center
|
|
2389
|
+ const uint8_t ctrx1 = (ABL_GRID_MAX_POINTS_X - 1) / 2, // left-of-center
|
|
2390
|
+ ctrx2 = ABL_GRID_MAX_POINTS_X / 2, // right-of-center
|
2383
|
2391
|
xlen = ctrx1;
|
2384
|
2392
|
#endif
|
2385
|
2393
|
|
2386
|
2394
|
#ifdef HALF_IN_Y
|
2387
|
|
- const uint8_t ctry2 = 0, ylen = ABL_GRID_POINTS_Y - 1;
|
|
2395
|
+ const uint8_t ctry2 = 0, ylen = ABL_GRID_MAX_POINTS_Y - 1;
|
2388
|
2396
|
#else
|
2389
|
|
- const uint8_t ctry1 = (ABL_GRID_POINTS_Y - 1) / 2, // top-of-center
|
2390
|
|
- ctry2 = ABL_GRID_POINTS_Y / 2, // bottom-of-center
|
|
2397
|
+ const uint8_t ctry1 = (ABL_GRID_MAX_POINTS_Y - 1) / 2, // top-of-center
|
|
2398
|
+ ctry2 = ABL_GRID_MAX_POINTS_Y / 2, // bottom-of-center
|
2391
|
2399
|
ylen = ctry1;
|
2392
|
2400
|
#endif
|
2393
|
2401
|
|
|
@@ -2415,21 +2423,21 @@ static void clean_up_after_endstop_or_probe_move() {
|
2415
|
2423
|
/**
|
2416
|
2424
|
* Print calibration results for plotting or manual frame adjustment.
|
2417
|
2425
|
*/
|
2418
|
|
- static void print_bed_level() {
|
|
2426
|
+ static void print_bilinear_leveling_grid() {
|
2419
|
2427
|
SERIAL_ECHOPGM("Bilinear Leveling Grid:\n ");
|
2420
|
|
- for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) {
|
|
2428
|
+ for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; x++) {
|
2421
|
2429
|
SERIAL_PROTOCOLPGM(" ");
|
2422
|
2430
|
if (x < 10) SERIAL_PROTOCOLCHAR(' ');
|
2423
|
2431
|
SERIAL_PROTOCOL((int)x);
|
2424
|
2432
|
}
|
2425
|
2433
|
SERIAL_EOL;
|
2426
|
|
- for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++) {
|
|
2434
|
+ for (uint8_t y = 0; y < ABL_GRID_MAX_POINTS_Y; y++) {
|
2427
|
2435
|
if (y < 10) SERIAL_PROTOCOLCHAR(' ');
|
2428
|
2436
|
SERIAL_PROTOCOL((int)y);
|
2429
|
|
- for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) {
|
|
2437
|
+ for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; x++) {
|
2430
|
2438
|
SERIAL_PROTOCOLCHAR(' ');
|
2431
|
2439
|
float offset = bed_level_grid[x][y];
|
2432
|
|
- if (offset < 999.0) {
|
|
2440
|
+ if (offset != UNPROBED) {
|
2433
|
2441
|
if (offset > 0) SERIAL_CHAR('+');
|
2434
|
2442
|
SERIAL_PROTOCOL_F(offset, 2);
|
2435
|
2443
|
}
|
|
@@ -2442,10 +2450,10 @@ static void clean_up_after_endstop_or_probe_move() {
|
2442
|
2450
|
}
|
2443
|
2451
|
|
2444
|
2452
|
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
2445
|
|
- #define ABL_GRID_POINTS_VIRT_X (ABL_GRID_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1
|
2446
|
|
- #define ABL_GRID_POINTS_VIRT_Y (ABL_GRID_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1
|
|
2453
|
+ #define ABL_GRID_POINTS_VIRT_X (ABL_GRID_MAX_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1
|
|
2454
|
+ #define ABL_GRID_POINTS_VIRT_Y (ABL_GRID_MAX_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1
|
2447
|
2455
|
float bed_level_grid_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
|
2448
|
|
- float bed_level_grid_virt_temp[ABL_GRID_POINTS_X + 2][ABL_GRID_POINTS_Y + 2]; //temporary for calculation (maybe dynamical?)
|
|
2456
|
+ float bed_level_grid_virt_temp[ABL_GRID_MAX_POINTS_X + 2][ABL_GRID_MAX_POINTS_Y + 2]; //temporary for calculation (maybe dynamical?)
|
2449
|
2457
|
int bilinear_grid_spacing_virt[2] = { 0 };
|
2450
|
2458
|
|
2451
|
2459
|
static void bed_level_virt_print() {
|
|
@@ -2462,7 +2470,7 @@ static void clean_up_after_endstop_or_probe_move() {
|
2462
|
2470
|
for (uint8_t x = 0; x < ABL_GRID_POINTS_VIRT_X; x++) {
|
2463
|
2471
|
SERIAL_PROTOCOLCHAR(' ');
|
2464
|
2472
|
float offset = bed_level_grid_virt[x][y];
|
2465
|
|
- if (offset < 999.0) {
|
|
2473
|
+ if (offset != UNPROBED) {
|
2466
|
2474
|
if (offset > 0) SERIAL_CHAR('+');
|
2467
|
2475
|
SERIAL_PROTOCOL_F(offset, 5);
|
2468
|
2476
|
}
|
|
@@ -2474,10 +2482,10 @@ static void clean_up_after_endstop_or_probe_move() {
|
2474
|
2482
|
SERIAL_EOL;
|
2475
|
2483
|
}
|
2476
|
2484
|
#define LINEAR_EXTRAPOLATION(E, I) (E * 2 - I)
|
2477
|
|
- static void bed_level_virt_prepare() {
|
2478
|
|
- for (uint8_t y = 1; y <= ABL_GRID_POINTS_Y; y++) {
|
|
2485
|
+ void bed_level_virt_prepare() {
|
|
2486
|
+ for (uint8_t y = 1; y <= ABL_GRID_MAX_POINTS_Y; y++) {
|
2479
|
2487
|
|
2480
|
|
- for (uint8_t x = 1; x <= ABL_GRID_POINTS_X; x++)
|
|
2488
|
+ for (uint8_t x = 1; x <= ABL_GRID_MAX_POINTS_X; x++)
|
2481
|
2489
|
bed_level_grid_virt_temp[x][y] = bed_level_grid[x - 1][y - 1];
|
2482
|
2490
|
|
2483
|
2491
|
bed_level_grid_virt_temp[0][y] = LINEAR_EXTRAPOLATION(
|
|
@@ -2485,21 +2493,21 @@ static void clean_up_after_endstop_or_probe_move() {
|
2485
|
2493
|
bed_level_grid_virt_temp[2][y]
|
2486
|
2494
|
);
|
2487
|
2495
|
|
2488
|
|
- bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 1][y] =
|
|
2496
|
+ bed_level_grid_virt_temp[(ABL_GRID_MAX_POINTS_X + 2) - 1][y] =
|
2489
|
2497
|
LINEAR_EXTRAPOLATION(
|
2490
|
|
- bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 2][y],
|
2491
|
|
- bed_level_grid_virt_temp[(ABL_GRID_POINTS_X + 2) - 3][y]
|
|
2498
|
+ bed_level_grid_virt_temp[(ABL_GRID_MAX_POINTS_X + 2) - 2][y],
|
|
2499
|
+ bed_level_grid_virt_temp[(ABL_GRID_MAX_POINTS_X + 2) - 3][y]
|
2492
|
2500
|
);
|
2493
|
2501
|
}
|
2494
|
|
- for (uint8_t x = 0; x < ABL_GRID_POINTS_X + 2; x++) {
|
|
2502
|
+ for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X + 2; x++) {
|
2495
|
2503
|
bed_level_grid_virt_temp[x][0] = LINEAR_EXTRAPOLATION(
|
2496
|
2504
|
bed_level_grid_virt_temp[x][1],
|
2497
|
2505
|
bed_level_grid_virt_temp[x][2]
|
2498
|
2506
|
);
|
2499
|
|
- bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 1] =
|
|
2507
|
+ bed_level_grid_virt_temp[x][(ABL_GRID_MAX_POINTS_Y + 2) - 1] =
|
2500
|
2508
|
LINEAR_EXTRAPOLATION(
|
2501
|
|
- bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 2],
|
2502
|
|
- bed_level_grid_virt_temp[x][(ABL_GRID_POINTS_Y + 2) - 3]
|
|
2509
|
+ bed_level_grid_virt_temp[x][(ABL_GRID_MAX_POINTS_Y + 2) - 2],
|
|
2510
|
+ bed_level_grid_virt_temp[x][(ABL_GRID_MAX_POINTS_Y + 2) - 3]
|
2503
|
2511
|
);
|
2504
|
2512
|
}
|
2505
|
2513
|
}
|
|
@@ -2520,12 +2528,12 @@ static void clean_up_after_endstop_or_probe_move() {
|
2520
|
2528
|
}
|
2521
|
2529
|
return bed_level_virt_cmr(row, 1, tx);
|
2522
|
2530
|
}
|
2523
|
|
- static void bed_level_virt_interpolate() {
|
2524
|
|
- for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++)
|
2525
|
|
- for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++)
|
|
2531
|
+ void bed_level_virt_interpolate() {
|
|
2532
|
+ for (uint8_t y = 0; y < ABL_GRID_MAX_POINTS_Y; y++)
|
|
2533
|
+ for (uint8_t x = 0; x < ABL_GRID_MAX_POINTS_X; x++)
|
2526
|
2534
|
for (uint8_t ty = 0; ty < BILINEAR_SUBDIVISIONS; ty++)
|
2527
|
2535
|
for (uint8_t tx = 0; tx < BILINEAR_SUBDIVISIONS; tx++) {
|
2528
|
|
- if ((ty && y == ABL_GRID_POINTS_Y - 1) || (tx && x == ABL_GRID_POINTS_X - 1))
|
|
2536
|
+ if ((ty && y == ABL_GRID_MAX_POINTS_Y - 1) || (tx && x == ABL_GRID_MAX_POINTS_X - 1))
|
2529
|
2537
|
continue;
|
2530
|
2538
|
bed_level_grid_virt[x * (BILINEAR_SUBDIVISIONS) + tx][y * (BILINEAR_SUBDIVISIONS) + ty] =
|
2531
|
2539
|
bed_level_virt_2cmr(
|
|
@@ -3422,9 +3430,9 @@ inline void gcode_G28() {
|
3422
|
3430
|
// Wait for planner moves to finish!
|
3423
|
3431
|
stepper.synchronize();
|
3424
|
3432
|
|
3425
|
|
- // For auto bed leveling, clear the level matrix
|
3426
|
|
- #if HAS_ABL
|
3427
|
|
- reset_bed_level();
|
|
3433
|
+ // Disable the leveling matrix before homing
|
|
3434
|
+ #if PLANNER_LEVELING
|
|
3435
|
+ set_bed_leveling_enabled(false);
|
3428
|
3436
|
#endif
|
3429
|
3437
|
|
3430
|
3438
|
// Always home with tool 0 active
|
|
@@ -3693,6 +3701,20 @@ inline void gcode_G28() {
|
3693
|
3701
|
// Save 130 bytes with non-duplication of PSTR
|
3694
|
3702
|
void say_not_entered() { SERIAL_PROTOCOLLNPGM(" not entered."); }
|
3695
|
3703
|
|
|
3704
|
+ void mbl_mesh_report() {
|
|
3705
|
+ SERIAL_PROTOCOLLNPGM("Num X,Y: " STRINGIFY(MESH_NUM_X_POINTS) "," STRINGIFY(MESH_NUM_Y_POINTS));
|
|
3706
|
+ SERIAL_PROTOCOLLNPGM("Z search height: " STRINGIFY(MESH_HOME_SEARCH_Z));
|
|
3707
|
+ SERIAL_PROTOCOLPGM("Z offset: "); SERIAL_PROTOCOL_F(mbl.z_offset, 5);
|
|
3708
|
+ SERIAL_PROTOCOLLNPGM("\nMeasured points:");
|
|
3709
|
+ for (uint8_t py = 0; py < MESH_NUM_Y_POINTS; py++) {
|
|
3710
|
+ for (uint8_t px = 0; px < MESH_NUM_X_POINTS; px++) {
|
|
3711
|
+ SERIAL_PROTOCOLPGM(" ");
|
|
3712
|
+ SERIAL_PROTOCOL_F(mbl.z_values[py][px], 5);
|
|
3713
|
+ }
|
|
3714
|
+ SERIAL_EOL;
|
|
3715
|
+ }
|
|
3716
|
+ }
|
|
3717
|
+
|
3696
|
3718
|
/**
|
3697
|
3719
|
* G29: Mesh-based Z probe, probes a grid and produces a
|
3698
|
3720
|
* mesh to compensate for variable bed height
|
|
@@ -3728,21 +3750,11 @@ inline void gcode_G28() {
|
3728
|
3750
|
switch (state) {
|
3729
|
3751
|
case MeshReport:
|
3730
|
3752
|
if (mbl.has_mesh()) {
|
3731
|
|
- SERIAL_PROTOCOLPAIR("State: ", mbl.active() ? MSG_ON : MSG_OFF);
|
3732
|
|
- SERIAL_PROTOCOLLNPGM("\nNum X,Y: " STRINGIFY(MESH_NUM_X_POINTS) "," STRINGIFY(MESH_NUM_Y_POINTS));
|
3733
|
|
- SERIAL_PROTOCOLLNPGM("Z search height: " STRINGIFY(MESH_HOME_SEARCH_Z));
|
3734
|
|
- SERIAL_PROTOCOLPGM("Z offset: "); SERIAL_PROTOCOL_F(mbl.z_offset, 5);
|
3735
|
|
- SERIAL_PROTOCOLLNPGM("\nMeasured points:");
|
3736
|
|
- for (py = 0; py < MESH_NUM_Y_POINTS; py++) {
|
3737
|
|
- for (px = 0; px < MESH_NUM_X_POINTS; px++) {
|
3738
|
|
- SERIAL_PROTOCOLPGM(" ");
|
3739
|
|
- SERIAL_PROTOCOL_F(mbl.z_values[py][px], 5);
|
3740
|
|
- }
|
3741
|
|
- SERIAL_EOL;
|
3742
|
|
- }
|
|
3753
|
+ SERIAL_PROTOCOLLNPAIR("State: ", mbl.active() ? MSG_ON : MSG_OFF);
|
|
3754
|
+ mbl_mesh_report();
|
3743
|
3755
|
}
|
3744
|
3756
|
else
|
3745
|
|
- SERIAL_PROTOCOLLNPGM("Mesh bed leveling not active.");
|
|
3757
|
+ SERIAL_PROTOCOLLNPGM("Mesh bed leveling has no data.");
|
3746
|
3758
|
break;
|
3747
|
3759
|
|
3748
|
3760
|
case MeshStart:
|
|
@@ -3863,7 +3875,7 @@ inline void gcode_G28() {
|
3863
|
3875
|
*
|
3864
|
3876
|
* Enhanced G29 Auto Bed Leveling Probe Routine
|
3865
|
3877
|
*
|
3866
|
|
- * Parameters With ABL_GRID:
|
|
3878
|
+ * Parameters With LINEAR and BILINEAR:
|
3867
|
3879
|
*
|
3868
|
3880
|
* P Set the size of the grid that will be probed (P x P points).
|
3869
|
3881
|
* Not supported by non-linear delta printer bed leveling.
|
|
@@ -3887,6 +3899,10 @@ inline void gcode_G28() {
|
3887
|
3899
|
* L Set the Left limit of the probing grid
|
3888
|
3900
|
* R Set the Right limit of the probing grid
|
3889
|
3901
|
*
|
|
3902
|
+ * Parameters with BILINEAR only:
|
|
3903
|
+ *
|
|
3904
|
+ * Z Supply an additional Z probe offset
|
|
3905
|
+ *
|
3890
|
3906
|
* Global Parameters:
|
3891
|
3907
|
*
|
3892
|
3908
|
* E/e By default G29 will engage the Z probe, test the bed, then disengage.
|
|
@@ -3934,8 +3950,8 @@ inline void gcode_G28() {
|
3934
|
3950
|
|
3935
|
3951
|
// X and Y specify points in each direction, overriding the default
|
3936
|
3952
|
// These values may be saved with the completed mesh
|
3937
|
|
- int abl_grid_points_x = code_seen('X') ? code_value_int() : ABL_GRID_POINTS_X,
|
3938
|
|
- abl_grid_points_y = code_seen('Y') ? code_value_int() : ABL_GRID_POINTS_Y;
|
|
3953
|
+ int abl_grid_points_x = code_seen('X') ? code_value_int() : ABL_GRID_MAX_POINTS_X,
|
|
3954
|
+ abl_grid_points_y = code_seen('Y') ? code_value_int() : ABL_GRID_MAX_POINTS_Y;
|
3939
|
3955
|
|
3940
|
3956
|
if (code_seen('P')) abl_grid_points_x = abl_grid_points_y = code_value_int();
|
3941
|
3957
|
|
|
@@ -3946,7 +3962,7 @@ inline void gcode_G28() {
|
3946
|
3962
|
|
3947
|
3963
|
#else
|
3948
|
3964
|
|
3949
|
|
- const int abl_grid_points_x = ABL_GRID_POINTS_X, abl_grid_points_y = ABL_GRID_POINTS_Y;
|
|
3965
|
+ const uint8_t abl_grid_points_x = ABL_GRID_MAX_POINTS_X, abl_grid_points_y = ABL_GRID_MAX_POINTS_Y;
|
3950
|
3966
|
|
3951
|
3967
|
#endif
|
3952
|
3968
|
|
|
@@ -4030,7 +4046,11 @@ inline void gcode_G28() {
|
4030
|
4046
|
|| left_probe_bed_position != bilinear_start[X_AXIS]
|
4031
|
4047
|
|| front_probe_bed_position != bilinear_start[Y_AXIS]
|
4032
|
4048
|
) {
|
|
4049
|
+ // Before reset bed level, re-enable to correct the position
|
|
4050
|
+ planner.abl_enabled = abl_should_enable;
|
|
4051
|
+ // Reset grid to 0.0 or "not probed". (Also disables ABL)
|
4033
|
4052
|
reset_bed_level();
|
|
4053
|
+
|
4034
|
4054
|
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
4035
|
4055
|
bilinear_grid_spacing_virt[X_AXIS] = xGridSpacing / (BILINEAR_SUBDIVISIONS);
|
4036
|
4056
|
bilinear_grid_spacing_virt[Y_AXIS] = yGridSpacing / (BILINEAR_SUBDIVISIONS);
|
|
@@ -4039,6 +4059,7 @@ inline void gcode_G28() {
|
4039
|
4059
|
bilinear_grid_spacing[Y_AXIS] = yGridSpacing;
|
4040
|
4060
|
bilinear_start[X_AXIS] = RAW_X_POSITION(left_probe_bed_position);
|
4041
|
4061
|
bilinear_start[Y_AXIS] = RAW_Y_POSITION(front_probe_bed_position);
|
|
4062
|
+
|
4042
|
4063
|
// Can't re-enable (on error) until the new grid is written
|
4043
|
4064
|
abl_should_enable = false;
|
4044
|
4065
|
}
|
|
@@ -4203,7 +4224,7 @@ inline void gcode_G28() {
|
4203
|
4224
|
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
4204
|
4225
|
|
4205
|
4226
|
if (!dryrun) extrapolate_unprobed_bed_level();
|
4206
|
|
- print_bed_level();
|
|
4227
|
+ print_bilinear_leveling_grid();
|
4207
|
4228
|
|
4208
|
4229
|
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
4209
|
4230
|
bed_level_virt_prepare();
|
|
@@ -4322,45 +4343,34 @@ inline void gcode_G28() {
|
4322
|
4343
|
// Correct the current XYZ position based on the tilted plane.
|
4323
|
4344
|
//
|
4324
|
4345
|
|
4325
|
|
- // 1. Get the distance from the current position to the reference point.
|
4326
|
|
- float x_dist = RAW_CURRENT_POSITION(X_AXIS) - X_TILT_FULCRUM,
|
4327
|
|
- y_dist = RAW_CURRENT_POSITION(Y_AXIS) - Y_TILT_FULCRUM,
|
4328
|
|
- z_real = current_position[Z_AXIS],
|
4329
|
|
- z_zero = 0;
|
4330
|
|
-
|
4331
|
4346
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
4332
|
4347
|
if (DEBUGGING(LEVELING)) DEBUG_POS("G29 uncorrected XYZ", current_position);
|
4333
|
4348
|
#endif
|
4334
|
4349
|
|
4335
|
|
- matrix_3x3 inverse = matrix_3x3::transpose(planner.bed_level_matrix);
|
4336
|
|
-
|
4337
|
|
- // 2. Apply the inverse matrix to the distance
|
4338
|
|
- // from the reference point to X, Y, and zero.
|
4339
|
|
- apply_rotation_xyz(inverse, x_dist, y_dist, z_zero);
|
|
4350
|
+ float converted[XYZ];
|
|
4351
|
+ memcpy(converted, current_position, sizeof(converted));
|
4340
|
4352
|
|
4341
|
|
- // 3. Get the matrix-based corrected Z.
|
4342
|
|
- // (Even if not used, get it for comparison.)
|
4343
|
|
- float new_z = z_real + z_zero;
|
|
4353
|
+ planner.abl_enabled = true;
|
|
4354
|
+ planner.unapply_leveling(converted); // use conversion machinery
|
|
4355
|
+ planner.abl_enabled = false;
|
4344
|
4356
|
|
4345
|
|
- // 4. Use the last measured distance to the bed, if possible
|
|
4357
|
+ // Use the last measured distance to the bed, if possible
|
4346
|
4358
|
if ( NEAR(current_position[X_AXIS], xProbe - (X_PROBE_OFFSET_FROM_EXTRUDER))
|
4347
|
4359
|
&& NEAR(current_position[Y_AXIS], yProbe - (Y_PROBE_OFFSET_FROM_EXTRUDER))
|
4348
|
4360
|
) {
|
4349
|
|
- float simple_z = z_real - (measured_z - (-zprobe_zoffset));
|
|
4361
|
+ float simple_z = current_position[Z_AXIS] - (measured_z - (-zprobe_zoffset));
|
4350
|
4362
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
4351
|
4363
|
if (DEBUGGING(LEVELING)) {
|
4352
|
4364
|
SERIAL_ECHOPAIR("Z from Probe:", simple_z);
|
4353
|
|
- SERIAL_ECHOPAIR(" Matrix:", new_z);
|
4354
|
|
- SERIAL_ECHOLNPAIR(" Discrepancy:", simple_z - new_z);
|
|
4365
|
+ SERIAL_ECHOPAIR(" Matrix:", converted[Z_AXIS]);
|
|
4366
|
+ SERIAL_ECHOLNPAIR(" Discrepancy:", simple_z - converted[Z_AXIS]);
|
4355
|
4367
|
}
|
4356
|
4368
|
#endif
|
4357
|
|
- new_z = simple_z;
|
|
4369
|
+ converted[Z_AXIS] = simple_z;
|
4358
|
4370
|
}
|
4359
|
4371
|
|
4360
|
|
- // 5. The rotated XY and corrected Z are now current_position
|
4361
|
|
- current_position[X_AXIS] = LOGICAL_X_POSITION(x_dist) + X_TILT_FULCRUM;
|
4362
|
|
- current_position[Y_AXIS] = LOGICAL_Y_POSITION(y_dist) + Y_TILT_FULCRUM;
|
4363
|
|
- current_position[Z_AXIS] = new_z;
|
|
4372
|
+ // The rotated XY and corrected Z are now current_position
|
|
4373
|
+ memcpy(current_position, converted, sizeof(converted));
|
4364
|
4374
|
|
4365
|
4375
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
4366
|
4376
|
if (DEBUGGING(LEVELING)) DEBUG_POS("G29 corrected XYZ", current_position);
|
|
@@ -5041,7 +5051,8 @@ inline void gcode_M42() {
|
5041
|
5051
|
|
5042
|
5052
|
// Disable bed level correction in M48 because we want the raw data when we probe
|
5043
|
5053
|
#if HAS_ABL
|
5044
|
|
- reset_bed_level();
|
|
5054
|
+ const bool abl_was_enabled = planner.abl_enabled;
|
|
5055
|
+ set_bed_leveling_enabled(false);
|
5045
|
5056
|
#endif
|
5046
|
5057
|
|
5047
|
5058
|
setup_for_endstop_or_probe_move();
|
|
@@ -5192,6 +5203,11 @@ inline void gcode_M42() {
|
5192
|
5203
|
|
5193
|
5204
|
clean_up_after_endstop_or_probe_move();
|
5194
|
5205
|
|
|
5206
|
+ // Re-enable bed level correction if it has been on
|
|
5207
|
+ #if HAS_ABL
|
|
5208
|
+ set_bed_leveling_enabled(abl_was_enabled);
|
|
5209
|
+ #endif
|
|
5210
|
+
|
5195
|
5211
|
report_current_position();
|
5196
|
5212
|
}
|
5197
|
5213
|
|
|
@@ -7000,12 +7016,54 @@ void quickstop_stepper() {
|
7000
|
7016
|
*
|
7001
|
7017
|
* S[bool] Turns leveling on or off
|
7002
|
7018
|
* Z[height] Sets the Z fade height (0 or none to disable)
|
|
7019
|
+ * V[bool] Verbose - Print the levelng grid
|
7003
|
7020
|
*/
|
7004
|
7021
|
inline void gcode_M420() {
|
7005
|
|
- if (code_seen('S')) set_bed_leveling_enabled(code_value_bool());
|
|
7022
|
+ bool to_enable = false;
|
|
7023
|
+
|
|
7024
|
+ if (code_seen('S')) {
|
|
7025
|
+ to_enable = code_value_bool();
|
|
7026
|
+ set_bed_leveling_enabled(to_enable);
|
|
7027
|
+ }
|
|
7028
|
+
|
7006
|
7029
|
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
7007
|
7030
|
if (code_seen('Z')) set_z_fade_height(code_value_linear_units());
|
7008
|
7031
|
#endif
|
|
7032
|
+
|
|
7033
|
+ if (to_enable && !(
|
|
7034
|
+ #if ENABLED(MESH_BED_LEVELING)
|
|
7035
|
+ mbl.active()
|
|
7036
|
+ #else
|
|
7037
|
+ planner.abl_enabled
|
|
7038
|
+ #endif
|
|
7039
|
+ ) ) {
|
|
7040
|
+ to_enable = false;
|
|
7041
|
+ SERIAL_ERROR_START;
|
|
7042
|
+ SERIAL_ERRORLNPGM(MSG_ERR_M420_FAILED);
|
|
7043
|
+ }
|
|
7044
|
+
|
|
7045
|
+ SERIAL_ECHO_START;
|
|
7046
|
+ SERIAL_ECHOLNPAIR("Bed Leveling ", to_enable ? MSG_ON : MSG_OFF);
|
|
7047
|
+
|
|
7048
|
+ // V to print the matrix or mesh
|
|
7049
|
+ if (code_seen('V')) {
|
|
7050
|
+ #if ABL_PLANAR
|
|
7051
|
+ planner.bed_level_matrix.debug("Bed Level Correction Matrix:");
|
|
7052
|
+ #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
7053
|
+ if (bilinear_grid_spacing[X_AXIS]) {
|
|
7054
|
+ print_bilinear_leveling_grid();
|
|
7055
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
7056
|
+ bed_level_virt_print();
|
|
7057
|
+ #endif
|
|
7058
|
+ }
|
|
7059
|
+ #elif ENABLED(MESH_BED_LEVELING)
|
|
7060
|
+ if (mbl.has_mesh()) {
|
|
7061
|
+ SERIAL_ECHOLNPGM("Mesh Bed Level data:");
|
|
7062
|
+ mbl_mesh_report();
|
|
7063
|
+ }
|
|
7064
|
+ #endif
|
|
7065
|
+ }
|
|
7066
|
+
|
7009
|
7067
|
}
|
7010
|
7068
|
#endif
|
7011
|
7069
|
|
|
@@ -7048,6 +7106,40 @@ void quickstop_stepper() {
|
7048
|
7106
|
}
|
7049
|
7107
|
}
|
7050
|
7108
|
|
|
7109
|
+#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
7110
|
+
|
|
7111
|
+ /**
|
|
7112
|
+ * M421: Set a single Mesh Bed Leveling Z coordinate
|
|
7113
|
+ *
|
|
7114
|
+ * M421 I<xindex> J<yindex> Z<linear>
|
|
7115
|
+ */
|
|
7116
|
+ inline void gcode_M421() {
|
|
7117
|
+ int8_t px = 0, py = 0;
|
|
7118
|
+ float z = 0;
|
|
7119
|
+ bool hasI, hasJ, hasZ;
|
|
7120
|
+ if ((hasI = code_seen('I'))) px = code_value_axis_units(X_AXIS);
|
|
7121
|
+ if ((hasJ = code_seen('J'))) py = code_value_axis_units(Y_AXIS);
|
|
7122
|
+ if ((hasZ = code_seen('Z'))) z = code_value_axis_units(Z_AXIS);
|
|
7123
|
+
|
|
7124
|
+ if (hasI && hasJ && hasZ) {
|
|
7125
|
+ if (px >= 0 && px < ABL_GRID_MAX_POINTS_X && py >= 0 && py < ABL_GRID_MAX_POINTS_X) {
|
|
7126
|
+ bed_level_grid[px][py] = z;
|
|
7127
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
7128
|
+ bed_level_virt_prepare();
|
|
7129
|
+ bed_level_virt_interpolate();
|
|
7130
|
+ #endif
|
|
7131
|
+ }
|
|
7132
|
+ else {
|
|
7133
|
+ SERIAL_ERROR_START;
|
|
7134
|
+ SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY);
|
|
7135
|
+ }
|
|
7136
|
+ }
|
|
7137
|
+ else {
|
|
7138
|
+ SERIAL_ERROR_START;
|
|
7139
|
+ SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS);
|
|
7140
|
+ }
|
|
7141
|
+ }
|
|
7142
|
+
|
7051
|
7143
|
#endif
|
7052
|
7144
|
|
7053
|
7145
|
/**
|
|
@@ -8757,8 +8849,8 @@ void ok_to_send() {
|
8757
|
8849
|
#define ABL_BG_GRID(X,Y) bed_level_grid_virt[X][Y]
|
8758
|
8850
|
#else
|
8759
|
8851
|
#define ABL_BG_SPACING(A) bilinear_grid_spacing[A]
|
8760
|
|
- #define ABL_BG_POINTS_X ABL_GRID_POINTS_X
|
8761
|
|
- #define ABL_BG_POINTS_Y ABL_GRID_POINTS_Y
|
|
8852
|
+ #define ABL_BG_POINTS_X ABL_GRID_MAX_POINTS_X
|
|
8853
|
+ #define ABL_BG_POINTS_Y ABL_GRID_MAX_POINTS_Y
|
8762
|
8854
|
#define ABL_BG_GRID(X,Y) bed_level_grid[X][Y]
|
8763
|
8855
|
#endif
|
8764
|
8856
|
|