|
@@ -353,10 +353,10 @@ static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
|
353
|
353
|
* the main loop. The process_next_command function parses the next
|
354
|
354
|
* command and hands off execution to individual handler functions.
|
355
|
355
|
*/
|
356
|
|
-static char command_queue[BUFSIZE][MAX_CMD_SIZE];
|
|
356
|
+uint8_t commands_in_queue = 0; // Count of commands in the queue
|
357
|
357
|
static uint8_t cmd_queue_index_r = 0, // Ring buffer read position
|
358
|
|
- cmd_queue_index_w = 0, // Ring buffer write position
|
359
|
|
- commands_in_queue = 0; // Count of commands in the queue
|
|
358
|
+ cmd_queue_index_w = 0; // Ring buffer write position
|
|
359
|
+static char command_queue[BUFSIZE][MAX_CMD_SIZE];
|
360
|
360
|
|
361
|
361
|
/**
|
362
|
362
|
* Current GCode Command
|
|
@@ -3502,6 +3502,12 @@ inline void gcode_G4() {
|
3502
|
3502
|
|
3503
|
3503
|
#endif // Z_SAFE_HOMING
|
3504
|
3504
|
|
|
3505
|
+#if ENABLED(PROBE_MANUALLY)
|
|
3506
|
+ static bool g29_in_progress = false;
|
|
3507
|
+#else
|
|
3508
|
+ constexpr bool g29_in_progress = false;
|
|
3509
|
+#endif
|
|
3510
|
+
|
3505
|
3511
|
/**
|
3506
|
3512
|
* G28: Home all axes according to settings
|
3507
|
3513
|
*
|
|
@@ -3529,6 +3535,11 @@ inline void gcode_G28() {
|
3529
|
3535
|
// Wait for planner moves to finish!
|
3530
|
3536
|
stepper.synchronize();
|
3531
|
3537
|
|
|
3538
|
+ // Cancel the active G29 session
|
|
3539
|
+ #if ENABLED(PROBE_MANUALLY)
|
|
3540
|
+ g29_in_progress = false;
|
|
3541
|
+ #endif
|
|
3542
|
+
|
3532
|
3543
|
// Disable the leveling matrix before homing
|
3533
|
3544
|
#if PLANNER_LEVELING
|
3534
|
3545
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
|
@@ -3719,9 +3730,9 @@ inline void gcode_G28() {
|
3719
|
3730
|
|
3720
|
3731
|
#endif
|
3721
|
3732
|
|
3722
|
|
-#if ENABLED(MESH_BED_LEVELING)
|
|
3733
|
+#if ENABLED(MESH_BED_LEVELING) || ENABLED(PROBE_MANUALLY)
|
3723
|
3734
|
|
3724
|
|
- inline void _mbl_goto_xy(const float &x, const float &y) {
|
|
3735
|
+ inline void _manual_goto_xy(const float &x, const float &y) {
|
3725
|
3736
|
const float old_feedrate_mm_s = feedrate_mm_s;
|
3726
|
3737
|
|
3727
|
3738
|
#if MANUAL_PROBE_HEIGHT > 0
|
|
@@ -3745,6 +3756,10 @@ inline void gcode_G28() {
|
3745
|
3756
|
stepper.synchronize();
|
3746
|
3757
|
}
|
3747
|
3758
|
|
|
3759
|
+#endif
|
|
3760
|
+
|
|
3761
|
+#if ENABLED(MESH_BED_LEVELING)
|
|
3762
|
+
|
3748
|
3763
|
// Save 130 bytes with non-duplication of PSTR
|
3749
|
3764
|
void say_not_entered() { SERIAL_PROTOCOLLNPGM(" not entered."); }
|
3750
|
3765
|
|
|
@@ -3835,7 +3850,7 @@ inline void gcode_G28() {
|
3835
|
3850
|
// If there's another point to sample, move there with optional lift.
|
3836
|
3851
|
if (mbl_probe_index < (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) {
|
3837
|
3852
|
mbl.zigzag(mbl_probe_index, px, py);
|
3838
|
|
- _mbl_goto_xy(mbl.index_to_xpos[px], mbl.index_to_ypos[py]);
|
|
3853
|
+ _manual_goto_xy(mbl.index_to_xpos[px], mbl.index_to_ypos[py]);
|
3839
|
3854
|
|
3840
|
3855
|
#if HAS_SOFTWARE_ENDSTOPS
|
3841
|
3856
|
// Disable software endstops to allow manual adjustment
|
|
@@ -3917,50 +3932,86 @@ inline void gcode_G28() {
|
3917
|
3932
|
|
3918
|
3933
|
#elif HAS_ABL && DISABLED(AUTO_BED_LEVELING_UBL)
|
3919
|
3934
|
|
|
3935
|
+ #if ABL_GRID
|
|
3936
|
+ #if ENABLED(PROBE_Y_FIRST)
|
|
3937
|
+ #define PR_OUTER_VAR xCount
|
|
3938
|
+ #define PR_OUTER_END abl_grid_points_x
|
|
3939
|
+ #define PR_INNER_VAR yCount
|
|
3940
|
+ #define PR_INNER_END abl_grid_points_y
|
|
3941
|
+ #else
|
|
3942
|
+ #define PR_OUTER_VAR yCount
|
|
3943
|
+ #define PR_OUTER_END abl_grid_points_y
|
|
3944
|
+ #define PR_INNER_VAR xCount
|
|
3945
|
+ #define PR_INNER_END abl_grid_points_x
|
|
3946
|
+ #endif
|
|
3947
|
+ #endif
|
|
3948
|
+
|
3920
|
3949
|
/**
|
3921
|
3950
|
* G29: Detailed Z probe, probes the bed at 3 or more points.
|
3922
|
3951
|
* Will fail if the printer has not been homed with G28.
|
3923
|
3952
|
*
|
3924
|
3953
|
* Enhanced G29 Auto Bed Leveling Probe Routine
|
3925
|
3954
|
*
|
3926
|
|
- * Parameters With LINEAR and BILINEAR:
|
|
3955
|
+ * D Dry-Run mode. Just evaluate the bed Topology - Don't apply
|
|
3956
|
+ * or alter the bed level data. Useful to check the topology
|
|
3957
|
+ * after a first run of G29.
|
|
3958
|
+ *
|
|
3959
|
+ * J Jettison current bed leveling data
|
|
3960
|
+ *
|
|
3961
|
+ * V Set the verbose level (0-4). Example: "G29 V3"
|
|
3962
|
+ *
|
|
3963
|
+ * Parameters With LINEAR leveling only:
|
3927
|
3964
|
*
|
3928
|
3965
|
* P Set the size of the grid that will be probed (P x P points).
|
3929
|
|
- * Not supported by non-linear delta printer bed leveling.
|
3930
|
3966
|
* Example: "G29 P4"
|
3931
|
3967
|
*
|
3932
|
|
- * S Set the XY travel speed between probe points (in units/min)
|
|
3968
|
+ * X Set the X size of the grid that will be probed (X x Y points).
|
|
3969
|
+ * Example: "G29 X7 Y5"
|
3933
|
3970
|
*
|
3934
|
|
- * D Dry-Run mode. Just evaluate the bed Topology - Don't apply
|
3935
|
|
- * or clean the rotation Matrix. Useful to check the topology
|
3936
|
|
- * after a first run of G29.
|
3937
|
|
- *
|
3938
|
|
- * V Set the verbose level (0-4). Example: "G29 V3"
|
|
3971
|
+ * Y Set the Y size of the grid that will be probed (X x Y points).
|
3939
|
3972
|
*
|
3940
|
3973
|
* T Generate a Bed Topology Report. Example: "G29 P5 T" for a detailed report.
|
3941
|
3974
|
* This is useful for manual bed leveling and finding flaws in the bed (to
|
3942
|
3975
|
* assist with part placement).
|
3943
|
3976
|
* Not supported by non-linear delta printer bed leveling.
|
3944
|
3977
|
*
|
|
3978
|
+ * Parameters With LINEAR and BILINEAR leveling only:
|
|
3979
|
+ *
|
|
3980
|
+ * S Set the XY travel speed between probe points (in units/min)
|
|
3981
|
+ *
|
3945
|
3982
|
* F Set the Front limit of the probing grid
|
3946
|
3983
|
* B Set the Back limit of the probing grid
|
3947
|
3984
|
* L Set the Left limit of the probing grid
|
3948
|
3985
|
* R Set the Right limit of the probing grid
|
3949
|
3986
|
*
|
3950
|
|
- * Parameters with BILINEAR only:
|
|
3987
|
+ * Parameters with BILINEAR leveling only:
|
3951
|
3988
|
*
|
3952
|
3989
|
* Z Supply an additional Z probe offset
|
3953
|
3990
|
*
|
3954
|
|
- * Global Parameters:
|
|
3991
|
+ * Extra parameters with PROBE_MANUALLY:
|
|
3992
|
+ *
|
|
3993
|
+ * To do manual probing simply repeat G29 until the procedure is complete.
|
|
3994
|
+ * The first G29 accepts parameters. 'G29 Q' for status, 'G29 A' to abort.
|
|
3995
|
+ *
|
|
3996
|
+ * Q Query leveling and G29 state
|
|
3997
|
+ *
|
|
3998
|
+ * A Abort current leveling procedure
|
|
3999
|
+ *
|
|
4000
|
+ * W Write a mesh point. (Ignored during leveling.)
|
|
4001
|
+ * X Required X for mesh point
|
|
4002
|
+ * Y Required Y for mesh point
|
|
4003
|
+ * Z Required Z for mesh point
|
3955
|
4004
|
*
|
3956
|
|
- * E/e By default G29 will engage the Z probe, test the bed, then disengage.
|
|
4005
|
+ * Without PROBE_MANUALLY:
|
|
4006
|
+ *
|
|
4007
|
+ * E By default G29 will engage the Z probe, test the bed, then disengage.
|
3957
|
4008
|
* Include "E" to engage/disengage the Z probe for each sample.
|
3958
|
4009
|
* There's no extra effect if you have a fixed Z probe.
|
3959
|
|
- * Usage: "G29 E" or "G29 e"
|
3960
|
4010
|
*
|
3961
|
4011
|
*/
|
3962
|
4012
|
inline void gcode_G29() {
|
3963
|
4013
|
|
|
4014
|
+ // G29 Q is also available if debugging
|
3964
|
4015
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
3965
|
4016
|
const bool query = code_seen('Q');
|
3966
|
4017
|
const uint8_t old_debug_flags = marlin_debug_flags;
|
|
@@ -3970,37 +4021,148 @@ inline void gcode_G28() {
|
3970
|
4021
|
log_machine_info();
|
3971
|
4022
|
}
|
3972
|
4023
|
marlin_debug_flags = old_debug_flags;
|
3973
|
|
- if (query) return;
|
|
4024
|
+ #if DISABLED(PROBE_MANUALLY)
|
|
4025
|
+ if (query) return;
|
|
4026
|
+ #endif
|
3974
|
4027
|
#endif
|
3975
|
4028
|
|
3976
|
4029
|
// Don't allow auto-leveling without homing first
|
3977
|
4030
|
if (axis_unhomed_error(true, true, true)) return;
|
3978
|
4031
|
|
3979
|
|
- const int verbose_level = code_seen('V') ? code_value_int() : 1;
|
3980
|
|
- if (verbose_level < 0 || verbose_level > 4) {
|
3981
|
|
- SERIAL_PROTOCOLLNPGM("?(V)erbose Level is implausible (0-4).");
|
3982
|
|
- return;
|
3983
|
|
- }
|
|
4032
|
+ // Define local vars 'static' for manual probing, 'auto' otherwise
|
|
4033
|
+ #if ENABLED(PROBE_MANUALLY)
|
|
4034
|
+ #define ABL_VAR static
|
|
4035
|
+ #else
|
|
4036
|
+ #define ABL_VAR
|
|
4037
|
+ #endif
|
3984
|
4038
|
|
3985
|
|
- bool dryrun = code_seen('D'),
|
3986
|
|
- stow_probe_after_each = code_seen('E');
|
|
4039
|
+ ABL_VAR int verbose_level, abl_probe_index;
|
|
4040
|
+ ABL_VAR float xProbe, yProbe, measured_z;
|
|
4041
|
+ ABL_VAR bool dryrun, abl_should_enable;
|
|
4042
|
+
|
|
4043
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
4044
|
+ ABL_VAR bool enable_soft_endstops = true;
|
|
4045
|
+ #endif
|
3987
|
4046
|
|
3988
|
4047
|
#if ABL_GRID
|
|
4048
|
+ ABL_VAR uint8_t PR_OUTER_VAR;
|
|
4049
|
+ ABL_VAR int8_t PR_INNER_VAR;
|
|
4050
|
+ ABL_VAR int left_probe_bed_position, right_probe_bed_position, front_probe_bed_position, back_probe_bed_position;
|
|
4051
|
+ ABL_VAR float xGridSpacing, yGridSpacing;
|
3989
|
4052
|
|
3990
|
|
- if (verbose_level > 0) {
|
3991
|
|
- SERIAL_PROTOCOLLNPGM("G29 Auto Bed Leveling");
|
3992
|
|
- if (dryrun) SERIAL_PROTOCOLLNPGM("Running in DRY-RUN mode");
|
3993
|
|
- }
|
|
4053
|
+ #define ABL_GRID_MAX (ABL_GRID_MAX_POINTS_X) * (ABL_GRID_MAX_POINTS_Y)
|
3994
|
4054
|
|
3995
|
4055
|
#if ABL_PLANAR
|
|
4056
|
+ ABL_VAR uint8_t abl_grid_points_x = ABL_GRID_MAX_POINTS_X,
|
|
4057
|
+ abl_grid_points_y = ABL_GRID_MAX_POINTS_Y;
|
|
4058
|
+ ABL_VAR int abl2;
|
|
4059
|
+ ABL_VAR bool do_topography_map;
|
|
4060
|
+ #else // 3-point
|
|
4061
|
+ uint8_t constexpr abl_grid_points_x = ABL_GRID_MAX_POINTS_X,
|
|
4062
|
+ abl_grid_points_y = ABL_GRID_MAX_POINTS_Y;
|
|
4063
|
+
|
|
4064
|
+ int constexpr abl2 = ABL_GRID_MAX;
|
|
4065
|
+ #endif
|
|
4066
|
+
|
|
4067
|
+ #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
4068
|
+
|
|
4069
|
+ ABL_VAR float zoffset;
|
|
4070
|
+
|
|
4071
|
+ #elif ENABLED(AUTO_BED_LEVELING_LINEAR)
|
|
4072
|
+
|
|
4073
|
+ ABL_VAR int indexIntoAB[ABL_GRID_MAX_POINTS_X][ABL_GRID_MAX_POINTS_Y];
|
|
4074
|
+
|
|
4075
|
+ ABL_VAR float eqnAMatrix[ABL_GRID_MAX * 3], // "A" matrix of the linear system of equations
|
|
4076
|
+ eqnBVector[ABL_GRID_MAX], // "B" vector of Z points
|
|
4077
|
+ mean;
|
|
4078
|
+ #endif
|
|
4079
|
+
|
|
4080
|
+ #elif ENABLED(AUTO_BED_LEVELING_3POINT)
|
|
4081
|
+
|
|
4082
|
+ // Probe at 3 arbitrary points
|
|
4083
|
+ ABL_VAR vector_3 points[3] = {
|
|
4084
|
+ vector_3(ABL_PROBE_PT_1_X, ABL_PROBE_PT_1_Y, 0),
|
|
4085
|
+ vector_3(ABL_PROBE_PT_2_X, ABL_PROBE_PT_2_Y, 0),
|
|
4086
|
+ vector_3(ABL_PROBE_PT_3_X, ABL_PROBE_PT_3_Y, 0)
|
|
4087
|
+ };
|
|
4088
|
+
|
|
4089
|
+ #endif // AUTO_BED_LEVELING_3POINT
|
3996
|
4090
|
|
3997
|
|
- bool do_topography_map = verbose_level > 2 || code_seen('T');
|
|
4091
|
+ /**
|
|
4092
|
+ * On the initial G29 fetch command parameters.
|
|
4093
|
+ */
|
|
4094
|
+ if (!g29_in_progress) {
|
|
4095
|
+
|
|
4096
|
+ abl_probe_index = 0;
|
|
4097
|
+ abl_should_enable = planner.abl_enabled;
|
|
4098
|
+
|
|
4099
|
+ #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
4100
|
+
|
|
4101
|
+ if (code_seen('W')) {
|
|
4102
|
+ if (!bilinear_grid_spacing[X_AXIS]) {
|
|
4103
|
+ SERIAL_ERROR_START;
|
|
4104
|
+ SERIAL_ERRORLNPGM("No bilinear grid");
|
|
4105
|
+ return;
|
|
4106
|
+ }
|
|
4107
|
+
|
|
4108
|
+ const float z = code_seen('Z') && code_has_value() ? code_value_float() : 99999;
|
|
4109
|
+ if (!WITHIN(z, -10, 10)) {
|
|
4110
|
+ SERIAL_ERROR_START;
|
|
4111
|
+ SERIAL_ERRORLNPGM("Bad Z value");
|
|
4112
|
+ return;
|
|
4113
|
+ }
|
|
4114
|
+
|
|
4115
|
+ const float x = code_seen('X') && code_has_value() ? code_value_float() : 99999,
|
|
4116
|
+ y = code_seen('Y') && code_has_value() ? code_value_float() : 99999;
|
|
4117
|
+ int8_t i = code_seen('I') && code_has_value() ? code_value_byte() : -1,
|
|
4118
|
+ j = code_seen('J') && code_has_value() ? code_value_byte() : -1;
|
|
4119
|
+
|
|
4120
|
+ if (x < 99998 && y < 99998) {
|
|
4121
|
+ // Get nearest i / j from x / y
|
|
4122
|
+ i = (x - LOGICAL_X_POSITION(bilinear_start[X_AXIS]) + 0.5 * xGridSpacing) / xGridSpacing;
|
|
4123
|
+ j = (y - LOGICAL_Y_POSITION(bilinear_start[Y_AXIS]) + 0.5 * yGridSpacing) / yGridSpacing;
|
|
4124
|
+ i = constrain(i, 0, ABL_GRID_MAX_POINTS_X - 1);
|
|
4125
|
+ j = constrain(j, 0, ABL_GRID_MAX_POINTS_Y - 1);
|
|
4126
|
+ }
|
|
4127
|
+ if (WITHIN(i, 0, ABL_GRID_MAX_POINTS_X - 1) && WITHIN(j, 0, ABL_GRID_MAX_POINTS_Y)) {
|
|
4128
|
+ set_bed_leveling_enabled(false);
|
|
4129
|
+ bed_level_grid[i][j] = z;
|
|
4130
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
4131
|
+ bed_level_virt_interpolate();
|
|
4132
|
+ #endif
|
|
4133
|
+ set_bed_leveling_enabled(abl_should_enable);
|
|
4134
|
+ }
|
|
4135
|
+ return;
|
|
4136
|
+ } // code_seen('W')
|
|
4137
|
+
|
|
4138
|
+ #endif
|
|
4139
|
+
|
|
4140
|
+ #if PLANNER_LEVELING
|
|
4141
|
+
|
|
4142
|
+ // Jettison bed leveling data
|
|
4143
|
+ if (code_seen('J')) {
|
|
4144
|
+ reset_bed_level();
|
|
4145
|
+ return;
|
|
4146
|
+ }
|
|
4147
|
+
|
|
4148
|
+ #endif
|
|
4149
|
+
|
|
4150
|
+ verbose_level = code_seen('V') && code_has_value() ? code_value_int() : 0;
|
|
4151
|
+ if (!WITHIN(verbose_level, 0, 4)) {
|
|
4152
|
+ SERIAL_PROTOCOLLNPGM("?(V)erbose Level is implausible (0-4).");
|
|
4153
|
+ return;
|
|
4154
|
+ }
|
|
4155
|
+
|
|
4156
|
+ dryrun = code_seen('D') ? code_value_bool() : false;
|
|
4157
|
+
|
|
4158
|
+ #if ENABLED(AUTO_BED_LEVELING_LINEAR)
|
|
4159
|
+
|
|
4160
|
+ do_topography_map = verbose_level > 2 || code_seen('T');
|
3998
|
4161
|
|
3999
|
4162
|
// X and Y specify points in each direction, overriding the default
|
4000
|
4163
|
// These values may be saved with the completed mesh
|
4001
|
|
- int abl_grid_points_x = code_seen('X') ? code_value_int() : ABL_GRID_MAX_POINTS_X,
|
4002
|
|
- abl_grid_points_y = code_seen('Y') ? code_value_int() : ABL_GRID_MAX_POINTS_Y;
|
4003
|
|
-
|
|
4164
|
+ abl_grid_points_x = code_seen('X') ? code_value_int() : ABL_GRID_MAX_POINTS_X;
|
|
4165
|
+ abl_grid_points_y = code_seen('Y') ? code_value_int() : ABL_GRID_MAX_POINTS_Y;
|
4004
|
4166
|
if (code_seen('P')) abl_grid_points_x = abl_grid_points_y = code_value_int();
|
4005
|
4167
|
|
4006
|
4168
|
if (abl_grid_points_x < 2 || abl_grid_points_y < 2) {
|
|
@@ -4008,91 +4170,98 @@ inline void gcode_G28() {
|
4008
|
4170
|
return;
|
4009
|
4171
|
}
|
4010
|
4172
|
|
4011
|
|
- #else
|
|
4173
|
+ abl2 = abl_grid_points_x * abl_grid_points_y;
|
4012
|
4174
|
|
4013
|
|
- const uint8_t abl_grid_points_x = ABL_GRID_MAX_POINTS_X, abl_grid_points_y = ABL_GRID_MAX_POINTS_Y;
|
|
4175
|
+ #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
4176
|
+
|
|
4177
|
+ zoffset = code_seen('Z') ? code_value_axis_units(Z_AXIS) : 0;
|
|
4178
|
+ #if HAS_BED_PROBE
|
|
4179
|
+ zoffset += zprobe_zoffset;
|
|
4180
|
+ #endif
|
4014
|
4181
|
|
4015
|
4182
|
#endif
|
4016
|
4183
|
|
4017
|
|
- xy_probe_feedrate_mm_s = MMM_TO_MMS(code_seen('S') ? code_value_linear_units() : XY_PROBE_SPEED);
|
|
4184
|
+ #if ABL_GRID
|
4018
|
4185
|
|
4019
|
|
- int left_probe_bed_position = code_seen('L') ? (int)code_value_axis_units(X_AXIS) : LOGICAL_X_POSITION(LEFT_PROBE_BED_POSITION),
|
4020
|
|
- right_probe_bed_position = code_seen('R') ? (int)code_value_axis_units(X_AXIS) : LOGICAL_X_POSITION(RIGHT_PROBE_BED_POSITION),
|
4021
|
|
- front_probe_bed_position = code_seen('F') ? (int)code_value_axis_units(Y_AXIS) : LOGICAL_Y_POSITION(FRONT_PROBE_BED_POSITION),
|
4022
|
|
- back_probe_bed_position = code_seen('B') ? (int)code_value_axis_units(Y_AXIS) : LOGICAL_Y_POSITION(BACK_PROBE_BED_POSITION);
|
|
4186
|
+ xy_probe_feedrate_mm_s = MMM_TO_MMS(code_seen('S') ? code_value_linear_units() : XY_PROBE_SPEED);
|
4023
|
4187
|
|
4024
|
|
- const bool left_out_l = left_probe_bed_position < LOGICAL_X_POSITION(MIN_PROBE_X),
|
4025
|
|
- left_out = left_out_l || left_probe_bed_position > right_probe_bed_position - (MIN_PROBE_EDGE),
|
4026
|
|
- right_out_r = right_probe_bed_position > LOGICAL_X_POSITION(MAX_PROBE_X),
|
4027
|
|
- right_out = right_out_r || right_probe_bed_position < left_probe_bed_position + MIN_PROBE_EDGE,
|
4028
|
|
- front_out_f = front_probe_bed_position < LOGICAL_Y_POSITION(MIN_PROBE_Y),
|
4029
|
|
- front_out = front_out_f || front_probe_bed_position > back_probe_bed_position - (MIN_PROBE_EDGE),
|
4030
|
|
- back_out_b = back_probe_bed_position > LOGICAL_Y_POSITION(MAX_PROBE_Y),
|
4031
|
|
- back_out = back_out_b || back_probe_bed_position < front_probe_bed_position + MIN_PROBE_EDGE;
|
|
4188
|
+ left_probe_bed_position = code_seen('L') ? (int)code_value_axis_units(X_AXIS) : LOGICAL_X_POSITION(LEFT_PROBE_BED_POSITION);
|
|
4189
|
+ right_probe_bed_position = code_seen('R') ? (int)code_value_axis_units(X_AXIS) : LOGICAL_X_POSITION(RIGHT_PROBE_BED_POSITION);
|
|
4190
|
+ front_probe_bed_position = code_seen('F') ? (int)code_value_axis_units(Y_AXIS) : LOGICAL_Y_POSITION(FRONT_PROBE_BED_POSITION);
|
|
4191
|
+ back_probe_bed_position = code_seen('B') ? (int)code_value_axis_units(Y_AXIS) : LOGICAL_Y_POSITION(BACK_PROBE_BED_POSITION);
|
4032
|
4192
|
|
4033
|
|
- if (left_out || right_out || front_out || back_out) {
|
4034
|
|
- if (left_out) {
|
4035
|
|
- out_of_range_error(PSTR("(L)eft"));
|
4036
|
|
- left_probe_bed_position = left_out_l ? LOGICAL_X_POSITION(MIN_PROBE_X) : right_probe_bed_position - (MIN_PROBE_EDGE);
|
4037
|
|
- }
|
4038
|
|
- if (right_out) {
|
4039
|
|
- out_of_range_error(PSTR("(R)ight"));
|
4040
|
|
- right_probe_bed_position = right_out_r ? LOGICAL_Y_POSITION(MAX_PROBE_X) : left_probe_bed_position + MIN_PROBE_EDGE;
|
4041
|
|
- }
|
4042
|
|
- if (front_out) {
|
4043
|
|
- out_of_range_error(PSTR("(F)ront"));
|
4044
|
|
- front_probe_bed_position = front_out_f ? LOGICAL_Y_POSITION(MIN_PROBE_Y) : back_probe_bed_position - (MIN_PROBE_EDGE);
|
4045
|
|
- }
|
4046
|
|
- if (back_out) {
|
4047
|
|
- out_of_range_error(PSTR("(B)ack"));
|
4048
|
|
- back_probe_bed_position = back_out_b ? LOGICAL_Y_POSITION(MAX_PROBE_Y) : front_probe_bed_position + MIN_PROBE_EDGE;
|
4049
|
|
- }
|
4050
|
|
- return;
|
4051
|
|
- }
|
|
4193
|
+ const bool left_out_l = left_probe_bed_position < LOGICAL_X_POSITION(MIN_PROBE_X),
|
|
4194
|
+ left_out = left_out_l || left_probe_bed_position > right_probe_bed_position - (MIN_PROBE_EDGE),
|
|
4195
|
+ right_out_r = right_probe_bed_position > LOGICAL_X_POSITION(MAX_PROBE_X),
|
|
4196
|
+ right_out = right_out_r || right_probe_bed_position < left_probe_bed_position + MIN_PROBE_EDGE,
|
|
4197
|
+ front_out_f = front_probe_bed_position < LOGICAL_Y_POSITION(MIN_PROBE_Y),
|
|
4198
|
+ front_out = front_out_f || front_probe_bed_position > back_probe_bed_position - (MIN_PROBE_EDGE),
|
|
4199
|
+ back_out_b = back_probe_bed_position > LOGICAL_Y_POSITION(MAX_PROBE_Y),
|
|
4200
|
+ back_out = back_out_b || back_probe_bed_position < front_probe_bed_position + MIN_PROBE_EDGE;
|
4052
|
4201
|
|
4053
|
|
- #endif // ABL_GRID
|
|
4202
|
+ if (left_out || right_out || front_out || back_out) {
|
|
4203
|
+ if (left_out) {
|
|
4204
|
+ out_of_range_error(PSTR("(L)eft"));
|
|
4205
|
+ left_probe_bed_position = left_out_l ? LOGICAL_X_POSITION(MIN_PROBE_X) : right_probe_bed_position - (MIN_PROBE_EDGE);
|
|
4206
|
+ }
|
|
4207
|
+ if (right_out) {
|
|
4208
|
+ out_of_range_error(PSTR("(R)ight"));
|
|
4209
|
+ right_probe_bed_position = right_out_r ? LOGICAL_Y_POSITION(MAX_PROBE_X) : left_probe_bed_position + MIN_PROBE_EDGE;
|
|
4210
|
+ }
|
|
4211
|
+ if (front_out) {
|
|
4212
|
+ out_of_range_error(PSTR("(F)ront"));
|
|
4213
|
+ front_probe_bed_position = front_out_f ? LOGICAL_Y_POSITION(MIN_PROBE_Y) : back_probe_bed_position - (MIN_PROBE_EDGE);
|
|
4214
|
+ }
|
|
4215
|
+ if (back_out) {
|
|
4216
|
+ out_of_range_error(PSTR("(B)ack"));
|
|
4217
|
+ back_probe_bed_position = back_out_b ? LOGICAL_Y_POSITION(MAX_PROBE_Y) : front_probe_bed_position + MIN_PROBE_EDGE;
|
|
4218
|
+ }
|
|
4219
|
+ return;
|
|
4220
|
+ }
|
4054
|
4221
|
|
4055
|
|
- stepper.synchronize();
|
|
4222
|
+ // probe at the points of a lattice grid
|
|
4223
|
+ xGridSpacing = (right_probe_bed_position - left_probe_bed_position) / (abl_grid_points_x - 1);
|
|
4224
|
+ yGridSpacing = (back_probe_bed_position - front_probe_bed_position) / (abl_grid_points_y - 1);
|
4056
|
4225
|
|
4057
|
|
- // Disable auto bed leveling during G29
|
4058
|
|
- bool abl_should_enable = planner.abl_enabled;
|
|
4226
|
+ #endif // ABL_GRID
|
4059
|
4227
|
|
4060
|
|
- planner.abl_enabled = false;
|
|
4228
|
+ if (verbose_level > 0) {
|
|
4229
|
+ SERIAL_PROTOCOLLNPGM("G29 Auto Bed Leveling");
|
|
4230
|
+ if (dryrun) SERIAL_PROTOCOLLNPGM("Running in DRY-RUN mode");
|
|
4231
|
+ }
|
4061
|
4232
|
|
4062
|
|
- if (!dryrun) {
|
4063
|
|
- // Re-orient the current position without leveling
|
4064
|
|
- // based on where the steppers are positioned.
|
4065
|
|
- set_current_from_steppers_for_axis(ALL_AXES);
|
|
4233
|
+ stepper.synchronize();
|
4066
|
4234
|
|
4067
|
|
- // Sync the planner to where the steppers stopped
|
4068
|
|
- SYNC_PLAN_POSITION_KINEMATIC();
|
4069
|
|
- }
|
|
4235
|
+ // Disable auto bed leveling during G29
|
|
4236
|
+ planner.abl_enabled = false;
|
4070
|
4237
|
|
4071
|
|
- setup_for_endstop_or_probe_move();
|
|
4238
|
+ if (!dryrun) {
|
|
4239
|
+ // Re-orient the current position without leveling
|
|
4240
|
+ // based on where the steppers are positioned.
|
|
4241
|
+ set_current_from_steppers_for_axis(ALL_AXES);
|
4072
|
4242
|
|
4073
|
|
- // Deploy the probe. Probe will raise if needed.
|
4074
|
|
- if (DEPLOY_PROBE()) {
|
4075
|
|
- planner.abl_enabled = abl_should_enable;
|
4076
|
|
- return;
|
4077
|
|
- }
|
|
4243
|
+ // Sync the planner to where the steppers stopped
|
|
4244
|
+ SYNC_PLAN_POSITION_KINEMATIC();
|
|
4245
|
+ }
|
4078
|
4246
|
|
4079
|
|
- float xProbe = 0, yProbe = 0, measured_z = 0;
|
|
4247
|
+ setup_for_endstop_or_probe_move();
|
4080
|
4248
|
|
4081
|
|
- #if ABL_GRID
|
|
4249
|
+ //xProbe = yProbe = measured_z = 0;
|
4082
|
4250
|
|
4083
|
|
- // probe at the points of a lattice grid
|
4084
|
|
- const float xGridSpacing = (right_probe_bed_position - left_probe_bed_position) / (abl_grid_points_x - 1),
|
4085
|
|
- yGridSpacing = (back_probe_bed_position - front_probe_bed_position) / (abl_grid_points_y - 1);
|
|
4251
|
+ #if HAS_BED_PROBE
|
|
4252
|
+ // Deploy the probe. Probe will raise if needed.
|
|
4253
|
+ if (DEPLOY_PROBE()) {
|
|
4254
|
+ planner.abl_enabled = abl_should_enable;
|
|
4255
|
+ return;
|
|
4256
|
+ }
|
|
4257
|
+ #endif
|
4086
|
4258
|
|
4087
|
4259
|
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
4088
|
4260
|
|
4089
|
|
- float zoffset = zprobe_zoffset;
|
4090
|
|
- if (code_seen('Z')) zoffset += code_value_axis_units(Z_AXIS);
|
4091
|
|
-
|
4092
|
4261
|
if ( xGridSpacing != bilinear_grid_spacing[X_AXIS]
|
4093
|
4262
|
|| yGridSpacing != bilinear_grid_spacing[Y_AXIS]
|
4094
|
|
- || left_probe_bed_position != bilinear_start[X_AXIS]
|
4095
|
|
- || front_probe_bed_position != bilinear_start[Y_AXIS]
|
|
4263
|
+ || left_probe_bed_position != LOGICAL_X_POSITION(bilinear_start[X_AXIS])
|
|
4264
|
+ || front_probe_bed_position != LOGICAL_Y_POSITION(bilinear_start[Y_AXIS])
|
4096
|
4265
|
) {
|
4097
|
4266
|
if (dryrun) {
|
4098
|
4267
|
// Before reset bed level, re-enable to correct the position
|
|
@@ -4101,164 +4270,311 @@ inline void gcode_G28() {
|
4101
|
4270
|
// Reset grid to 0.0 or "not probed". (Also disables ABL)
|
4102
|
4271
|
reset_bed_level();
|
4103
|
4272
|
|
4104
|
|
- #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
4105
|
|
- bilinear_grid_spacing_virt[X_AXIS] = xGridSpacing / (BILINEAR_SUBDIVISIONS);
|
4106
|
|
- bilinear_grid_spacing_virt[Y_AXIS] = yGridSpacing / (BILINEAR_SUBDIVISIONS);
|
4107
|
|
- #endif
|
|
4273
|
+ // Initialize a grid with the given dimensions
|
4108
|
4274
|
bilinear_grid_spacing[X_AXIS] = xGridSpacing;
|
4109
|
4275
|
bilinear_grid_spacing[Y_AXIS] = yGridSpacing;
|
4110
|
4276
|
bilinear_start[X_AXIS] = RAW_X_POSITION(left_probe_bed_position);
|
4111
|
4277
|
bilinear_start[Y_AXIS] = RAW_Y_POSITION(front_probe_bed_position);
|
4112
|
4278
|
|
|
4279
|
+ #if ENABLED(ABL_BILINEAR_SUBDIVISION)
|
|
4280
|
+ bilinear_grid_spacing_virt[X_AXIS] = xGridSpacing / (BILINEAR_SUBDIVISIONS);
|
|
4281
|
+ bilinear_grid_spacing_virt[Y_AXIS] = yGridSpacing / (BILINEAR_SUBDIVISIONS);
|
|
4282
|
+ #endif
|
|
4283
|
+
|
4113
|
4284
|
// Can't re-enable (on error) until the new grid is written
|
4114
|
4285
|
abl_should_enable = false;
|
4115
|
4286
|
}
|
4116
|
4287
|
|
4117
|
4288
|
#elif ENABLED(AUTO_BED_LEVELING_LINEAR)
|
4118
|
4289
|
|
4119
|
|
- /**
|
4120
|
|
- * solve the plane equation ax + by + d = z
|
4121
|
|
- * A is the matrix with rows [x y 1] for all the probed points
|
4122
|
|
- * B is the vector of the Z positions
|
4123
|
|
- * the normal vector to the plane is formed by the coefficients of the
|
4124
|
|
- * plane equation in the standard form, which is Vx*x+Vy*y+Vz*z+d = 0
|
4125
|
|
- * so Vx = -a Vy = -b Vz = 1 (we want the vector facing towards positive Z
|
4126
|
|
- */
|
|
4290
|
+ mean = 0.0;
|
4127
|
4291
|
|
4128
|
|
- const int abl2 = abl_grid_points_x * abl_grid_points_y;
|
|
4292
|
+ #endif // AUTO_BED_LEVELING_LINEAR
|
4129
|
4293
|
|
4130
|
|
- int indexIntoAB[abl_grid_points_x][abl_grid_points_y],
|
4131
|
|
- probe_index = -1;
|
|
4294
|
+ #if ENABLED(AUTO_BED_LEVELING_3POINT)
|
4132
|
4295
|
|
4133
|
|
- float eqnAMatrix[abl2 * 3], // "A" matrix of the linear system of equations
|
4134
|
|
- eqnBVector[abl2], // "B" vector of Z points
|
4135
|
|
- mean = 0.0;
|
|
4296
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
4297
|
+ if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> 3-point Leveling");
|
|
4298
|
+ #endif
|
4136
|
4299
|
|
4137
|
|
- #endif // AUTO_BED_LEVELING_LINEAR
|
|
4300
|
+ // Probe at 3 arbitrary points
|
|
4301
|
+ points[0].z = points[1].z = points[2].z = 0;
|
4138
|
4302
|
|
4139
|
|
- #if ENABLED(PROBE_Y_FIRST)
|
4140
|
|
- #define PR_OUTER_VAR xCount
|
4141
|
|
- #define PR_OUTER_NUM abl_grid_points_x
|
4142
|
|
- #define PR_INNER_VAR yCount
|
4143
|
|
- #define PR_INNER_NUM abl_grid_points_y
|
4144
|
|
- #else
|
4145
|
|
- #define PR_OUTER_VAR yCount
|
4146
|
|
- #define PR_OUTER_NUM abl_grid_points_y
|
4147
|
|
- #define PR_INNER_VAR xCount
|
4148
|
|
- #define PR_INNER_NUM abl_grid_points_x
|
4149
|
|
- #endif
|
|
4303
|
+ #endif // AUTO_BED_LEVELING_3POINT
|
4150
|
4304
|
|
4151
|
|
- bool zig = PR_OUTER_NUM & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION
|
|
4305
|
+ } // !g29_in_progress
|
4152
|
4306
|
|
4153
|
|
- // Outer loop is Y with PROBE_Y_FIRST disabled
|
4154
|
|
- for (uint8_t PR_OUTER_VAR = 0; PR_OUTER_VAR < PR_OUTER_NUM; PR_OUTER_VAR++) {
|
|
4307
|
+ #if ENABLED(PROBE_MANUALLY)
|
4155
|
4308
|
|
4156
|
|
- int8_t inStart, inStop, inInc;
|
|
4309
|
+ // Abort current G29 procedure, go back to ABLStart
|
|
4310
|
+ if (code_seen('A') && g29_in_progress) {
|
|
4311
|
+ SERIAL_PROTOCOLLNPGM("Manual G29 aborted");
|
|
4312
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
4313
|
+ soft_endstops_enabled = enable_soft_endstops;
|
|
4314
|
+ #endif
|
|
4315
|
+ planner.abl_enabled = abl_should_enable;
|
|
4316
|
+ g29_in_progress = false;
|
|
4317
|
+ }
|
4157
|
4318
|
|
4158
|
|
- if (zig) { // away from origin
|
4159
|
|
- inStart = 0;
|
4160
|
|
- inStop = PR_INNER_NUM;
|
4161
|
|
- inInc = 1;
|
4162
|
|
- }
|
4163
|
|
- else { // towards origin
|
4164
|
|
- inStart = PR_INNER_NUM - 1;
|
4165
|
|
- inStop = -1;
|
4166
|
|
- inInc = -1;
|
|
4319
|
+ // Query G29 status
|
|
4320
|
+ if (code_seen('Q')) {
|
|
4321
|
+ if (!g29_in_progress)
|
|
4322
|
+ SERIAL_PROTOCOLLNPGM("Manual G29 idle");
|
|
4323
|
+ else {
|
|
4324
|
+ SERIAL_PROTOCOLPAIR("Manual G29 point ", abl_probe_index + 1);
|
|
4325
|
+ SERIAL_PROTOCOLLNPAIR(" of ", abl2);
|
4167
|
4326
|
}
|
|
4327
|
+ }
|
|
4328
|
+
|
|
4329
|
+ if (code_seen('A') || code_seen('Q')) return;
|
4168
|
4330
|
|
4169
|
|
- zig = !zig; // zag
|
|
4331
|
+ // Fall through to probe the first point
|
|
4332
|
+ g29_in_progress = true;
|
|
4333
|
+
|
|
4334
|
+ if (abl_probe_index == 0) {
|
|
4335
|
+ // For the initial G29 S2 save software endstop state
|
|
4336
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
4337
|
+ enable_soft_endstops = soft_endstops_enabled;
|
|
4338
|
+ #endif
|
|
4339
|
+ }
|
|
4340
|
+ else {
|
|
4341
|
+ // For G29 after adjusting Z.
|
|
4342
|
+ // Save the previous Z before going to the next point
|
|
4343
|
+ measured_z = current_position[Z_AXIS];
|
|
4344
|
+
|
|
4345
|
+ #if ENABLED(AUTO_BED_LEVELING_LINEAR)
|
|
4346
|
+
|
|
4347
|
+ mean += measured_z;
|
|
4348
|
+ eqnBVector[abl_probe_index] = measured_z;
|
|
4349
|
+ eqnAMatrix[abl_probe_index + 0 * abl2] = xProbe;
|
|
4350
|
+ eqnAMatrix[abl_probe_index + 1 * abl2] = yProbe;
|
|
4351
|
+ eqnAMatrix[abl_probe_index + 2 * abl2] = 1;
|
|
4352
|
+
|
|
4353
|
+ #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
4170
|
4354
|
|
4171
|
|
- // Inner loop is Y with PROBE_Y_FIRST enabled
|
4172
|
|
- for (int8_t PR_INNER_VAR = inStart; PR_INNER_VAR != inStop; PR_INNER_VAR += inInc) {
|
|
4355
|
+ bed_level_grid[xCount][yCount] = measured_z + zoffset;
|
4173
|
4356
|
|
4174
|
|
- float xBase = left_probe_bed_position + xGridSpacing * xCount,
|
4175
|
|
- yBase = front_probe_bed_position + yGridSpacing * yCount;
|
|
4357
|
+ #elif ENABLED(AUTO_BED_LEVELING_3POINT)
|
|
4358
|
+
|
|
4359
|
+ points[i].z = measured_z;
|
|
4360
|
+
|
|
4361
|
+ #endif
|
|
4362
|
+ }
|
|
4363
|
+
|
|
4364
|
+ //
|
|
4365
|
+ // If there's another point to sample, move there with optional lift.
|
|
4366
|
+ //
|
|
4367
|
+
|
|
4368
|
+ #if ABL_GRID
|
|
4369
|
+
|
|
4370
|
+ // Find a next point to probe
|
|
4371
|
+ // On the first G29 this will be the first probe point
|
|
4372
|
+ while (abl_probe_index < abl2) {
|
|
4373
|
+
|
|
4374
|
+ // Set xCount, yCount based on abl_probe_index, with zig-zag
|
|
4375
|
+ PR_OUTER_VAR = abl_probe_index / PR_INNER_END;
|
|
4376
|
+ PR_INNER_VAR = abl_probe_index - (PR_OUTER_VAR * PR_INNER_END);
|
|
4377
|
+
|
|
4378
|
+ bool zig = (PR_OUTER_VAR & 1) != ((PR_OUTER_END) & 1);
|
|
4379
|
+
|
|
4380
|
+ if (zig) PR_INNER_VAR = (PR_INNER_END - 1) - PR_INNER_VAR;
|
|
4381
|
+
|
|
4382
|
+ const float xBase = left_probe_bed_position + xGridSpacing * xCount,
|
|
4383
|
+ yBase = front_probe_bed_position + yGridSpacing * yCount;
|
4176
|
4384
|
|
4177
|
4385
|
xProbe = floor(xBase + (xBase < 0 ? 0 : 0.5));
|
4178
|
4386
|
yProbe = floor(yBase + (yBase < 0 ? 0 : 0.5));
|
4179
|
4387
|
|
4180
|
4388
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR)
|
4181
|
|
- indexIntoAB[xCount][yCount] = ++probe_index;
|
|
4389
|
+ indexIntoAB[xCount][yCount] = abl_probe_index;
|
|
4390
|
+ #endif
|
|
4391
|
+
|
|
4392
|
+ float pos[XYZ] = { xProbe, yProbe, 0 };
|
|
4393
|
+ if (position_is_reachable(pos)) break;
|
|
4394
|
+ ++abl_probe_index;
|
|
4395
|
+ }
|
|
4396
|
+
|
|
4397
|
+ // Is there a next point to move to?
|
|
4398
|
+ if (abl_probe_index < abl2) {
|
|
4399
|
+ _manual_goto_xy(xProbe, yProbe); // Can be used here too!
|
|
4400
|
+ ++abl_probe_index;
|
|
4401
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
4402
|
+ // Disable software endstops to allow manual adjustment
|
|
4403
|
+ // If G29 is not completed, they will not be re-enabled
|
|
4404
|
+ soft_endstops_enabled = false;
|
4182
|
4405
|
#endif
|
|
4406
|
+ return;
|
|
4407
|
+ }
|
|
4408
|
+ else {
|
|
4409
|
+ // Then leveling is done!
|
|
4410
|
+ // G29 finishing code goes here
|
4183
|
4411
|
|
4184
|
|
- #if IS_KINEMATIC
|
4185
|
|
- // Avoid probing outside the round or hexagonal area
|
4186
|
|
- float pos[XYZ] = { xProbe, yProbe, 0 };
|
4187
|
|
- if (!position_is_reachable(pos, true)) continue;
|
|
4412
|
+ // After recording the last point, activate abl
|
|
4413
|
+ SERIAL_PROTOCOLLNPGM("Grid probing done.");
|
|
4414
|
+ g29_in_progress = false;
|
|
4415
|
+
|
|
4416
|
+ // Re-enable software endstops, if needed
|
|
4417
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
4418
|
+ soft_endstops_enabled = enable_soft_endstops;
|
4188
|
4419
|
#endif
|
|
4420
|
+ }
|
4189
|
4421
|
|
4190
|
|
- measured_z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
|
|
4422
|
+ #elif ENABLED(AUTO_BED_LEVELING_3POINT)
|
4191
|
4423
|
|
4192
|
|
- if (measured_z == NAN) {
|
4193
|
|
- planner.abl_enabled = abl_should_enable;
|
4194
|
|
- return;
|
|
4424
|
+ // Probe at 3 arbitrary points
|
|
4425
|
+ if (abl_probe_index < 3) {
|
|
4426
|
+ xProbe = LOGICAL_X_POSITION(points[i].x);
|
|
4427
|
+ yProbe = LOGICAL_Y_POSITION(points[i].y);
|
|
4428
|
+ ++abl_probe_index;
|
|
4429
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
4430
|
+ // Disable software endstops to allow manual adjustment
|
|
4431
|
+ // If G29 is not completed, they will not be re-enabled
|
|
4432
|
+ soft_endstops_enabled = false;
|
|
4433
|
+ #endif
|
|
4434
|
+ return;
|
|
4435
|
+ }
|
|
4436
|
+ else {
|
|
4437
|
+
|
|
4438
|
+ SERIAL_PROTOCOLLNPGM("3-point probing done.");
|
|
4439
|
+ g29_in_progress = false;
|
|
4440
|
+
|
|
4441
|
+ // Re-enable software endstops, if needed
|
|
4442
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
4443
|
+ soft_endstops_enabled = enable_soft_endstops;
|
|
4444
|
+ #endif
|
|
4445
|
+
|
|
4446
|
+ if (!dryrun) {
|
|
4447
|
+ vector_3 planeNormal = vector_3::cross(points[0] - points[1], points[2] - points[1]).get_normal();
|
|
4448
|
+ if (planeNormal.z < 0) {
|
|
4449
|
+ planeNormal.x *= -1;
|
|
4450
|
+ planeNormal.y *= -1;
|
|
4451
|
+ planeNormal.z *= -1;
|
|
4452
|
+ }
|
|
4453
|
+ planner.bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
|
|
4454
|
+
|
|
4455
|
+ // Can't re-enable (on error) until the new grid is written
|
|
4456
|
+ abl_should_enable = false;
|
4195
|
4457
|
}
|
4196
|
4458
|
|
4197
|
|
- #if ENABLED(AUTO_BED_LEVELING_LINEAR)
|
|
4459
|
+ }
|
4198
|
4460
|
|
4199
|
|
- mean += measured_z;
|
4200
|
|
- eqnBVector[probe_index] = measured_z;
|
4201
|
|
- eqnAMatrix[probe_index + 0 * abl2] = xProbe;
|
4202
|
|
- eqnAMatrix[probe_index + 1 * abl2] = yProbe;
|
4203
|
|
- eqnAMatrix[probe_index + 2 * abl2] = 1;
|
|
4461
|
+ #endif // AUTO_BED_LEVELING_3POINT
|
4204
|
4462
|
|
4205
|
|
- #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
4206
|
4463
|
|
4207
|
|
- bed_level_grid[xCount][yCount] = measured_z + zoffset;
|
|
4464
|
+ #else // !PROBE_MANUALLY
|
4208
|
4465
|
|
4209
|
|
- #endif
|
4210
|
4466
|
|
4211
|
|
- idle();
|
|
4467
|
+ bool stow_probe_after_each = code_seen('E');
|
4212
|
4468
|
|
4213
|
|
- } // inner
|
4214
|
|
- } // outer
|
|
4469
|
+ #if ABL_GRID
|
4215
|
4470
|
|
4216
|
|
- #elif ENABLED(AUTO_BED_LEVELING_3POINT)
|
|
4471
|
+ bool zig = PR_OUTER_END & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION
|
4217
|
4472
|
|
4218
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
4219
|
|
- if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> 3-point Leveling");
|
4220
|
|
- #endif
|
|
4473
|
+ // Outer loop is Y with PROBE_Y_FIRST disabled
|
|
4474
|
+ for (uint8_t PR_OUTER_VAR = 0; PR_OUTER_VAR < PR_OUTER_END; PR_OUTER_VAR++) {
|
4221
|
4475
|
|
4222
|
|
- // Probe at 3 arbitrary points
|
4223
|
|
- vector_3 points[3] = {
|
4224
|
|
- vector_3(ABL_PROBE_PT_1_X, ABL_PROBE_PT_1_Y, 0),
|
4225
|
|
- vector_3(ABL_PROBE_PT_2_X, ABL_PROBE_PT_2_Y, 0),
|
4226
|
|
- vector_3(ABL_PROBE_PT_3_X, ABL_PROBE_PT_3_Y, 0)
|
4227
|
|
- };
|
|
4476
|
+ int8_t inStart, inStop, inInc;
|
4228
|
4477
|
|
4229
|
|
- for (uint8_t i = 0; i < 3; ++i) {
|
4230
|
|
- // Retain the last probe position
|
4231
|
|
- xProbe = LOGICAL_X_POSITION(points[i].x);
|
4232
|
|
- yProbe = LOGICAL_Y_POSITION(points[i].y);
|
4233
|
|
- measured_z = points[i].z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
|
4234
|
|
- }
|
|
4478
|
+ if (zig) { // away from origin
|
|
4479
|
+ inStart = 0;
|
|
4480
|
+ inStop = PR_INNER_END;
|
|
4481
|
+ inInc = 1;
|
|
4482
|
+ }
|
|
4483
|
+ else { // towards origin
|
|
4484
|
+ inStart = PR_INNER_END - 1;
|
|
4485
|
+ inStop = -1;
|
|
4486
|
+ inInc = -1;
|
|
4487
|
+ }
|
4235
|
4488
|
|
4236
|
|
- if (measured_z == NAN) {
|
4237
|
|
- planner.abl_enabled = abl_should_enable;
|
4238
|
|
- return;
|
4239
|
|
- }
|
|
4489
|
+ zig = !zig; // zag
|
4240
|
4490
|
|
4241
|
|
- if (!dryrun) {
|
4242
|
|
- vector_3 planeNormal = vector_3::cross(points[0] - points[1], points[2] - points[1]).get_normal();
|
4243
|
|
- if (planeNormal.z < 0) {
|
4244
|
|
- planeNormal.x *= -1;
|
4245
|
|
- planeNormal.y *= -1;
|
4246
|
|
- planeNormal.z *= -1;
|
|
4491
|
+ // Inner loop is Y with PROBE_Y_FIRST enabled
|
|
4492
|
+ for (int8_t PR_INNER_VAR = inStart; PR_INNER_VAR != inStop; PR_INNER_VAR += inInc) {
|
|
4493
|
+
|
|
4494
|
+ float xBase = left_probe_bed_position + xGridSpacing * xCount,
|
|
4495
|
+ yBase = front_probe_bed_position + yGridSpacing * yCount;
|
|
4496
|
+
|
|
4497
|
+ xProbe = floor(xBase + (xBase < 0 ? 0 : 0.5));
|
|
4498
|
+ yProbe = floor(yBase + (yBase < 0 ? 0 : 0.5));
|
|
4499
|
+
|
|
4500
|
+ #if ENABLED(AUTO_BED_LEVELING_LINEAR)
|
|
4501
|
+ indexIntoAB[xCount][yCount] = ++abl_probe_index;
|
|
4502
|
+ #endif
|
|
4503
|
+
|
|
4504
|
+ #if IS_KINEMATIC
|
|
4505
|
+ // Avoid probing outside the round or hexagonal area
|
|
4506
|
+ float pos[XYZ] = { xProbe, yProbe, 0 };
|
|
4507
|
+ if (!position_is_reachable(pos, true)) continue;
|
|
4508
|
+ #endif
|
|
4509
|
+
|
|
4510
|
+ measured_z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
|
|
4511
|
+
|
|
4512
|
+ if (measured_z == NAN) {
|
|
4513
|
+ planner.abl_enabled = abl_should_enable;
|
|
4514
|
+ return;
|
|
4515
|
+ }
|
|
4516
|
+
|
|
4517
|
+ #if ENABLED(AUTO_BED_LEVELING_LINEAR)
|
|
4518
|
+
|
|
4519
|
+ mean += measured_z;
|
|
4520
|
+ eqnBVector[abl_probe_index] = measured_z;
|
|
4521
|
+ eqnAMatrix[abl_probe_index + 0 * abl2] = xProbe;
|
|
4522
|
+ eqnAMatrix[abl_probe_index + 1 * abl2] = yProbe;
|
|
4523
|
+ eqnAMatrix[abl_probe_index + 2 * abl2] = 1;
|
|
4524
|
+
|
|
4525
|
+ #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
4526
|
+
|
|
4527
|
+ bed_level_grid[xCount][yCount] = measured_z + zoffset;
|
|
4528
|
+
|
|
4529
|
+ #endif
|
|
4530
|
+
|
|
4531
|
+ abl_should_enable = false;
|
|
4532
|
+ idle();
|
|
4533
|
+
|
|
4534
|
+ } // inner
|
|
4535
|
+ } // outer
|
|
4536
|
+
|
|
4537
|
+ #elif ENABLED(AUTO_BED_LEVELING_3POINT)
|
|
4538
|
+
|
|
4539
|
+ // Probe at 3 arbitrary points
|
|
4540
|
+
|
|
4541
|
+ for (uint8_t i = 0; i < 3; ++i) {
|
|
4542
|
+ // Retain the last probe position
|
|
4543
|
+ xProbe = LOGICAL_X_POSITION(points[i].x);
|
|
4544
|
+ yProbe = LOGICAL_Y_POSITION(points[i].y);
|
|
4545
|
+ measured_z = points[i].z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
|
4247
|
4546
|
}
|
4248
|
|
- planner.bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
|
4249
|
4547
|
|
4250
|
|
- // Can't re-enable (on error) until the new grid is written
|
4251
|
|
- abl_should_enable = false;
|
4252
|
|
- }
|
|
4548
|
+ if (measured_z == NAN) {
|
|
4549
|
+ planner.abl_enabled = abl_should_enable;
|
|
4550
|
+ return;
|
|
4551
|
+ }
|
4253
|
4552
|
|
4254
|
|
- #endif // AUTO_BED_LEVELING_3POINT
|
|
4553
|
+ if (!dryrun) {
|
|
4554
|
+ vector_3 planeNormal = vector_3::cross(points[0] - points[1], points[2] - points[1]).get_normal();
|
|
4555
|
+ if (planeNormal.z < 0) {
|
|
4556
|
+ planeNormal.x *= -1;
|
|
4557
|
+ planeNormal.y *= -1;
|
|
4558
|
+ planeNormal.z *= -1;
|
|
4559
|
+ }
|
|
4560
|
+ planner.bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
|
4255
|
4561
|
|
4256
|
|
- // Raise to _Z_CLEARANCE_DEPLOY_PROBE. Stow the probe.
|
4257
|
|
- if (STOW_PROBE()) {
|
4258
|
|
- planner.abl_enabled = abl_should_enable;
|
4259
|
|
- return;
|
4260
|
|
- }
|
|
4562
|
+ // Can't re-enable (on error) until the new grid is written
|
|
4563
|
+ abl_should_enable = false;
|
|
4564
|
+ }
|
|
4565
|
+
|
|
4566
|
+ #endif // AUTO_BED_LEVELING_3POINT
|
4261
|
4567
|
|
|
4568
|
+ // Raise to _Z_CLEARANCE_DEPLOY_PROBE. Stow the probe.
|
|
4569
|
+ if (STOW_PROBE()) {
|
|
4570
|
+ planner.abl_enabled = abl_should_enable;
|
|
4571
|
+ return;
|
|
4572
|
+ }
|
|
4573
|
+
|
|
4574
|
+ #endif // !PROBE_MANUALLY
|
|
4575
|
+
|
|
4576
|
+ //
|
|
4577
|
+ // G29 Finishing Code
|
4262
|
4578
|
//
|
4263
|
4579
|
// Unless this is a dry run, auto bed leveling will
|
4264
|
4580
|
// definitely be enabled after this point
|
|
@@ -4286,7 +4602,14 @@ inline void gcode_G28() {
|
4286
|
4602
|
|
4287
|
4603
|
// For LINEAR leveling calculate matrix, print reports, correct the position
|
4288
|
4604
|
|
4289
|
|
- // solve lsq problem
|
|
4605
|
+ /**
|
|
4606
|
+ * solve the plane equation ax + by + d = z
|
|
4607
|
+ * A is the matrix with rows [x y 1] for all the probed points
|
|
4608
|
+ * B is the vector of the Z positions
|
|
4609
|
+ * the normal vector to the plane is formed by the coefficients of the
|
|
4610
|
+ * plane equation in the standard form, which is Vx*x+Vy*y+Vz*z+d = 0
|
|
4611
|
+ * so Vx = -a Vy = -b Vz = 1 (we want the vector facing towards positive Z
|
|
4612
|
+ */
|
4290
|
4613
|
float plane_equation_coefficients[3];
|
4291
|
4614
|
qr_solve(plane_equation_coefficients, abl2, 3, eqnAMatrix, eqnBVector);
|
4292
|
4615
|
|