Add custom types for position (#15204)
This commit is contained in:
@ -59,7 +59,7 @@
|
||||
static void quick_home_xy() {
|
||||
|
||||
// Pretend the current position is 0,0
|
||||
current_position[X_AXIS] = current_position[Y_AXIS] = 0.0;
|
||||
current_position.set(0.0, 0.0);
|
||||
sync_plan_position();
|
||||
|
||||
const int x_axis_home_dir =
|
||||
@ -95,7 +95,7 @@
|
||||
|
||||
endstops.validate_homing_move();
|
||||
|
||||
current_position[X_AXIS] = current_position[Y_AXIS] = 0.0;
|
||||
current_position.set(0.0, 0.0);
|
||||
|
||||
#if ENABLED(SENSORLESS_HOMING)
|
||||
tmc_disable_stallguard(stepperX, stealth_states.x);
|
||||
@ -128,17 +128,15 @@
|
||||
|
||||
/**
|
||||
* Move the Z probe (or just the nozzle) to the safe homing point
|
||||
* (Z is already at the right height)
|
||||
*/
|
||||
destination[X_AXIS] = Z_SAFE_HOMING_X_POINT;
|
||||
destination[Y_AXIS] = Z_SAFE_HOMING_Y_POINT;
|
||||
destination[Z_AXIS] = current_position[Z_AXIS]; // Z is already at the right height
|
||||
destination.set(safe_homing_xy, current_position.z);
|
||||
|
||||
#if HOMING_Z_WITH_PROBE
|
||||
destination[X_AXIS] -= probe_offset[X_AXIS];
|
||||
destination[Y_AXIS] -= probe_offset[Y_AXIS];
|
||||
destination -= probe_offset;
|
||||
#endif
|
||||
|
||||
if (position_is_reachable(destination[X_AXIS], destination[Y_AXIS])) {
|
||||
if (position_is_reachable(destination)) {
|
||||
|
||||
if (DEBUGGING(LEVELING)) DEBUG_POS("home_z_safely", destination);
|
||||
|
||||
@ -151,7 +149,7 @@
|
||||
safe_delay(500); // Short delay needed to settle
|
||||
#endif
|
||||
|
||||
do_blocking_move_to_xy(destination[X_AXIS], destination[Y_AXIS]);
|
||||
do_blocking_move_to_xy(destination);
|
||||
homeaxis(Z_AXIS);
|
||||
}
|
||||
else {
|
||||
@ -232,16 +230,14 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
#endif
|
||||
|
||||
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
|
||||
slow_homing_t slow_homing { 0 };
|
||||
slow_homing.acceleration.x = planner.settings.max_acceleration_mm_per_s2[X_AXIS];
|
||||
slow_homing.acceleration.y = planner.settings.max_acceleration_mm_per_s2[Y_AXIS];
|
||||
slow_homing_t slow_homing{0};
|
||||
slow_homing.acceleration.set(planner.settings.max_acceleration_mm_per_s2[X_AXIS];
|
||||
planner.settings.max_acceleration_mm_per_s2[Y_AXIS]);
|
||||
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = 100;
|
||||
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = 100;
|
||||
#if HAS_CLASSIC_JERK
|
||||
slow_homing.jerk.x = planner.max_jerk[X_AXIS];
|
||||
slow_homing.jerk.y = planner.max_jerk[Y_AXIS];
|
||||
planner.max_jerk[X_AXIS] = 0;
|
||||
planner.max_jerk[Y_AXIS] = 0;
|
||||
slow_homing.jerk_xy = planner.max_jerk;
|
||||
planner.max_jerk.set(0, 0);
|
||||
#endif
|
||||
|
||||
planner.reset_acceleration_rates();
|
||||
@ -274,7 +270,7 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
home_all = always_home_all || (homeX == homeY && homeX == homeZ),
|
||||
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ;
|
||||
|
||||
set_destination_from_current();
|
||||
destination = current_position;
|
||||
|
||||
#if Z_HOME_DIR > 0 // If homing away from BED do Z first
|
||||
|
||||
@ -291,10 +287,10 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
|
||||
if (z_homing_height && (doX || doY)) {
|
||||
// Raise Z before homing any other axes and z is not already high enough (never lower z)
|
||||
destination[Z_AXIS] = z_homing_height;
|
||||
if (destination[Z_AXIS] > current_position[Z_AXIS]) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) to ", destination[Z_AXIS]);
|
||||
do_blocking_move_to_z(destination[Z_AXIS]);
|
||||
destination.z = z_homing_height;
|
||||
if (destination.z > current_position.z) {
|
||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) to ", destination.z);
|
||||
do_blocking_move_to_z(destination.z);
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,14 +325,14 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
homeaxis(X_AXIS);
|
||||
|
||||
// Remember this extruder's position for later tool change
|
||||
inactive_extruder_x_pos = current_position[X_AXIS];
|
||||
inactive_extruder_x_pos = current_position.x;
|
||||
|
||||
// Home the 1st (left) extruder
|
||||
active_extruder = 0;
|
||||
homeaxis(X_AXIS);
|
||||
|
||||
// Consider the active extruder to be parked
|
||||
COPY(raised_parked_position, current_position);
|
||||
raised_parked_position = current_position;
|
||||
delayed_move_time = 0;
|
||||
active_extruder_parked = true;
|
||||
|
||||
@ -390,14 +386,14 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
homeaxis(X_AXIS);
|
||||
|
||||
// Remember this extruder's position for later tool change
|
||||
inactive_extruder_x_pos = current_position[X_AXIS];
|
||||
inactive_extruder_x_pos = current_position.x;
|
||||
|
||||
// Home the 1st (left) extruder
|
||||
active_extruder = 0;
|
||||
homeaxis(X_AXIS);
|
||||
|
||||
// Consider the active extruder to be parked
|
||||
COPY(raised_parked_position, current_position);
|
||||
raised_parked_position = current_position;
|
||||
delayed_move_time = 0;
|
||||
active_extruder_parked = true;
|
||||
extruder_duplication_enabled = IDEX_saved_duplication_state;
|
||||
@ -441,10 +437,8 @@ void GcodeSuite::G28(const bool always_home_all) {
|
||||
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = slow_homing.acceleration.x;
|
||||
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = slow_homing.acceleration.y;
|
||||
#if HAS_CLASSIC_JERK
|
||||
planner.max_jerk[X_AXIS] = slow_homing.jerk.x;
|
||||
planner.max_jerk[Y_AXIS] = slow_homing.jerk.y;
|
||||
planner.max_jerk = slow_homing.jerk_xy;
|
||||
#endif
|
||||
|
||||
planner.reset_acceleration_rates();
|
||||
#endif
|
||||
|
||||
|
@ -70,7 +70,7 @@ enum CalEnum : char { // the 7 main calibration points -
|
||||
#define AC_CLEANUP() ac_cleanup()
|
||||
#endif
|
||||
|
||||
float lcd_probe_pt(const float &rx, const float &ry);
|
||||
float lcd_probe_pt(const xy_pos_t &xy);
|
||||
|
||||
void ac_home() {
|
||||
endstops.enable(true);
|
||||
@ -122,9 +122,9 @@ void print_signed_float(PGM_P const prefix, const float &f) {
|
||||
static void print_calibration_settings(const bool end_stops, const bool tower_angles) {
|
||||
SERIAL_ECHOPAIR(".Height:", delta_height);
|
||||
if (end_stops) {
|
||||
print_signed_float(PSTR("Ex"), delta_endstop_adj[A_AXIS]);
|
||||
print_signed_float(PSTR("Ey"), delta_endstop_adj[B_AXIS]);
|
||||
print_signed_float(PSTR("Ez"), delta_endstop_adj[C_AXIS]);
|
||||
print_signed_float(PSTR("Ex"), delta_endstop_adj.a);
|
||||
print_signed_float(PSTR("Ey"), delta_endstop_adj.b);
|
||||
print_signed_float(PSTR("Ez"), delta_endstop_adj.c);
|
||||
}
|
||||
if (end_stops && tower_angles) {
|
||||
SERIAL_ECHOPAIR(" Radius:", delta_radius);
|
||||
@ -133,9 +133,9 @@ static void print_calibration_settings(const bool end_stops, const bool tower_an
|
||||
SERIAL_ECHO_SP(13);
|
||||
}
|
||||
if (tower_angles) {
|
||||
print_signed_float(PSTR("Tx"), delta_tower_angle_trim[A_AXIS]);
|
||||
print_signed_float(PSTR("Ty"), delta_tower_angle_trim[B_AXIS]);
|
||||
print_signed_float(PSTR("Tz"), delta_tower_angle_trim[C_AXIS]);
|
||||
print_signed_float(PSTR("Tx"), delta_tower_angle_trim.a);
|
||||
print_signed_float(PSTR("Ty"), delta_tower_angle_trim.b);
|
||||
print_signed_float(PSTR("Tz"), delta_tower_angle_trim.c);
|
||||
}
|
||||
if ((!end_stops && tower_angles) || (end_stops && !tower_angles)) { // XOR
|
||||
SERIAL_ECHOPAIR(" Radius:", delta_radius);
|
||||
@ -188,12 +188,12 @@ static float std_dev_points(float z_pt[NPP + 1], const bool _0p_cal, const bool
|
||||
/**
|
||||
* - Probe a point
|
||||
*/
|
||||
static float calibration_probe(const float &nx, const float &ny, const bool stow) {
|
||||
static float calibration_probe(const xy_pos_t &xy, const bool stow) {
|
||||
#if HAS_BED_PROBE
|
||||
return probe_at_point(nx, ny, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, false);
|
||||
return probe_at_point(xy, stow ? PROBE_PT_STOW : PROBE_PT_RAISE, 0, false);
|
||||
#else
|
||||
UNUSED(stow);
|
||||
return lcd_probe_pt(nx, ny);
|
||||
return lcd_probe_pt(xy);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -223,7 +223,8 @@ static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_poi
|
||||
if (!_0p_calibration) {
|
||||
|
||||
if (!_7p_no_intermediates && !_7p_4_intermediates && !_7p_11_intermediates) { // probe the center
|
||||
z_pt[CEN] += calibration_probe(0, 0, stow_after_each);
|
||||
const xy_pos_t center{0};
|
||||
z_pt[CEN] += calibration_probe(center, stow_after_each);
|
||||
if (isnan(z_pt[CEN])) return false;
|
||||
}
|
||||
|
||||
@ -233,7 +234,8 @@ static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_poi
|
||||
I_LOOP_CAL_PT(rad, start, steps) {
|
||||
const float a = RADIANS(210 + (360 / NPP) * (rad - 1)),
|
||||
r = delta_calibration_radius * 0.1;
|
||||
z_pt[CEN] += calibration_probe(cos(a) * r, sin(a) * r, stow_after_each);
|
||||
const xy_pos_t vec = { cos(a), sin(a) };
|
||||
z_pt[CEN] += calibration_probe(vec * r, stow_after_each);
|
||||
if (isnan(z_pt[CEN])) return false;
|
||||
}
|
||||
z_pt[CEN] /= float(_7p_2_intermediates ? 7 : probe_points);
|
||||
@ -257,7 +259,8 @@ static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_poi
|
||||
const float a = RADIANS(210 + (360 / NPP) * (rad - 1)),
|
||||
r = delta_calibration_radius * (1 - 0.1 * (zig_zag ? offset - circle : circle)),
|
||||
interpol = FMOD(rad, 1);
|
||||
const float z_temp = calibration_probe(cos(a) * r, sin(a) * r, stow_after_each);
|
||||
const xy_pos_t vec = { cos(a), sin(a) };
|
||||
const float z_temp = calibration_probe(vec * r, stow_after_each);
|
||||
if (isnan(z_temp)) return false;
|
||||
// split probe point to neighbouring calibration points
|
||||
z_pt[uint8_t(LROUND(rad - interpol + NPP - 1)) % NPP + 1] += z_temp * sq(cos(RADIANS(interpol * 90)));
|
||||
@ -281,80 +284,69 @@ static bool probe_calibration_points(float z_pt[NPP + 1], const int8_t probe_poi
|
||||
* - formulae for approximative forward kinematics in the end-stop displacement matrix
|
||||
* - definition of the matrix scaling parameters
|
||||
*/
|
||||
static void reverse_kinematics_probe_points(float z_pt[NPP + 1], float mm_at_pt_axis[NPP + 1][ABC]) {
|
||||
float pos[XYZ] = { 0.0 };
|
||||
static void reverse_kinematics_probe_points(float z_pt[NPP + 1], abc_float_t mm_at_pt_axis[NPP + 1]) {
|
||||
xyz_pos_t pos{0};
|
||||
|
||||
LOOP_CAL_ALL(rad) {
|
||||
const float a = RADIANS(210 + (360 / NPP) * (rad - 1)),
|
||||
r = (rad == CEN ? 0.0f : delta_calibration_radius);
|
||||
pos[X_AXIS] = cos(a) * r;
|
||||
pos[Y_AXIS] = sin(a) * r;
|
||||
pos[Z_AXIS] = z_pt[rad];
|
||||
pos.set(cos(a) * r, sin(a) * r, z_pt[rad]);
|
||||
inverse_kinematics(pos);
|
||||
LOOP_XYZ(axis) mm_at_pt_axis[rad][axis] = delta[axis];
|
||||
mm_at_pt_axis[rad] = delta;
|
||||
}
|
||||
}
|
||||
|
||||
static void forward_kinematics_probe_points(float mm_at_pt_axis[NPP + 1][ABC], float z_pt[NPP + 1]) {
|
||||
static void forward_kinematics_probe_points(abc_float_t mm_at_pt_axis[NPP + 1], float z_pt[NPP + 1]) {
|
||||
const float r_quot = delta_calibration_radius / delta_radius;
|
||||
|
||||
#define ZPP(N,I,A) ((1 / 3.0f + r_quot * (N) / 3.0f ) * mm_at_pt_axis[I][A])
|
||||
#define ZPP(N,I,A) (((1.0f + r_quot * (N)) / 3.0f) * mm_at_pt_axis[I].A)
|
||||
#define Z00(I, A) ZPP( 0, I, A)
|
||||
#define Zp1(I, A) ZPP(+1, I, A)
|
||||
#define Zm1(I, A) ZPP(-1, I, A)
|
||||
#define Zp2(I, A) ZPP(+2, I, A)
|
||||
#define Zm2(I, A) ZPP(-2, I, A)
|
||||
|
||||
z_pt[CEN] = Z00(CEN, A_AXIS) + Z00(CEN, B_AXIS) + Z00(CEN, C_AXIS);
|
||||
z_pt[__A] = Zp2(__A, A_AXIS) + Zm1(__A, B_AXIS) + Zm1(__A, C_AXIS);
|
||||
z_pt[__B] = Zm1(__B, A_AXIS) + Zp2(__B, B_AXIS) + Zm1(__B, C_AXIS);
|
||||
z_pt[__C] = Zm1(__C, A_AXIS) + Zm1(__C, B_AXIS) + Zp2(__C, C_AXIS);
|
||||
z_pt[_BC] = Zm2(_BC, A_AXIS) + Zp1(_BC, B_AXIS) + Zp1(_BC, C_AXIS);
|
||||
z_pt[_CA] = Zp1(_CA, A_AXIS) + Zm2(_CA, B_AXIS) + Zp1(_CA, C_AXIS);
|
||||
z_pt[_AB] = Zp1(_AB, A_AXIS) + Zp1(_AB, B_AXIS) + Zm2(_AB, C_AXIS);
|
||||
z_pt[CEN] = Z00(CEN, a) + Z00(CEN, b) + Z00(CEN, c);
|
||||
z_pt[__A] = Zp2(__A, a) + Zm1(__A, b) + Zm1(__A, c);
|
||||
z_pt[__B] = Zm1(__B, a) + Zp2(__B, b) + Zm1(__B, c);
|
||||
z_pt[__C] = Zm1(__C, a) + Zm1(__C, b) + Zp2(__C, c);
|
||||
z_pt[_BC] = Zm2(_BC, a) + Zp1(_BC, b) + Zp1(_BC, c);
|
||||
z_pt[_CA] = Zp1(_CA, a) + Zm2(_CA, b) + Zp1(_CA, c);
|
||||
z_pt[_AB] = Zp1(_AB, a) + Zp1(_AB, b) + Zm2(_AB, c);
|
||||
}
|
||||
|
||||
static void calc_kinematics_diff_probe_points(float z_pt[NPP + 1], float delta_e[ABC], float delta_r, float delta_t[ABC]) {
|
||||
static void calc_kinematics_diff_probe_points(float z_pt[NPP + 1], abc_float_t delta_e, const float delta_r, abc_float_t delta_t) {
|
||||
const float z_center = z_pt[CEN];
|
||||
float diff_mm_at_pt_axis[NPP + 1][ABC],
|
||||
new_mm_at_pt_axis[NPP + 1][ABC];
|
||||
abc_float_t diff_mm_at_pt_axis[NPP + 1], new_mm_at_pt_axis[NPP + 1];
|
||||
|
||||
reverse_kinematics_probe_points(z_pt, diff_mm_at_pt_axis);
|
||||
|
||||
delta_radius += delta_r;
|
||||
LOOP_XYZ(axis) delta_tower_angle_trim[axis] += delta_t[axis];
|
||||
delta_tower_angle_trim += delta_t;
|
||||
recalc_delta_settings();
|
||||
reverse_kinematics_probe_points(z_pt, new_mm_at_pt_axis);
|
||||
|
||||
LOOP_XYZ(axis) LOOP_CAL_ALL(rad) diff_mm_at_pt_axis[rad][axis] -= new_mm_at_pt_axis[rad][axis] + delta_e[axis];
|
||||
LOOP_CAL_ALL(rad) diff_mm_at_pt_axis[rad] -= new_mm_at_pt_axis[rad] + delta_e;
|
||||
forward_kinematics_probe_points(diff_mm_at_pt_axis, z_pt);
|
||||
|
||||
LOOP_CAL_RAD(rad) z_pt[rad] -= z_pt[CEN] - z_center;
|
||||
z_pt[CEN] = z_center;
|
||||
|
||||
delta_radius -= delta_r;
|
||||
LOOP_XYZ(axis) delta_tower_angle_trim[axis] -= delta_t[axis];
|
||||
delta_tower_angle_trim -= delta_t;
|
||||
recalc_delta_settings();
|
||||
}
|
||||
|
||||
static float auto_tune_h() {
|
||||
const float r_quot = delta_calibration_radius / delta_radius;
|
||||
float h_fac = 0.0f;
|
||||
|
||||
h_fac = r_quot / (2.0f / 3.0f);
|
||||
h_fac = 1.0f / h_fac; // (2/3)/CR
|
||||
return h_fac;
|
||||
return RECIPROCAL(r_quot / (2.0f / 3.0f)); // (2/3)/CR
|
||||
}
|
||||
|
||||
static float auto_tune_r() {
|
||||
const float diff = 0.01f;
|
||||
float r_fac = 0.0f,
|
||||
z_pt[NPP + 1] = { 0.0f },
|
||||
delta_e[ABC] = { 0.0f },
|
||||
delta_r = { 0.0f },
|
||||
delta_t[ABC] = { 0.0f };
|
||||
constexpr float diff = 0.01f, delta_r = diff;
|
||||
float r_fac = 0.0f, z_pt[NPP + 1] = { 0.0f };
|
||||
abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f };
|
||||
|
||||
delta_r = diff;
|
||||
calc_kinematics_diff_probe_points(z_pt, delta_e, delta_r, delta_t);
|
||||
r_fac = -(z_pt[__A] + z_pt[__B] + z_pt[__C] + z_pt[_BC] + z_pt[_CA] + z_pt[_AB]) / 6.0f;
|
||||
r_fac = diff / r_fac / 3.0f; // 1/(3*delta_Z)
|
||||
@ -362,14 +354,11 @@ static float auto_tune_r() {
|
||||
}
|
||||
|
||||
static float auto_tune_a() {
|
||||
const float diff = 0.01f;
|
||||
float a_fac = 0.0f,
|
||||
z_pt[NPP + 1] = { 0.0f },
|
||||
delta_e[ABC] = { 0.0f },
|
||||
delta_r = { 0.0f },
|
||||
delta_t[ABC] = { 0.0f };
|
||||
constexpr float diff = 0.01f, delta_r = 0.0f;
|
||||
float a_fac = 0.0f, z_pt[NPP + 1] = { 0.0f };
|
||||
abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f };
|
||||
|
||||
ZERO(delta_t);
|
||||
delta_t.reset();
|
||||
LOOP_XYZ(axis) {
|
||||
delta_t[axis] = diff;
|
||||
calc_kinematics_diff_probe_points(z_pt, delta_e, delta_r, delta_t);
|
||||
@ -453,21 +442,11 @@ void GcodeSuite::G33() {
|
||||
zero_std_dev = (verbose_level ? 999.0f : 0.0f), // 0.0 in dry-run mode : forced end
|
||||
zero_std_dev_min = zero_std_dev,
|
||||
zero_std_dev_old = zero_std_dev,
|
||||
h_factor,
|
||||
r_factor,
|
||||
a_factor,
|
||||
e_old[ABC] = {
|
||||
delta_endstop_adj[A_AXIS],
|
||||
delta_endstop_adj[B_AXIS],
|
||||
delta_endstop_adj[C_AXIS]
|
||||
},
|
||||
h_factor, r_factor, a_factor,
|
||||
r_old = delta_radius,
|
||||
h_old = delta_height,
|
||||
a_old[ABC] = {
|
||||
delta_tower_angle_trim[A_AXIS],
|
||||
delta_tower_angle_trim[B_AXIS],
|
||||
delta_tower_angle_trim[C_AXIS]
|
||||
};
|
||||
h_old = delta_height;
|
||||
|
||||
abc_pos_t e_old = delta_endstop_adj, a_old = delta_tower_angle_trim;
|
||||
|
||||
SERIAL_ECHOLNPGM("G33 Auto Calibrate");
|
||||
|
||||
@ -520,15 +499,14 @@ void GcodeSuite::G33() {
|
||||
|
||||
if (zero_std_dev < zero_std_dev_min) {
|
||||
// set roll-back point
|
||||
COPY(e_old, delta_endstop_adj);
|
||||
e_old = delta_endstop_adj;
|
||||
r_old = delta_radius;
|
||||
h_old = delta_height;
|
||||
COPY(a_old, delta_tower_angle_trim);
|
||||
a_old = delta_tower_angle_trim;
|
||||
}
|
||||
|
||||
float e_delta[ABC] = { 0.0f },
|
||||
r_delta = 0.0f,
|
||||
t_delta[ABC] = { 0.0f };
|
||||
abc_float_t e_delta = { 0.0f }, t_delta = { 0.0f };
|
||||
float r_delta = 0.0f;
|
||||
|
||||
/**
|
||||
* convergence matrices:
|
||||
@ -563,42 +541,42 @@ void GcodeSuite::G33() {
|
||||
|
||||
case 2:
|
||||
if (towers_set) { // see 4 point calibration (towers) matrix
|
||||
e_delta[A_AXIS] = (+Z4(__A) -Z2(__B) -Z2(__C)) * h_factor +Z4(CEN);
|
||||
e_delta[B_AXIS] = (-Z2(__A) +Z4(__B) -Z2(__C)) * h_factor +Z4(CEN);
|
||||
e_delta[C_AXIS] = (-Z2(__A) -Z2(__B) +Z4(__C)) * h_factor +Z4(CEN);
|
||||
r_delta = (+Z4(__A) +Z4(__B) +Z4(__C) -Z12(CEN)) * r_factor;
|
||||
e_delta.set((+Z4(__A) -Z2(__B) -Z2(__C)) * h_factor +Z4(CEN),
|
||||
(-Z2(__A) +Z4(__B) -Z2(__C)) * h_factor +Z4(CEN),
|
||||
(-Z2(__A) -Z2(__B) +Z4(__C)) * h_factor +Z4(CEN));
|
||||
r_delta = (+Z4(__A) +Z4(__B) +Z4(__C) -Z12(CEN)) * r_factor;
|
||||
}
|
||||
else { // see 4 point calibration (opposites) matrix
|
||||
e_delta[A_AXIS] = (-Z4(_BC) +Z2(_CA) +Z2(_AB)) * h_factor +Z4(CEN);
|
||||
e_delta[B_AXIS] = (+Z2(_BC) -Z4(_CA) +Z2(_AB)) * h_factor +Z4(CEN);
|
||||
e_delta[C_AXIS] = (+Z2(_BC) +Z2(_CA) -Z4(_AB)) * h_factor +Z4(CEN);
|
||||
r_delta = (+Z4(_BC) +Z4(_CA) +Z4(_AB) -Z12(CEN)) * r_factor;
|
||||
e_delta.set((-Z4(_BC) +Z2(_CA) +Z2(_AB)) * h_factor +Z4(CEN),
|
||||
(+Z2(_BC) -Z4(_CA) +Z2(_AB)) * h_factor +Z4(CEN),
|
||||
(+Z2(_BC) +Z2(_CA) -Z4(_AB)) * h_factor +Z4(CEN));
|
||||
r_delta = (+Z4(_BC) +Z4(_CA) +Z4(_AB) -Z12(CEN)) * r_factor;
|
||||
}
|
||||
break;
|
||||
|
||||
default: // see 7 point calibration (towers & opposites) matrix
|
||||
e_delta[A_AXIS] = (+Z2(__A) -Z1(__B) -Z1(__C) -Z2(_BC) +Z1(_CA) +Z1(_AB)) * h_factor +Z4(CEN);
|
||||
e_delta[B_AXIS] = (-Z1(__A) +Z2(__B) -Z1(__C) +Z1(_BC) -Z2(_CA) +Z1(_AB)) * h_factor +Z4(CEN);
|
||||
e_delta[C_AXIS] = (-Z1(__A) -Z1(__B) +Z2(__C) +Z1(_BC) +Z1(_CA) -Z2(_AB)) * h_factor +Z4(CEN);
|
||||
r_delta = (+Z2(__A) +Z2(__B) +Z2(__C) +Z2(_BC) +Z2(_CA) +Z2(_AB) -Z12(CEN)) * r_factor;
|
||||
e_delta.set((+Z2(__A) -Z1(__B) -Z1(__C) -Z2(_BC) +Z1(_CA) +Z1(_AB)) * h_factor +Z4(CEN),
|
||||
(-Z1(__A) +Z2(__B) -Z1(__C) +Z1(_BC) -Z2(_CA) +Z1(_AB)) * h_factor +Z4(CEN),
|
||||
(-Z1(__A) -Z1(__B) +Z2(__C) +Z1(_BC) +Z1(_CA) -Z2(_AB)) * h_factor +Z4(CEN));
|
||||
r_delta = (+Z2(__A) +Z2(__B) +Z2(__C) +Z2(_BC) +Z2(_CA) +Z2(_AB) -Z12(CEN)) * r_factor;
|
||||
|
||||
if (towers_set) { // see 7 point tower angle calibration (towers & opposites) matrix
|
||||
t_delta[A_AXIS] = (+Z0(__A) -Z4(__B) +Z4(__C) +Z0(_BC) -Z4(_CA) +Z4(_AB) +Z0(CEN)) * a_factor;
|
||||
t_delta[B_AXIS] = (+Z4(__A) +Z0(__B) -Z4(__C) +Z4(_BC) +Z0(_CA) -Z4(_AB) +Z0(CEN)) * a_factor;
|
||||
t_delta[C_AXIS] = (-Z4(__A) +Z4(__B) +Z0(__C) -Z4(_BC) +Z4(_CA) +Z0(_AB) +Z0(CEN)) * a_factor;
|
||||
t_delta.set((+Z0(__A) -Z4(__B) +Z4(__C) +Z0(_BC) -Z4(_CA) +Z4(_AB) +Z0(CEN)) * a_factor,
|
||||
(+Z4(__A) +Z0(__B) -Z4(__C) +Z4(_BC) +Z0(_CA) -Z4(_AB) +Z0(CEN)) * a_factor,
|
||||
(-Z4(__A) +Z4(__B) +Z0(__C) -Z4(_BC) +Z4(_CA) +Z0(_AB) +Z0(CEN)) * a_factor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
LOOP_XYZ(axis) delta_endstop_adj[axis] += e_delta[axis];
|
||||
delta_endstop_adj += e_delta;
|
||||
delta_radius += r_delta;
|
||||
LOOP_XYZ(axis) delta_tower_angle_trim[axis] += t_delta[axis];
|
||||
delta_tower_angle_trim += t_delta;
|
||||
}
|
||||
else if (zero_std_dev >= test_precision) {
|
||||
// roll back
|
||||
COPY(delta_endstop_adj, e_old);
|
||||
delta_endstop_adj = e_old;
|
||||
delta_radius = r_old;
|
||||
delta_height = h_old;
|
||||
COPY(delta_tower_angle_trim, a_old);
|
||||
delta_tower_angle_trim = a_old;
|
||||
}
|
||||
|
||||
if (verbose_level != 0) { // !dry run
|
||||
@ -611,7 +589,7 @@ void GcodeSuite::G33() {
|
||||
}
|
||||
|
||||
// adjust delta_height and endstops by the max amount
|
||||
const float z_temp = _MAX(delta_endstop_adj[A_AXIS], delta_endstop_adj[B_AXIS], delta_endstop_adj[C_AXIS]);
|
||||
const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c);
|
||||
delta_height -= z_temp;
|
||||
LOOP_XYZ(axis) delta_endstop_adj[axis] -= z_temp;
|
||||
}
|
||||
|
@ -45,8 +45,17 @@
|
||||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
#include "../../core/debug_out.h"
|
||||
|
||||
float z_auto_align_xpos[Z_STEPPER_COUNT] = Z_STEPPER_ALIGN_X,
|
||||
z_auto_align_ypos[Z_STEPPER_COUNT] = Z_STEPPER_ALIGN_Y;
|
||||
// Sanity-check
|
||||
constexpr xy_pos_t sanity_arr_z_align[] = Z_STEPPER_ALIGN_XY;
|
||||
static_assert(COUNT(sanity_arr_z_align) == Z_STEPPER_COUNT,
|
||||
#if ENABLED(Z_TRIPLE_STEPPER_DRIVERS)
|
||||
"Z_STEPPER_ALIGN_XY requires three {X,Y} entries (Z, Z2, and Z3)."
|
||||
#else
|
||||
"Z_STEPPER_ALIGN_XY requires two {X,Y} entries (Z and Z2)."
|
||||
#endif
|
||||
);
|
||||
|
||||
xy_pos_t z_auto_align_pos[Z_STEPPER_COUNT] = Z_STEPPER_ALIGN_XY;
|
||||
|
||||
inline void set_all_z_lock(const bool lock) {
|
||||
stepper.set_z_lock(lock);
|
||||
@ -123,11 +132,11 @@ void GcodeSuite::G34() {
|
||||
|
||||
float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * (
|
||||
#if ENABLED(Z_TRIPLE_STEPPER_DRIVERS)
|
||||
SQRT(_MAX(HYPOT2(z_auto_align_xpos[0] - z_auto_align_ypos[0], z_auto_align_xpos[1] - z_auto_align_ypos[1]),
|
||||
HYPOT2(z_auto_align_xpos[1] - z_auto_align_ypos[1], z_auto_align_xpos[2] - z_auto_align_ypos[2]),
|
||||
HYPOT2(z_auto_align_xpos[2] - z_auto_align_ypos[2], z_auto_align_xpos[0] - z_auto_align_ypos[0])))
|
||||
SQRT(_MAX(HYPOT2(z_auto_align_pos[0].x - z_auto_align_pos[0].y, z_auto_align_pos[1].x - z_auto_align_pos[1].y),
|
||||
HYPOT2(z_auto_align_pos[1].x - z_auto_align_pos[1].y, z_auto_align_pos[2].x - z_auto_align_pos[2].y),
|
||||
HYPOT2(z_auto_align_pos[2].x - z_auto_align_pos[2].y, z_auto_align_pos[0].x - z_auto_align_pos[0].y)))
|
||||
#else
|
||||
HYPOT(z_auto_align_xpos[0] - z_auto_align_ypos[0], z_auto_align_xpos[1] - z_auto_align_ypos[1])
|
||||
HYPOT(z_auto_align_pos[0].x - z_auto_align_pos[0].y, z_auto_align_pos[1].x - z_auto_align_pos[1].y)
|
||||
#endif
|
||||
);
|
||||
|
||||
@ -135,7 +144,7 @@ void GcodeSuite::G34() {
|
||||
if (!all_axes_known()) home_all_axes();
|
||||
|
||||
// Move the Z coordinate realm towards the positive - dirty trick
|
||||
current_position[Z_AXIS] -= z_probe * 0.5;
|
||||
current_position.z -= z_probe * 0.5f;
|
||||
|
||||
float last_z_align_move[Z_STEPPER_COUNT] = ARRAY_N(Z_STEPPER_COUNT, 10000.0f, 10000.0f, 10000.0f),
|
||||
z_measured[Z_STEPPER_COUNT] = { 0 },
|
||||
@ -162,7 +171,7 @@ void GcodeSuite::G34() {
|
||||
if (iteration == 0 || izstepper > 0) do_blocking_move_to_z(z_probe);
|
||||
|
||||
// Probe a Z height for each stepper.
|
||||
const float z_probed_height = probe_at_point(z_auto_align_xpos[zstepper], z_auto_align_ypos[zstepper], raise_after, 0, true);
|
||||
const float z_probed_height = probe_at_point(z_auto_align_pos[zstepper], raise_after, 0, true);
|
||||
if (isnan(z_probed_height)) {
|
||||
SERIAL_ECHOLNPGM("Probing failed.");
|
||||
err_break = true;
|
||||
@ -240,7 +249,7 @@ void GcodeSuite::G34() {
|
||||
}
|
||||
|
||||
// Do a move to correct part of the misalignment for the current stepper
|
||||
do_blocking_move_to_z(amplification * z_align_move + current_position[Z_AXIS]);
|
||||
do_blocking_move_to_z(amplification * z_align_move + current_position.z);
|
||||
} // for (zstepper)
|
||||
|
||||
// Back to normal stepper operations
|
||||
@ -299,20 +308,22 @@ void GcodeSuite::M422() {
|
||||
return;
|
||||
}
|
||||
|
||||
const float x_pos = parser.floatval('X', z_auto_align_xpos[zstepper]);
|
||||
if (!WITHIN(x_pos, X_MIN_POS, X_MAX_POS)) {
|
||||
const xy_pos_t pos = {
|
||||
parser.floatval('X', z_auto_align_pos[zstepper].x),
|
||||
parser.floatval('Y', z_auto_align_pos[zstepper].y)
|
||||
};
|
||||
|
||||
if (!WITHIN(pos.x, X_MIN_POS, X_MAX_POS)) {
|
||||
SERIAL_ECHOLNPGM("?(X) out of bounds.");
|
||||
return;
|
||||
}
|
||||
|
||||
const float y_pos = parser.floatval('Y', z_auto_align_ypos[zstepper]);
|
||||
if (!WITHIN(y_pos, Y_MIN_POS, Y_MAX_POS)) {
|
||||
if (!WITHIN(pos.y, Y_MIN_POS, Y_MAX_POS)) {
|
||||
SERIAL_ECHOLNPGM("?(Y) out of bounds.");
|
||||
return;
|
||||
}
|
||||
|
||||
z_auto_align_xpos[zstepper] = x_pos;
|
||||
z_auto_align_ypos[zstepper] = y_pos;
|
||||
z_auto_align_pos[zstepper] = pos;
|
||||
}
|
||||
|
||||
#endif // Z_STEPPER_AUTO_ALIGN
|
||||
|
@ -61,17 +61,17 @@
|
||||
|
||||
enum side_t : uint8_t { TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES };
|
||||
|
||||
static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER;
|
||||
static constexpr xyz_float_t dimensions CALIBRATION_OBJECT_DIMENSIONS;
|
||||
static constexpr xy_float_t nod = { CALIBRATION_NOZZLE_OUTER_DIAMETER, CALIBRATION_NOZZLE_OUTER_DIAMETER };
|
||||
|
||||
struct measurements_t {
|
||||
static constexpr float dimensions[XYZ] = CALIBRATION_OBJECT_DIMENSIONS;
|
||||
static constexpr float true_center[XYZ] = CALIBRATION_OBJECT_CENTER;
|
||||
xyz_pos_t obj_center = true_center; // Non-static must be assigned from xyz_pos_t
|
||||
|
||||
float obj_center[XYZ] = CALIBRATION_OBJECT_CENTER;
|
||||
float obj_side[NUM_SIDES];
|
||||
float obj_side[NUM_SIDES], backlash[NUM_SIDES];
|
||||
xyz_float_t pos_error;
|
||||
|
||||
float backlash[NUM_SIDES];
|
||||
float pos_error[XYZ];
|
||||
|
||||
float nozzle_outer_dimension[2] = {CALIBRATION_NOZZLE_OUTER_DIAMETER, CALIBRATION_NOZZLE_OUTER_DIAMETER};
|
||||
xy_float_t nozzle_outer_dimension = nod;
|
||||
};
|
||||
|
||||
#define TEMPORARY_SOFT_ENDSTOP_STATE(enable) REMEMBER(tes, soft_endstops_enabled, enable);
|
||||
@ -88,29 +88,8 @@ struct measurements_t {
|
||||
#define TEMPORARY_BACKLASH_SMOOTHING(value)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Move to a particular location. Up to three individual axes
|
||||
* and their destinations can be specified, in any order.
|
||||
*/
|
||||
inline void move_to(
|
||||
const AxisEnum a1 = NO_AXIS, const float p1 = 0,
|
||||
const AxisEnum a2 = NO_AXIS, const float p2 = 0,
|
||||
const AxisEnum a3 = NO_AXIS, const float p3 = 0
|
||||
) {
|
||||
set_destination_from_current();
|
||||
|
||||
// Note: The order of p1, p2, p3 may not correspond to X, Y, Z
|
||||
if (a1 != NO_AXIS) destination[a1] = p1;
|
||||
if (a2 != NO_AXIS) destination[a2] = p2;
|
||||
if (a3 != NO_AXIS) destination[a3] = p3;
|
||||
|
||||
// Make sure coordinates are within bounds
|
||||
destination[X_AXIS] = _MAX(_MIN(destination[X_AXIS], X_MAX_POS), X_MIN_POS);
|
||||
destination[Y_AXIS] = _MAX(_MIN(destination[Y_AXIS], Y_MAX_POS), Y_MIN_POS);
|
||||
destination[Z_AXIS] = _MAX(_MIN(destination[Z_AXIS], Z_MAX_POS), Z_MIN_POS);
|
||||
|
||||
// Move to position
|
||||
do_blocking_move_to(destination, MMM_TO_MMS(CALIBRATION_FEEDRATE_TRAVEL));
|
||||
inline void calibration_move() {
|
||||
do_blocking_move_to(current_position, MMM_TO_MMS(CALIBRATION_FEEDRATE_TRAVEL));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,10 +100,12 @@ inline void move_to(
|
||||
*/
|
||||
inline void park_above_object(measurements_t &m, const float uncertainty) {
|
||||
// Move to safe distance above calibration object
|
||||
move_to(Z_AXIS, m.obj_center[Z_AXIS] + m.dimensions[Z_AXIS] / 2 + uncertainty);
|
||||
current_position.z = m.obj_center.z + dimensions.z / 2 + uncertainty;
|
||||
calibration_move();
|
||||
|
||||
// Move to center of calibration object in XY
|
||||
move_to(X_AXIS, m.obj_center[X_AXIS], Y_AXIS, m.obj_center[Y_AXIS]);
|
||||
current_position = xy_pos_t(m.obj_center);
|
||||
calibration_move();
|
||||
}
|
||||
|
||||
#if HOTENDS > 1
|
||||
@ -139,14 +120,9 @@ inline void park_above_object(measurements_t &m, const float uncertainty) {
|
||||
#if HAS_HOTEND_OFFSET
|
||||
|
||||
inline void normalize_hotend_offsets() {
|
||||
for (uint8_t e = 1; e < HOTENDS; e++) {
|
||||
hotend_offset[X_AXIS][e] -= hotend_offset[X_AXIS][0];
|
||||
hotend_offset[Y_AXIS][e] -= hotend_offset[Y_AXIS][0];
|
||||
hotend_offset[Z_AXIS][e] -= hotend_offset[Z_AXIS][0];
|
||||
}
|
||||
hotend_offset[X_AXIS][0] = 0;
|
||||
hotend_offset[Y_AXIS][0] = 0;
|
||||
hotend_offset[Z_AXIS][0] = 0;
|
||||
for (uint8_t e = 1; e < HOTENDS; e++)
|
||||
hotend_offset[e] -= hotend_offset[0];
|
||||
hotend_offset[0].reset();
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -175,7 +151,7 @@ float measuring_movement(const AxisEnum axis, const int dir, const bool stop_sta
|
||||
const feedRate_t mms = fast ? MMM_TO_MMS(CALIBRATION_FEEDRATE_FAST) : MMM_TO_MMS(CALIBRATION_FEEDRATE_SLOW);
|
||||
const float limit = fast ? 50 : 5;
|
||||
|
||||
set_destination_from_current();
|
||||
destination = current_position;
|
||||
for (float travel = 0; travel < limit; travel += step) {
|
||||
destination[axis] += dir * step;
|
||||
do_blocking_move_to(destination, mms);
|
||||
@ -199,7 +175,7 @@ inline float measure(const AxisEnum axis, const int dir, const bool stop_state,
|
||||
const bool fast = uncertainty == CALIBRATION_MEASUREMENT_UNKNOWN;
|
||||
|
||||
// Save position
|
||||
set_destination_from_current();
|
||||
destination = current_position;
|
||||
const float start_pos = destination[axis];
|
||||
const float measured_pos = measuring_movement(axis, dir, stop_state, fast);
|
||||
// Measure backlash
|
||||
@ -223,7 +199,7 @@ inline float measure(const AxisEnum axis, const int dir, const bool stop_state,
|
||||
* to find out height of edge
|
||||
*/
|
||||
inline void probe_side(measurements_t &m, const float uncertainty, const side_t side, const bool probe_top_at_edge=false) {
|
||||
const float dimensions[] = CALIBRATION_OBJECT_DIMENSIONS;
|
||||
const xyz_float_t dimensions = CALIBRATION_OBJECT_DIMENSIONS;
|
||||
AxisEnum axis;
|
||||
float dir;
|
||||
|
||||
@ -232,7 +208,7 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
|
||||
switch (side) {
|
||||
case TOP: {
|
||||
const float measurement = measure(Z_AXIS, -1, true, &m.backlash[TOP], uncertainty);
|
||||
m.obj_center[Z_AXIS] = measurement - dimensions[Z_AXIS] / 2;
|
||||
m.obj_center.z = measurement - dimensions.z / 2;
|
||||
m.obj_side[TOP] = measurement;
|
||||
return;
|
||||
}
|
||||
@ -240,22 +216,24 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
|
||||
case FRONT: axis = Y_AXIS; dir = 1; break;
|
||||
case LEFT: axis = X_AXIS; dir = 1; break;
|
||||
case BACK: axis = Y_AXIS; dir = -1; break;
|
||||
default:
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if (probe_top_at_edge) {
|
||||
// Probe top nearest the side we are probing
|
||||
move_to(axis, m.obj_center[axis] + (-dir) * (dimensions[axis] / 2 - m.nozzle_outer_dimension[axis]));
|
||||
current_position[axis] = m.obj_center[axis] + (-dir) * (dimensions[axis] / 2 - m.nozzle_outer_dimension[axis]);
|
||||
calibration_move();
|
||||
m.obj_side[TOP] = measure(Z_AXIS, -1, true, &m.backlash[TOP], uncertainty);
|
||||
m.obj_center[Z_AXIS] = m.obj_side[TOP] - dimensions[Z_AXIS] / 2;
|
||||
m.obj_center.z = m.obj_side[TOP] - dimensions.z / 2;
|
||||
}
|
||||
|
||||
// Move to safe distance to the side of the calibration object
|
||||
move_to(axis, m.obj_center[axis] + (-dir) * (dimensions[axis] / 2 + m.nozzle_outer_dimension[axis] / 2 + uncertainty));
|
||||
current_position[axis] = m.obj_center[axis] + (-dir) * (dimensions[axis] / 2 + m.nozzle_outer_dimension[axis] / 2 + uncertainty);
|
||||
calibration_move();
|
||||
|
||||
// Plunge below the side of the calibration object and measure
|
||||
move_to(Z_AXIS, m.obj_side[TOP] - CALIBRATION_NOZZLE_TIP_HEIGHT * 0.7);
|
||||
current_position.z = m.obj_side[TOP] - CALIBRATION_NOZZLE_TIP_HEIGHT * 0.7;
|
||||
calibration_move();
|
||||
const float measurement = measure(axis, dir, true, &m.backlash[side], uncertainty);
|
||||
m.obj_center[axis] = measurement + dir * (dimensions[axis] / 2 + m.nozzle_outer_dimension[axis] / 2);
|
||||
m.obj_side[side] = measurement;
|
||||
@ -294,36 +272,36 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
|
||||
|
||||
// Compute the measured center of the calibration object.
|
||||
#if HAS_X_CENTER
|
||||
m.obj_center[X_AXIS] = (m.obj_side[LEFT] + m.obj_side[RIGHT]) / 2;
|
||||
m.obj_center.x = (m.obj_side[LEFT] + m.obj_side[RIGHT]) / 2;
|
||||
#endif
|
||||
#if HAS_Y_CENTER
|
||||
m.obj_center[Y_AXIS] = (m.obj_side[FRONT] + m.obj_side[BACK]) / 2;
|
||||
m.obj_center.y = (m.obj_side[FRONT] + m.obj_side[BACK]) / 2;
|
||||
#endif
|
||||
|
||||
// Compute the outside diameter of the nozzle at the height
|
||||
// at which it makes contact with the calibration object
|
||||
#if HAS_X_CENTER
|
||||
m.nozzle_outer_dimension[X_AXIS] = m.obj_side[RIGHT] - m.obj_side[LEFT] - m.dimensions[X_AXIS];
|
||||
m.nozzle_outer_dimension.x = m.obj_side[RIGHT] - m.obj_side[LEFT] - dimensions.x;
|
||||
#endif
|
||||
#if HAS_Y_CENTER
|
||||
m.nozzle_outer_dimension[Y_AXIS] = m.obj_side[BACK] - m.obj_side[FRONT] - m.dimensions[Y_AXIS];
|
||||
m.nozzle_outer_dimension.y = m.obj_side[BACK] - m.obj_side[FRONT] - dimensions.y;
|
||||
#endif
|
||||
|
||||
park_above_object(m, uncertainty);
|
||||
|
||||
// The difference between the known and the measured location
|
||||
// of the calibration object is the positional error
|
||||
m.pos_error[X_AXIS] = (0
|
||||
m.pos_error.x = (0
|
||||
#if HAS_X_CENTER
|
||||
+ m.true_center[X_AXIS] - m.obj_center[X_AXIS]
|
||||
+ true_center.x - m.obj_center.x
|
||||
#endif
|
||||
);
|
||||
m.pos_error[Y_AXIS] = (0
|
||||
m.pos_error.y = (0
|
||||
#if HAS_Y_CENTER
|
||||
+ m.true_center[Y_AXIS] - m.obj_center[Y_AXIS]
|
||||
+ true_center.y - m.obj_center.y
|
||||
#endif
|
||||
);
|
||||
m.pos_error[Z_AXIS] = m.true_center[Z_AXIS] - m.obj_center[Z_AXIS];
|
||||
m.pos_error.z = true_center.z - m.obj_center.z;
|
||||
}
|
||||
|
||||
#if ENABLED(CALIBRATION_REPORTING)
|
||||
@ -348,12 +326,12 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
|
||||
inline void report_measured_center(const measurements_t &m) {
|
||||
SERIAL_ECHOLNPGM("Center:");
|
||||
#if HAS_X_CENTER
|
||||
SERIAL_ECHOLNPAIR(" X", m.obj_center[X_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" X", m.obj_center.x);
|
||||
#endif
|
||||
#if HAS_Y_CENTER
|
||||
SERIAL_ECHOLNPAIR(" Y", m.obj_center[Y_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" Y", m.obj_center.y);
|
||||
#endif
|
||||
SERIAL_ECHOLNPAIR(" Z", m.obj_center[Z_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" Z", m.obj_center.z);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
@ -380,12 +358,12 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
|
||||
SERIAL_ECHO(int(active_extruder));
|
||||
SERIAL_ECHOLNPGM(" Positional Error:");
|
||||
#if HAS_X_CENTER
|
||||
SERIAL_ECHOLNPAIR(" X", m.pos_error[X_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" X", m.pos_error.x);
|
||||
#endif
|
||||
#if HAS_Y_CENTER
|
||||
SERIAL_ECHOLNPAIR(" Y", m.pos_error[Y_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" Y", m.pos_error.y);
|
||||
#endif
|
||||
SERIAL_ECHOLNPAIR(" Z", m.pos_error[Z_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" Z", m.pos_error.z);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
@ -393,10 +371,10 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
|
||||
SERIAL_ECHOLNPGM("Nozzle Tip Outer Dimensions:");
|
||||
#if HAS_X_CENTER || HAS_Y_CENTER
|
||||
#if HAS_X_CENTER
|
||||
SERIAL_ECHOLNPAIR(" X", m.nozzle_outer_dimension[X_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" X", m.nozzle_outer_dimension.x);
|
||||
#endif
|
||||
#if HAS_Y_CENTER
|
||||
SERIAL_ECHOLNPAIR(" Y", m.nozzle_outer_dimension[Y_AXIS]);
|
||||
SERIAL_ECHOLNPAIR(" Y", m.nozzle_outer_dimension.y);
|
||||
#endif
|
||||
#else
|
||||
UNUSED(m);
|
||||
@ -410,7 +388,7 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
|
||||
//
|
||||
inline void report_hotend_offsets() {
|
||||
for (uint8_t e = 1; e < HOTENDS; e++)
|
||||
SERIAL_ECHOLNPAIR("T", int(e), " Hotend Offset X", hotend_offset[X_AXIS][e], " Y", hotend_offset[Y_AXIS][e], " Z", hotend_offset[Z_AXIS][e]);
|
||||
SERIAL_ECHOLNPAIR("T", int(e), " Hotend Offset X", hotend_offset[e].x, " Y", hotend_offset[e].y, " Z", hotend_offset[e].z);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -434,49 +412,40 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) {
|
||||
|
||||
#if ENABLED(BACKLASH_GCODE)
|
||||
#if HAS_X_CENTER
|
||||
backlash.distance_mm[X_AXIS] = (m.backlash[LEFT] + m.backlash[RIGHT]) / 2;
|
||||
backlash.distance_mm.x = (m.backlash[LEFT] + m.backlash[RIGHT]) / 2;
|
||||
#elif ENABLED(CALIBRATION_MEASURE_LEFT)
|
||||
backlash.distance_mm[X_AXIS] = m.backlash[LEFT];
|
||||
backlash.distance_mm.x = m.backlash[LEFT];
|
||||
#elif ENABLED(CALIBRATION_MEASURE_RIGHT)
|
||||
backlash.distance_mm[X_AXIS] = m.backlash[RIGHT];
|
||||
backlash.distance_mm.x = m.backlash[RIGHT];
|
||||
#endif
|
||||
|
||||
#if HAS_Y_CENTER
|
||||
backlash.distance_mm[Y_AXIS] = (m.backlash[FRONT] + m.backlash[BACK]) / 2;
|
||||
backlash.distance_mm.y = (m.backlash[FRONT] + m.backlash[BACK]) / 2;
|
||||
#elif ENABLED(CALIBRATION_MEASURE_FRONT)
|
||||
backlash.distance_mm[Y_AXIS] = m.backlash[FRONT];
|
||||
backlash.distance_mm.y = m.backlash[FRONT];
|
||||
#elif ENABLED(CALIBRATION_MEASURE_BACK)
|
||||
backlash.distance_mm[Y_AXIS] = m.backlash[BACK];
|
||||
backlash.distance_mm.y = m.backlash[BACK];
|
||||
#endif
|
||||
|
||||
backlash.distance_mm[Z_AXIS] = m.backlash[TOP];
|
||||
backlash.distance_mm.z = m.backlash[TOP];
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(BACKLASH_GCODE)
|
||||
// Turn on backlash compensation and move in all
|
||||
// directions to take up any backlash
|
||||
|
||||
{
|
||||
// New scope for TEMPORARY_BACKLASH_CORRECTION
|
||||
TEMPORARY_BACKLASH_CORRECTION(all_on);
|
||||
TEMPORARY_BACKLASH_SMOOTHING(0.0f);
|
||||
move_to(
|
||||
X_AXIS, current_position[X_AXIS] + 3,
|
||||
Y_AXIS, current_position[Y_AXIS] + 3,
|
||||
Z_AXIS, current_position[Z_AXIS] + 3
|
||||
);
|
||||
move_to(
|
||||
X_AXIS, current_position[X_AXIS] - 3,
|
||||
Y_AXIS, current_position[Y_AXIS] - 3,
|
||||
Z_AXIS, current_position[Z_AXIS] - 3
|
||||
);
|
||||
const xyz_float_t move = { 3, 3, 3 };
|
||||
current_position += move; calibration_move();
|
||||
current_position -= move; calibration_move();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void update_measurements(measurements_t &m, const AxisEnum axis) {
|
||||
const float true_center[XYZ] = CALIBRATION_OBJECT_CENTER;
|
||||
current_position[axis] += m.pos_error[axis];
|
||||
m.obj_center[axis] = true_center[axis];
|
||||
m.pos_error[axis] = 0;
|
||||
@ -508,12 +477,12 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const
|
||||
// Adjust the hotend offset
|
||||
#if HAS_HOTEND_OFFSET
|
||||
#if HAS_X_CENTER
|
||||
hotend_offset[X_AXIS][extruder] += m.pos_error[X_AXIS];
|
||||
hotend_offset[extruder].x += m.pos_error.x;
|
||||
#endif
|
||||
#if HAS_Y_CENTER
|
||||
hotend_offset[Y_AXIS][extruder] += m.pos_error[Y_AXIS];
|
||||
hotend_offset[extruder].y += m.pos_error.y;
|
||||
#endif
|
||||
hotend_offset[Z_AXIS][extruder] += m.pos_error[Z_AXIS];
|
||||
hotend_offset[extruder].z += m.pos_error.z;
|
||||
normalize_hotend_offsets();
|
||||
#endif
|
||||
|
||||
@ -589,7 +558,8 @@ inline void calibrate_all() {
|
||||
// Do a slow and precise calibration of the toolheads
|
||||
calibrate_all_toolheads(m, CALIBRATION_MEASUREMENT_UNCERTAIN);
|
||||
|
||||
move_to(X_AXIS, 150); // Park nozzle away from calibration object
|
||||
current_position.x = X_CENTER;
|
||||
calibration_move(); // Park nozzle away from calibration object
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,13 +74,14 @@ void GcodeSuite::M48() {
|
||||
|
||||
const ProbePtRaise raise_after = parser.boolval('E') ? PROBE_PT_STOW : PROBE_PT_RAISE;
|
||||
|
||||
float X_current = current_position[X_AXIS],
|
||||
Y_current = current_position[Y_AXIS];
|
||||
xy_float_t next_pos = current_position;
|
||||
|
||||
const float X_probe_location = parser.linearval('X', X_current + probe_offset[X_AXIS]),
|
||||
Y_probe_location = parser.linearval('Y', Y_current + probe_offset[Y_AXIS]);
|
||||
const xy_pos_t probe_pos = {
|
||||
parser.linearval('X', next_pos.x + probe_offset.x),
|
||||
parser.linearval('Y', next_pos.y + probe_offset.y)
|
||||
};
|
||||
|
||||
if (!position_is_reachable_by_probe(X_probe_location, Y_probe_location)) {
|
||||
if (!position_is_reachable_by_probe(probe_pos)) {
|
||||
SERIAL_ECHOLNPGM("? (X,Y) out of bounds.");
|
||||
return;
|
||||
}
|
||||
@ -116,7 +117,7 @@ void GcodeSuite::M48() {
|
||||
float mean = 0.0, sigma = 0.0, min = 99999.9, max = -99999.9, sample_set[n_samples];
|
||||
|
||||
// Move to the first point, deploy, and probe
|
||||
const float t = probe_at_point(X_probe_location, Y_probe_location, raise_after, verbose_level);
|
||||
const float t = probe_at_point(probe_pos, raise_after, verbose_level);
|
||||
bool probing_good = !isnan(t);
|
||||
|
||||
if (probing_good) {
|
||||
@ -165,32 +166,31 @@ void GcodeSuite::M48() {
|
||||
while (angle < 0.0) angle += 360.0; // outside of this range. It looks like they behave correctly with
|
||||
// numbers outside of the range, but just to be safe we clamp them.
|
||||
|
||||
X_current = X_probe_location - probe_offset[X_AXIS] + cos(RADIANS(angle)) * radius;
|
||||
Y_current = Y_probe_location - probe_offset[Y_AXIS] + sin(RADIANS(angle)) * radius;
|
||||
next_pos.set(probe_pos.x - probe_offset.x + cos(RADIANS(angle)) * radius,
|
||||
probe_pos.y - probe_offset.y + sin(RADIANS(angle)) * radius);
|
||||
|
||||
#if DISABLED(DELTA)
|
||||
LIMIT(X_current, X_MIN_POS, X_MAX_POS);
|
||||
LIMIT(Y_current, Y_MIN_POS, Y_MAX_POS);
|
||||
LIMIT(next_pos.x, X_MIN_POS, X_MAX_POS);
|
||||
LIMIT(next_pos.y, Y_MIN_POS, Y_MAX_POS);
|
||||
#else
|
||||
// If we have gone out too far, we can do a simple fix and scale the numbers
|
||||
// back in closer to the origin.
|
||||
while (!position_is_reachable_by_probe(X_current, Y_current)) {
|
||||
X_current *= 0.8;
|
||||
Y_current *= 0.8;
|
||||
while (!position_is_reachable_by_probe(next_pos)) {
|
||||
next_pos *= 0.8;
|
||||
if (verbose_level > 3)
|
||||
SERIAL_ECHOLNPAIR("Moving inward: X", X_current, " Y", Y_current);
|
||||
SERIAL_ECHOLNPAIR("Moving inward: X", next_pos.x, " Y", next_pos.y);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (verbose_level > 3)
|
||||
SERIAL_ECHOLNPAIR("Going to: X", X_current, " Y", Y_current, " Z", current_position[Z_AXIS]);
|
||||
SERIAL_ECHOLNPAIR("Going to: X", next_pos.x, " Y", next_pos.y);
|
||||
|
||||
do_blocking_move_to_xy(X_current, Y_current);
|
||||
do_blocking_move_to_xy(next_pos);
|
||||
} // n_legs loop
|
||||
} // n_legs
|
||||
|
||||
// Probe a single point
|
||||
sample_set[n] = probe_at_point(X_probe_location, Y_probe_location, raise_after, 0);
|
||||
sample_set[n] = probe_at_point(probe_pos, raise_after, 0);
|
||||
|
||||
// Break the loop if the probe fails
|
||||
probing_good = !isnan(sample_set[n]);
|
||||
|
@ -43,14 +43,14 @@
|
||||
* Z = Gamma (Tower 3) angle trim
|
||||
*/
|
||||
void GcodeSuite::M665() {
|
||||
if (parser.seen('H')) delta_height = parser.value_linear_units();
|
||||
if (parser.seen('L')) delta_diagonal_rod = parser.value_linear_units();
|
||||
if (parser.seen('R')) delta_radius = parser.value_linear_units();
|
||||
if (parser.seen('S')) delta_segments_per_second = parser.value_float();
|
||||
if (parser.seen('B')) delta_calibration_radius = parser.value_float();
|
||||
if (parser.seen('X')) delta_tower_angle_trim[A_AXIS] = parser.value_float();
|
||||
if (parser.seen('Y')) delta_tower_angle_trim[B_AXIS] = parser.value_float();
|
||||
if (parser.seen('Z')) delta_tower_angle_trim[C_AXIS] = parser.value_float();
|
||||
if (parser.seen('H')) delta_height = parser.value_linear_units();
|
||||
if (parser.seen('L')) delta_diagonal_rod = parser.value_linear_units();
|
||||
if (parser.seen('R')) delta_radius = parser.value_linear_units();
|
||||
if (parser.seen('S')) delta_segments_per_second = parser.value_float();
|
||||
if (parser.seen('B')) delta_calibration_radius = parser.value_float();
|
||||
if (parser.seen('X')) delta_tower_angle_trim.a = parser.value_float();
|
||||
if (parser.seen('Y')) delta_tower_angle_trim.b = parser.value_float();
|
||||
if (parser.seen('Z')) delta_tower_angle_trim.c = parser.value_float();
|
||||
recalc_delta_settings();
|
||||
}
|
||||
|
||||
@ -76,13 +76,13 @@
|
||||
|
||||
#if HAS_SCARA_OFFSET
|
||||
|
||||
if (parser.seenval('Z')) scara_home_offset[Z_AXIS] = parser.value_linear_units();
|
||||
if (parser.seenval('Z')) scara_home_offset.z = parser.value_linear_units();
|
||||
|
||||
const bool hasA = parser.seenval('A'), hasP = parser.seenval('P'), hasX = parser.seenval('X');
|
||||
const uint8_t sumAPX = hasA + hasP + hasX;
|
||||
if (sumAPX) {
|
||||
if (sumAPX == 1)
|
||||
scara_home_offset[A_AXIS] = parser.value_float();
|
||||
scara_home_offset.a = parser.value_float();
|
||||
else {
|
||||
SERIAL_ERROR_MSG("Only one of A, P, or X is allowed.");
|
||||
return;
|
||||
@ -93,7 +93,7 @@
|
||||
const uint8_t sumBTY = hasB + hasT + hasY;
|
||||
if (sumBTY) {
|
||||
if (sumBTY == 1)
|
||||
scara_home_offset[B_AXIS] = parser.value_float();
|
||||
scara_home_offset.b = parser.value_float();
|
||||
else {
|
||||
SERIAL_ERROR_MSG("Only one of B, T, or Y is allowed.");
|
||||
return;
|
||||
|
Reference in New Issue
Block a user