|
|
@ -36,12 +36,11 @@ |
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#include "vector_3.h" |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_GRID) |
|
|
|
#include "qr_solve.h" |
|
|
|
#endif |
|
|
|
#endif // AUTO_BED_LEVELING_FEATURE
|
|
|
|
|
|
|
|
#if ENABLED(MESH_BED_LEVELING) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
#include "qr_solve.h" |
|
|
|
#elif ENABLED(MESH_BED_LEVELING) |
|
|
|
#include "mesh_bed_leveling.h" |
|
|
|
#endif |
|
|
|
|
|
|
@ -497,7 +496,12 @@ static uint8_t target_extruder; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
#if ENABLED(SCARA) |
|
|
|
#if IS_SCARA |
|
|
|
// Float constants for SCARA calculations
|
|
|
|
const float L1 = SCARA_LINKAGE_1, L2 = SCARA_LINKAGE_2, |
|
|
|
L1_2 = sq(float(L1)), L1_2_2 = 2.0 * L1_2, |
|
|
|
L2_2 = sq(float(L2)); |
|
|
|
|
|
|
|
float delta_segments_per_second = SCARA_SEGMENTS_PER_SECOND, |
|
|
|
delta[ABC], |
|
|
|
axis_scaling[ABC] = { 1, 1, 1 }, // Build size scaling, default to 1
|
|
|
@ -651,7 +655,7 @@ inline void sync_plan_position() { |
|
|
|
} |
|
|
|
inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); } |
|
|
|
|
|
|
|
#if ENABLED(DELTA) || ENABLED(SCARA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
inline void sync_plan_position_delta() { |
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE) |
|
|
|
if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_delta", current_position); |
|
|
@ -2161,7 +2165,7 @@ static void clean_up_after_endstop_or_probe_move() { |
|
|
|
// Prevent stepper_inactive_time from running out and EXTRUDER_RUNOUT_PREVENT from extruding
|
|
|
|
refresh_cmd_timeout(); |
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
planner.bed_level_matrix.set_to_identity(); |
|
|
|
#endif |
|
|
|
|
|
|
@ -2272,7 +2276,7 @@ static void clean_up_after_endstop_or_probe_move() { |
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
|
|
|
|
#if DISABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the stepper positions, apply the rotation matrix |
|
|
@ -2302,9 +2306,7 @@ static void clean_up_after_endstop_or_probe_move() { |
|
|
|
return pos; |
|
|
|
} |
|
|
|
|
|
|
|
#endif // !DELTA
|
|
|
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
|
|
|
|
/**
|
|
|
|
* All DELTA leveling in the Marlin uses NONLINEAR_BED_LEVELING |
|
|
@ -2870,7 +2872,7 @@ inline void gcode_G4() { |
|
|
|
SERIAL_ECHOPGM("Machine Type: "); |
|
|
|
#if ENABLED(DELTA) |
|
|
|
SERIAL_ECHOLNPGM("Delta"); |
|
|
|
#elif ENABLED(SCARA) |
|
|
|
#elif IS_SCARA |
|
|
|
SERIAL_ECHOLNPGM("SCARA"); |
|
|
|
#elif ENABLED(COREXY) || ENABLED(COREXZ) || ENABLED(COREYZ) |
|
|
|
SERIAL_ECHOLNPGM("Core"); |
|
|
@ -2947,11 +2949,12 @@ inline void gcode_G28() { |
|
|
|
stepper.synchronize(); |
|
|
|
|
|
|
|
// For auto bed leveling, clear the level matrix
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
planner.bed_level_matrix.set_to_identity(); |
|
|
|
#if ENABLED(DELTA) |
|
|
|
reset_bed_level(); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
reset_bed_level(); |
|
|
|
#endif |
|
|
|
|
|
|
|
// Always home with tool 0 active
|
|
|
@ -3533,7 +3536,7 @@ inline void gcode_G28() { |
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_GRID) |
|
|
|
|
|
|
|
#if DISABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
bool do_topography_map = verbose_level > 2 || code_seen('T'); |
|
|
|
#endif |
|
|
|
|
|
|
@ -3544,7 +3547,7 @@ inline void gcode_G28() { |
|
|
|
|
|
|
|
int auto_bed_leveling_grid_points = AUTO_BED_LEVELING_GRID_POINTS; |
|
|
|
|
|
|
|
#if DISABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
if (code_seen('P')) auto_bed_leveling_grid_points = code_value_int(); |
|
|
|
if (auto_bed_leveling_grid_points < 2) { |
|
|
|
SERIAL_PROTOCOLLNPGM("?Number of probed (P)oints is implausible (2 minimum)."); |
|
|
@ -3594,17 +3597,19 @@ inline void gcode_G28() { |
|
|
|
|
|
|
|
if (!dryrun) { |
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
// Reset the bed_level_matrix because leveling
|
|
|
|
// needs to be done without leveling enabled.
|
|
|
|
planner.bed_level_matrix.set_to_identity(); |
|
|
|
#endif |
|
|
|
|
|
|
|
//
|
|
|
|
// Re-orient the current position without leveling
|
|
|
|
// based on where the steppers are positioned.
|
|
|
|
//
|
|
|
|
#if ENABLED(DELTA) || ENABLED(SCARA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
reset_bed_level(); |
|
|
|
#endif |
|
|
|
|
|
|
@ -3639,12 +3644,14 @@ inline void gcode_G28() { |
|
|
|
const float xGridSpacing = (right_probe_bed_position - left_probe_bed_position) / (auto_bed_leveling_grid_points - 1), |
|
|
|
yGridSpacing = (back_probe_bed_position - front_probe_bed_position) / (auto_bed_leveling_grid_points - 1); |
|
|
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
delta_grid_spacing[X_AXIS] = xGridSpacing; |
|
|
|
delta_grid_spacing[Y_AXIS] = yGridSpacing; |
|
|
|
float zoffset = zprobe_zoffset; |
|
|
|
if (code_seen('Z')) zoffset += code_value_axis_units(Z_AXIS); |
|
|
|
#else // !DELTA
|
|
|
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
|
|
|
|
/**
|
|
|
|
* solve the plane equation ax + by + d = z |
|
|
|
* A is the matrix with rows [x y 1] for all the probed points |
|
|
@ -3660,7 +3667,8 @@ inline void gcode_G28() { |
|
|
|
eqnBVector[abl2], // "B" vector of Z points
|
|
|
|
mean = 0.0; |
|
|
|
int8_t indexIntoAB[auto_bed_leveling_grid_points][auto_bed_leveling_grid_points]; |
|
|
|
#endif // !DELTA
|
|
|
|
|
|
|
|
#endif // AUTO_BED_LEVELING_LINEAR
|
|
|
|
|
|
|
|
int probePointCounter = 0; |
|
|
|
bool zig = auto_bed_leveling_grid_points & 1; //always end at [RIGHT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION]
|
|
|
@ -3694,16 +3702,19 @@ inline void gcode_G28() { |
|
|
|
|
|
|
|
float measured_z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level); |
|
|
|
|
|
|
|
#if DISABLED(DELTA) |
|
|
|
mean += measured_z; |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
|
|
|
|
mean += measured_z; |
|
|
|
eqnBVector[probePointCounter] = measured_z; |
|
|
|
eqnAMatrix[probePointCounter + 0 * abl2] = xProbe; |
|
|
|
eqnAMatrix[probePointCounter + 1 * abl2] = yProbe; |
|
|
|
eqnAMatrix[probePointCounter + 2 * abl2] = 1; |
|
|
|
indexIntoAB[xCount][yCount] = probePointCounter; |
|
|
|
#else |
|
|
|
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
|
|
|
|
bed_level[xCount][yCount] = measured_z + zoffset; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
probePointCounter++; |
|
|
@ -3713,7 +3724,7 @@ inline void gcode_G28() { |
|
|
|
} //xProbe
|
|
|
|
} //yProbe
|
|
|
|
|
|
|
|
#else // !AUTO_BED_LEVELING_GRID
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_3POINT) |
|
|
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE) |
|
|
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> 3-point Leveling"); |
|
|
@ -3759,12 +3770,12 @@ inline void gcode_G28() { |
|
|
|
|
|
|
|
// Calculate leveling, print reports, correct the position
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_GRID) |
|
|
|
#if ENABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
|
|
|
|
if (!dryrun) extrapolate_unprobed_bed_level(); |
|
|
|
print_bed_level(); |
|
|
|
|
|
|
|
#else // !DELTA
|
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
|
|
|
|
// solve lsq problem
|
|
|
|
double plane_equation_coefficients[3]; |
|
|
@ -3860,11 +3871,11 @@ inline void gcode_G28() { |
|
|
|
} |
|
|
|
} //do_topography_map
|
|
|
|
|
|
|
|
#endif //!DELTA
|
|
|
|
#endif // AUTO_BED_LEVELING_LINEAR
|
|
|
|
|
|
|
|
#endif // AUTO_BED_LEVELING_GRID
|
|
|
|
|
|
|
|
#if DISABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
|
|
|
|
if (verbose_level > 0) |
|
|
|
planner.bed_level_matrix.debug("\n\nBed Level Correction Matrix:"); |
|
|
@ -4358,10 +4369,10 @@ inline void gcode_M42() { |
|
|
|
if (verbose_level > 2) |
|
|
|
SERIAL_PROTOCOLLNPGM("Positioning the probe..."); |
|
|
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
// we don't do bed level correction in M48 because we want the raw data when we probe
|
|
|
|
reset_bed_level(); |
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#elif ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
// we don't do bed level correction in M48 because we want the raw data when we probe
|
|
|
|
planner.bed_level_matrix.set_to_identity(); |
|
|
|
#endif |
|
|
@ -6361,7 +6372,7 @@ inline void gcode_M503() { |
|
|
|
lastpos[i] = destination[i] = current_position[i]; |
|
|
|
|
|
|
|
// Define runplan for move axes
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
#define RUNPLAN(RATE_MM_S) inverse_kinematics(destination); \ |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], destination[E_AXIS], RATE_MM_S, active_extruder); |
|
|
|
#else |
|
|
@ -6482,7 +6493,7 @@ inline void gcode_M503() { |
|
|
|
destination[E_AXIS] = lastpos[E_AXIS]; |
|
|
|
planner.set_e_position_mm(current_position[E_AXIS]); |
|
|
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
// Move XYZ to starting position, then E
|
|
|
|
inverse_kinematics(lastpos); |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], destination[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder); |
|
|
@ -6925,7 +6936,7 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n |
|
|
|
* Z software endstop. But this is technically correct (and |
|
|
|
* there is no viable alternative). |
|
|
|
*/ |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_LINEAR) |
|
|
|
// Offset extruder, make sure to apply the bed level rotation matrix
|
|
|
|
vector_3 tmp_offset_vec = vector_3(hotend_offset[X_AXIS][tmp_extruder], |
|
|
|
hotend_offset[Y_AXIS][tmp_extruder], |
|
|
@ -7961,7 +7972,7 @@ void ok_to_send() { |
|
|
|
stepper.get_axis_position_mm(C_AXIS)); |
|
|
|
} |
|
|
|
|
|
|
|
#if ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#if ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
|
|
|
|
// Adjust print surface height by linear interpolation over the bed_level array.
|
|
|
|
void adjust_delta(float cartesian[XYZ]) { |
|
|
@ -8001,7 +8012,7 @@ void ok_to_send() { |
|
|
|
SERIAL_ECHOPGM(" offset="); SERIAL_ECHOLN(offset); |
|
|
|
*/ |
|
|
|
} |
|
|
|
#endif // AUTO_BED_LEVELING_FEATURE
|
|
|
|
#endif // AUTO_BED_LEVELING_NONLINEAR
|
|
|
|
|
|
|
|
#endif // DELTA
|
|
|
|
|
|
|
@ -8076,7 +8087,7 @@ void mesh_line_to_destination(float fr_mm_s, uint8_t x_splits = 0xff, uint8_t y_ |
|
|
|
} |
|
|
|
#endif // MESH_BED_LEVELING
|
|
|
|
|
|
|
|
#if ENABLED(DELTA) || ENABLED(SCARA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
|
|
|
|
inline bool prepare_kinematic_move_to(float target[NUM_AXIS]) { |
|
|
|
float difference[NUM_AXIS]; |
|
|
@ -8103,7 +8114,7 @@ void mesh_line_to_destination(float fr_mm_s, uint8_t x_splits = 0xff, uint8_t y_ |
|
|
|
|
|
|
|
inverse_kinematics(target); |
|
|
|
|
|
|
|
#if ENABLED(DELTA) && ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#if ENABLED(DELTA) && ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
if (!bed_leveling_in_progress) adjust_delta(target); |
|
|
|
#endif |
|
|
|
|
|
|
@ -8115,7 +8126,7 @@ void mesh_line_to_destination(float fr_mm_s, uint8_t x_splits = 0xff, uint8_t y_ |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
#endif // DELTA || SCARA
|
|
|
|
#endif // IS_KINEMATIC
|
|
|
|
|
|
|
|
#if ENABLED(DUAL_X_CARRIAGE) |
|
|
|
|
|
|
@ -8161,7 +8172,7 @@ void mesh_line_to_destination(float fr_mm_s, uint8_t x_splits = 0xff, uint8_t y_ |
|
|
|
|
|
|
|
#endif // DUAL_X_CARRIAGE
|
|
|
|
|
|
|
|
#if DISABLED(DELTA) && DISABLED(SCARA) |
|
|
|
#if !IS_KINEMATIC |
|
|
|
|
|
|
|
inline bool prepare_move_to_destination_cartesian() { |
|
|
|
// Do not use feedrate_percentage for E or Z only moves
|
|
|
@ -8181,7 +8192,7 @@ void mesh_line_to_destination(float fr_mm_s, uint8_t x_splits = 0xff, uint8_t y_ |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
#endif // !DELTA && !SCARA
|
|
|
|
#endif // !IS_KINEMATIC
|
|
|
|
|
|
|
|
#if ENABLED(PREVENT_COLD_EXTRUSION) |
|
|
|
|
|
|
@ -8220,7 +8231,7 @@ void prepare_move_to_destination() { |
|
|
|
prevent_dangerous_extrude(current_position[E_AXIS], destination[E_AXIS]); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if ENABLED(DELTA) || ENABLED(SCARA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
if (!prepare_kinematic_move_to(destination)) return; |
|
|
|
#else |
|
|
|
#if ENABLED(DUAL_X_CARRIAGE) |
|
|
@ -8356,9 +8367,9 @@ void prepare_move_to_destination() { |
|
|
|
|
|
|
|
clamp_to_software_endstops(arc_target); |
|
|
|
|
|
|
|
#if ENABLED(DELTA) || ENABLED(SCARA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
inverse_kinematics(arc_target); |
|
|
|
#if ENABLED(DELTA) && ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#if ENABLED(DELTA) && ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
adjust_delta(arc_target); |
|
|
|
#endif |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], arc_target[E_AXIS], fr_mm_s, active_extruder); |
|
|
@ -8368,9 +8379,9 @@ void prepare_move_to_destination() { |
|
|
|
} |
|
|
|
|
|
|
|
// Ensure last segment arrives at target location.
|
|
|
|
#if ENABLED(DELTA) || ENABLED(SCARA) |
|
|
|
#if IS_KINEMATIC |
|
|
|
inverse_kinematics(target); |
|
|
|
#if ENABLED(DELTA) && ENABLED(AUTO_BED_LEVELING_FEATURE) |
|
|
|
#if ENABLED(DELTA) && ENABLED(AUTO_BED_LEVELING_NONLINEAR) |
|
|
|
adjust_delta(target); |
|
|
|
#endif |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], target[E_AXIS], fr_mm_s, active_extruder); |
|
|
|