🏗️ Support for up to 6 linear axes (#19112)

Co-authored-by: Scott Lahteine <github@thinkyhead.com>
This commit is contained in:
DerAndere
2021-06-05 09:18:47 +02:00
committed by Scott Lahteine
parent d3c56a76e7
commit c1fca91103
98 changed files with 5040 additions and 2256 deletions

View File

@ -245,6 +245,9 @@ void home_delta() {
TERN_(X_SENSORLESS, sensorless_t stealth_states_x = start_sensorless_homing_per_axis(X_AXIS));
TERN_(Y_SENSORLESS, sensorless_t stealth_states_y = start_sensorless_homing_per_axis(Y_AXIS));
TERN_(Z_SENSORLESS, sensorless_t stealth_states_z = start_sensorless_homing_per_axis(Z_AXIS));
TERN_(I_SENSORLESS, sensorless_t stealth_states_i = start_sensorless_homing_per_axis(I_AXIS));
TERN_(J_SENSORLESS, sensorless_t stealth_states_j = start_sensorless_homing_per_axis(J_AXIS));
TERN_(K_SENSORLESS, sensorless_t stealth_states_k = start_sensorless_homing_per_axis(K_AXIS));
#endif
// Move all carriages together linearly until an endstop is hit.
@ -257,6 +260,9 @@ void home_delta() {
TERN_(X_SENSORLESS, end_sensorless_homing_per_axis(X_AXIS, stealth_states_x));
TERN_(Y_SENSORLESS, end_sensorless_homing_per_axis(Y_AXIS, stealth_states_y));
TERN_(Z_SENSORLESS, end_sensorless_homing_per_axis(Z_AXIS, stealth_states_z));
TERN_(I_SENSORLESS, end_sensorless_homing_per_axis(I_AXIS, stealth_states_i));
TERN_(J_SENSORLESS, end_sensorless_homing_per_axis(J_AXIS, stealth_states_j));
TERN_(K_SENSORLESS, end_sensorless_homing_per_axis(K_AXIS, stealth_states_k));
#endif
endstops.validate_homing_move();

View File

@ -259,6 +259,66 @@ void Endstops::init() {
#endif
#endif
#if HAS_I_MIN
#if ENABLED(ENDSTOPPULLUP_IMIN)
SET_INPUT_PULLUP(I_MIN_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_IMIN)
SET_INPUT_PULLDOWN(I_MIN_PIN);
#else
SET_INPUT(I_MIN_PIN);
#endif
#endif
#if HAS_I_MAX
#if ENABLED(ENDSTOPPULLUP_IMAX)
SET_INPUT_PULLUP(I_MAX_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_IMAX)
SET_INPUT_PULLDOWN(I_MAX_PIN);
#else
SET_INPUT(I_MAX_PIN);
#endif
#endif
#if HAS_J_MIN
#if ENABLED(ENDSTOPPULLUP_JMIN)
SET_INPUT_PULLUP(J_MIN_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_IMIN)
SET_INPUT_PULLDOWN(J_MIN_PIN);
#else
SET_INPUT(J_MIN_PIN);
#endif
#endif
#if HAS_J_MAX
#if ENABLED(ENDSTOPPULLUP_JMAX)
SET_INPUT_PULLUP(J_MAX_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_JMAX)
SET_INPUT_PULLDOWN(J_MAX_PIN);
#else
SET_INPUT(J_MAX_PIN);
#endif
#endif
#if HAS_K_MIN
#if ENABLED(ENDSTOPPULLUP_KMIN)
SET_INPUT_PULLUP(K_MIN_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_KMIN)
SET_INPUT_PULLDOWN(K_MIN_PIN);
#else
SET_INPUT(K_MIN_PIN);
#endif
#endif
#if HAS_K_MAX
#if ENABLED(ENDSTOPPULLUP_KMAX)
SET_INPUT_PULLUP(K_MAX_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_KMIN)
SET_INPUT_PULLDOWN(K_MAX_PIN);
#else
SET_INPUT(K_MAX_PIN);
#endif
#endif
#if PIN_EXISTS(CALIBRATION)
#if ENABLED(CALIBRATION_PIN_PULLUP)
SET_INPUT_PULLUP(CALIBRATION_PIN);
@ -361,7 +421,7 @@ void Endstops::event_handler() {
prev_hit_state = hit_state;
if (hit_state) {
#if HAS_STATUS_MESSAGE
char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' '),
char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' '),
chrP = ' ';
#define _SET_STOP_CHAR(A,C) (chr## A = C)
#else
@ -378,12 +438,20 @@ void Endstops::event_handler() {
#define ENDSTOP_HIT_TEST_X() _ENDSTOP_HIT_TEST(X,'X')
#define ENDSTOP_HIT_TEST_Y() _ENDSTOP_HIT_TEST(Y,'Y')
#define ENDSTOP_HIT_TEST_Z() _ENDSTOP_HIT_TEST(Z,'Z')
#define ENDSTOP_HIT_TEST_I() _ENDSTOP_HIT_TEST(I,'I')
#define ENDSTOP_HIT_TEST_J() _ENDSTOP_HIT_TEST(J,'J')
#define ENDSTOP_HIT_TEST_K() _ENDSTOP_HIT_TEST(K,'K')
SERIAL_ECHO_START();
SERIAL_ECHOPGM(STR_ENDSTOPS_HIT);
ENDSTOP_HIT_TEST_X();
ENDSTOP_HIT_TEST_Y();
ENDSTOP_HIT_TEST_Z();
LINEAR_AXIS_CODE(
ENDSTOP_HIT_TEST_X(),
ENDSTOP_HIT_TEST_Y(),
ENDSTOP_HIT_TEST_Z(),
_ENDSTOP_HIT_TEST(I,'I'),
_ENDSTOP_HIT_TEST(J,'J'),
_ENDSTOP_HIT_TEST(K,'K')
);
#if HAS_CUSTOM_PROBE_PIN
#define P_AXIS Z_AXIS
@ -395,7 +463,7 @@ void Endstops::event_handler() {
ui.status_printf_P(0,
PSTR(S_FMT GANG_N_1(LINEAR_AXES, " %c") " %c"),
GET_TEXT(MSG_LCD_ENDSTOPS),
LINEAR_AXIS_LIST(chrX, chrY, chrZ), chrP
LINEAR_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK), chrP
)
);
@ -477,6 +545,24 @@ void _O2 Endstops::report_states() {
#if HAS_Z4_MAX
ES_REPORT(Z4_MAX);
#endif
#if HAS_I_MIN
ES_REPORT(I_MIN);
#endif
#if HAS_I_MAX
ES_REPORT(I_MAX);
#endif
#if HAS_J_MIN
ES_REPORT(J_MIN);
#endif
#if HAS_J_MAX
ES_REPORT(J_MAX);
#endif
#if HAS_K_MIN
ES_REPORT(K_MIN);
#endif
#if HAS_K_MAX
ES_REPORT(K_MAX);
#endif
#if BOTH(MARLIN_DEV_MODE, PROBE_ACTIVATION_SWITCH)
print_es_state(probe_switch_activated(), PSTR(STR_PROBE_EN));
#endif
@ -549,6 +635,10 @@ void Endstops::update() {
#define Z_AXIS_HEAD Z_AXIS
#endif
#define I_AXIS_HEAD I_AXIS
#define J_AXIS_HEAD J_AXIS
#define K_AXIS_HEAD K_AXIS
/**
* Check and update endstops
*/
@ -656,6 +746,84 @@ void Endstops::update() {
#endif
#endif
#if HAS_I_MIN
#if ENABLED(I_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(I, MIN);
#if HAS_I2_MIN
UPDATE_ENDSTOP_BIT(I2, MAX);
#else
COPY_LIVE_STATE(I_MIN, I2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(I, MIN);
#endif
#endif
#if HAS_I_MAX
#if ENABLED(I_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(I, MAX);
#if HAS_I2_MAX
UPDATE_ENDSTOP_BIT(I2, MAX);
#else
COPY_LIVE_STATE(I_MAX, I2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(I, MAX);
#endif
#endif
#if HAS_J_MIN
#if ENABLED(J_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(J, MIN);
#if HAS_J2_MIN
UPDATE_ENDSTOP_BIT(J2, MIN);
#else
COPY_LIVE_STATE(J_MIN, J2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(J, MIN);
#endif
#endif
#if HAS_J_MAX
#if ENABLED(J_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(J, MAX);
#if HAS_J2_MAX
UPDATE_ENDSTOP_BIT(J2, MAX);
#else
COPY_LIVE_STATE(J_MAX, J2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(J, MAX);
#endif
#endif
#if HAS_K_MIN
#if ENABLED(K_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(K, MIN);
#if HAS_K2_MIN
UPDATE_ENDSTOP_BIT(K2, MIN);
#else
COPY_LIVE_STATE(K_MIN, K2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(K, MIN);
#endif
#endif
#if HAS_K_MAX
#if ENABLED(K_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(K, MAX);
#if HAS_K2_MAX
UPDATE_ENDSTOP_BIT(K2, MAX);
#else
COPY_LIVE_STATE(K_MAX, K2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(K, MAX);
#endif
#endif
#if ENDSTOP_NOISE_THRESHOLD
/**
@ -804,79 +972,128 @@ void Endstops::update() {
}
}
if (stepper.axis_is_moving(Y_AXIS)) {
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
#if HAS_Y_MIN || (Y_SPI_SENSORLESS && Y_HOME_TO_MIN)
PROCESS_ENDSTOP_Y(MIN);
#if CORE_DIAG(XY, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Y,MIN);
#elif CORE_DIAG(XY, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Y,MIN);
#elif CORE_DIAG(YZ, Z, MIN)
PROCESS_CORE_ENDSTOP(Z,MIN,Y,MIN);
#elif CORE_DIAG(YZ, Z, MAX)
PROCESS_CORE_ENDSTOP(Z,MAX,Y,MIN);
#if HAS_Y_AXIS
if (stepper.axis_is_moving(Y_AXIS)) {
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
#if HAS_Y_MIN || (Y_SPI_SENSORLESS && Y_HOME_TO_MIN)
PROCESS_ENDSTOP_Y(MIN);
#if CORE_DIAG(XY, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Y,MIN);
#elif CORE_DIAG(XY, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Y,MIN);
#elif CORE_DIAG(YZ, Z, MIN)
PROCESS_CORE_ENDSTOP(Z,MIN,Y,MIN);
#elif CORE_DIAG(YZ, Z, MAX)
PROCESS_CORE_ENDSTOP(Z,MAX,Y,MIN);
#endif
#endif
#endif
}
else { // +direction
#if HAS_Y_MAX || (Y_SPI_SENSORLESS && Y_HOME_TO_MAX)
PROCESS_ENDSTOP_Y(MAX);
#if CORE_DIAG(XY, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Y,MAX);
#elif CORE_DIAG(XY, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Y,MAX);
#elif CORE_DIAG(YZ, Z, MIN)
PROCESS_CORE_ENDSTOP(Z,MIN,Y,MAX);
#elif CORE_DIAG(YZ, Z, MAX)
PROCESS_CORE_ENDSTOP(Z,MAX,Y,MAX);
}
else { // +direction
#if HAS_Y_MAX || (Y_SPI_SENSORLESS && Y_HOME_TO_MAX)
PROCESS_ENDSTOP_Y(MAX);
#if CORE_DIAG(XY, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Y,MAX);
#elif CORE_DIAG(XY, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Y,MAX);
#elif CORE_DIAG(YZ, Z, MIN)
PROCESS_CORE_ENDSTOP(Z,MIN,Y,MAX);
#elif CORE_DIAG(YZ, Z, MAX)
PROCESS_CORE_ENDSTOP(Z,MAX,Y,MAX);
#endif
#endif
#endif
}
}
}
#endif
if (stepper.axis_is_moving(Z_AXIS)) {
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
#if HAS_Z_AXIS
if (stepper.axis_is_moving(Z_AXIS)) {
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
#if HAS_Z_MIN || (Z_SPI_SENSORLESS && Z_HOME_TO_MIN)
if ( TERN1(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, z_probe_enabled)
&& TERN1(HAS_CUSTOM_PROBE_PIN, !z_probe_enabled)
) PROCESS_ENDSTOP_Z(MIN);
#if CORE_DIAG(XZ, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Z,MIN);
#elif CORE_DIAG(XZ, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Z,MIN);
#elif CORE_DIAG(YZ, Y, MIN)
PROCESS_CORE_ENDSTOP(Y,MIN,Z,MIN);
#elif CORE_DIAG(YZ, Y, MAX)
PROCESS_CORE_ENDSTOP(Y,MAX,Z,MIN);
#if HAS_Z_MIN || (Z_SPI_SENSORLESS && Z_HOME_TO_MIN)
if ( TERN1(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, z_probe_enabled)
&& TERN1(HAS_CUSTOM_PROBE_PIN, !z_probe_enabled)
) PROCESS_ENDSTOP_Z(MIN);
#if CORE_DIAG(XZ, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Z,MIN);
#elif CORE_DIAG(XZ, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Z,MIN);
#elif CORE_DIAG(YZ, Y, MIN)
PROCESS_CORE_ENDSTOP(Y,MIN,Z,MIN);
#elif CORE_DIAG(YZ, Y, MAX)
PROCESS_CORE_ENDSTOP(Y,MAX,Z,MIN);
#endif
#endif
#endif
// When closing the gap check the enabled probe
#if HAS_CUSTOM_PROBE_PIN
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE);
#endif
}
else { // Z +direction. Gantry up, bed down.
#if HAS_Z_MAX || (Z_SPI_SENSORLESS && Z_HOME_TO_MAX)
#if ENABLED(Z_MULTI_ENDSTOPS)
PROCESS_ENDSTOP_Z(MAX);
#elif !HAS_CUSTOM_PROBE_PIN || Z_MAX_PIN != Z_MIN_PROBE_PIN // No probe or probe is Z_MIN || Probe is not Z_MAX
PROCESS_ENDSTOP(Z, MAX);
// When closing the gap check the enabled probe
#if HAS_CUSTOM_PROBE_PIN
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE);
#endif
#if CORE_DIAG(XZ, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Z,MAX);
#elif CORE_DIAG(XZ, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Z,MAX);
#elif CORE_DIAG(YZ, Y, MIN)
PROCESS_CORE_ENDSTOP(Y,MIN,Z,MAX);
#elif CORE_DIAG(YZ, Y, MAX)
PROCESS_CORE_ENDSTOP(Y,MAX,Z,MAX);
}
else { // Z +direction. Gantry up, bed down.
#if HAS_Z_MAX || (Z_SPI_SENSORLESS && Z_HOME_TO_MAX)
#if ENABLED(Z_MULTI_ENDSTOPS)
PROCESS_ENDSTOP_Z(MAX);
#elif !HAS_CUSTOM_PROBE_PIN || Z_MAX_PIN != Z_MIN_PROBE_PIN // No probe or probe is Z_MIN || Probe is not Z_MAX
PROCESS_ENDSTOP(Z, MAX);
#endif
#if CORE_DIAG(XZ, X, MIN)
PROCESS_CORE_ENDSTOP(X,MIN,Z,MAX);
#elif CORE_DIAG(XZ, X, MAX)
PROCESS_CORE_ENDSTOP(X,MAX,Z,MAX);
#elif CORE_DIAG(YZ, Y, MIN)
PROCESS_CORE_ENDSTOP(Y,MIN,Z,MAX);
#elif CORE_DIAG(YZ, Y, MAX)
PROCESS_CORE_ENDSTOP(Y,MAX,Z,MAX);
#endif
#endif
#endif
}
}
}
#endif
#if LINEAR_AXES >= 4
if (stepper.axis_is_moving(I_AXIS)) {
if (stepper.motor_direction(I_AXIS_HEAD)) { // -direction
#if HAS_I_MIN || (I_SPI_SENSORLESS && I_HOME_TO_MIN)
PROCESS_ENDSTOP(I, MIN);
#endif
}
else { // +direction
#if HAS_I_MAX || (I_SPI_SENSORLESS && I_HOME_TO_MAX)
PROCESS_ENDSTOP(I, MAX);
#endif
}
}
#endif
#if LINEAR_AXES >= 5
if (stepper.axis_is_moving(J_AXIS)) {
if (stepper.motor_direction(J_AXIS_HEAD)) { // -direction
#if HAS_J_MIN || (J_SPI_SENSORLESS && J_HOME_TO_MIN)
PROCESS_ENDSTOP(J, MIN);
#endif
}
else { // +direction
#if HAS_J_MAX || (J_SPI_SENSORLESS && J_HOME_TO_MAX)
PROCESS_ENDSTOP(J, MAX);
#endif
}
}
#endif
#if LINEAR_AXES >= 6
if (stepper.axis_is_moving(K_AXIS)) {
if (stepper.motor_direction(K_AXIS_HEAD)) { // -direction
#if HAS_K_MIN || (K_SPI_SENSORLESS && K_HOME_TO_MIN)
PROCESS_ENDSTOP(K, MIN);
#endif
}
else { // +direction
#if HAS_K_MAX || (K_SPI_SENSORLESS && K_HOME_TO_MAX)
PROCESS_ENDSTOP(K, MAX);
#endif
}
}
#endif
} // Endstops::update()
#if ENABLED(SPI_ENDSTOPS)
@ -919,6 +1136,24 @@ void Endstops::update() {
hit = true;
}
#endif
#if I_SPI_SENSORLESS
if (tmc_spi_homing.i && stepperI.test_stall_status()) {
SBI(live_state, I_ENDSTOP);
hit = true;
}
#endif
#if J_SPI_SENSORLESS
if (tmc_spi_homing.j && stepperJ.test_stall_status()) {
SBI(live_state, J_ENDSTOP);
hit = true;
}
#endif
#if K_SPI_SENSORLESS
if (tmc_spi_homing.k && stepperK.test_stall_status()) {
SBI(live_state, K_ENDSTOP);
hit = true;
}
#endif
if (TERN0(ENDSTOP_INTERRUPTS_FEATURE, hit)) update();
@ -929,6 +1164,9 @@ void Endstops::update() {
TERN_(X_SPI_SENSORLESS, CBI(live_state, X_ENDSTOP));
TERN_(Y_SPI_SENSORLESS, CBI(live_state, Y_ENDSTOP));
TERN_(Z_SPI_SENSORLESS, CBI(live_state, Z_ENDSTOP));
TERN_(I_SPI_SENSORLESS, CBI(live_state, I_ENDSTOP));
TERN_(J_SPI_SENSORLESS, CBI(live_state, J_ENDSTOP));
TERN_(K_SPI_SENSORLESS, CBI(live_state, K_ENDSTOP));
}
#endif // SPI_ENDSTOPS
@ -1005,6 +1243,24 @@ void Endstops::update() {
#if HAS_Z4_MAX
ES_GET_STATE(Z4_MAX);
#endif
#if HAS_I_MAX
ES_GET_STATE(I_MAX);
#endif
#if HAS_I_MIN
ES_GET_STATE(I_MIN);
#endif
#if HAS_J_MAX
ES_GET_STATE(J_MAX);
#endif
#if HAS_J_MIN
ES_GET_STATE(J_MIN);
#endif
#if HAS_K_MAX
ES_GET_STATE(K_MAX);
#endif
#if HAS_K_MIN
ES_GET_STATE(K_MIN);
#endif
uint16_t endstop_change = live_state_local ^ old_live_state_local;
#define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPAIR(" " STRINGIFY(S) ":", TEST(live_state_local, S))
@ -1061,6 +1317,24 @@ void Endstops::update() {
#if HAS_Z4_MAX
ES_REPORT_CHANGE(Z4_MAX);
#endif
#if HAS_I_MIN
ES_REPORT_CHANGE(I_MIN);
#endif
#if HAS_I_MAX
ES_REPORT_CHANGE(I_MAX);
#endif
#if HAS_J_MIN
ES_REPORT_CHANGE(J_MIN);
#endif
#if HAS_J_MAX
ES_REPORT_CHANGE(J_MAX);
#endif
#if HAS_K_MIN
ES_REPORT_CHANGE(K_MIN);
#endif
#if HAS_K_MAX
ES_REPORT_CHANGE(K_MAX);
#endif
SERIAL_ECHOLNPGM("\n");
analogWrite(pin_t(LED_PIN), local_LED_status);
local_LED_status ^= 255;

View File

@ -39,6 +39,12 @@ enum EndstopEnum : char {
_ES_ITEM(HAS_Y_MAX, Y_MAX)
_ES_ITEM(HAS_Z_MIN, Z_MIN)
_ES_ITEM(HAS_Z_MAX, Z_MAX)
_ES_ITEM(HAS_I_MIN, I_MIN)
_ES_ITEM(HAS_I_MAX, I_MAX)
_ES_ITEM(HAS_J_MIN, J_MIN)
_ES_ITEM(HAS_J_MAX, J_MAX)
_ES_ITEM(HAS_K_MIN, K_MIN)
_ES_ITEM(HAS_K_MAX, K_MAX)
// Extra Endstops for XYZ
#if ENABLED(X_DUAL_ENDSTOPS)

View File

@ -89,7 +89,7 @@ bool relative_mode; // = false;
#define Z_INIT_POS Z_HOME_POS
#endif
xyze_pos_t current_position = LOGICAL_AXIS_ARRAY(0, X_HOME_POS, Y_HOME_POS, Z_INIT_POS);
xyze_pos_t current_position = LOGICAL_AXIS_ARRAY(0, X_HOME_POS, Y_HOME_POS, Z_INIT_POS, I_HOME_POS, J_HOME_POS, K_HOME_POS);
/**
* Cartesian Destination
@ -143,7 +143,7 @@ xyz_pos_t cartes;
#if IS_KINEMATIC
abc_pos_t delta;
abce_pos_t delta;
#if HAS_SCARA_OFFSET
abc_pos_t scara_home_offset;
@ -196,7 +196,14 @@ inline void report_more_positions() {
inline void report_logical_position(const xyze_pos_t &rpos) {
const xyze_pos_t lpos = rpos.asLogical();
SERIAL_ECHOPAIR_P(
LIST_N(DOUBLE(LINEAR_AXES), X_LBL, lpos.x, SP_Y_LBL, lpos.y, SP_Z_LBL, lpos.z)
LIST_N(DOUBLE(LINEAR_AXES),
X_LBL, lpos.x,
SP_Y_LBL, lpos.y,
SP_Z_LBL, lpos.z,
SP_I_LBL, lpos.i,
SP_J_LBL, lpos.j,
SP_K_LBL, lpos.k
)
#if HAS_EXTRUDERS
, SP_E_LBL, lpos.e
#endif
@ -209,7 +216,10 @@ void report_real_position() {
get_cartesian_from_steppers();
xyze_pos_t npos = LOGICAL_AXIS_ARRAY(
planner.get_axis_position_mm(E_AXIS),
cartes.x, cartes.y, cartes.z
cartes.x, cartes.y, cartes.z,
planner.get_axis_position_mm(I_AXIS),
planner.get_axis_position_mm(J_AXIS),
planner.get_axis_position_mm(K_AXIS)
);
TERN_(HAS_POSITION_MODIFIERS, planner.unapply_modifiers(npos, true));
@ -334,20 +344,21 @@ void sync_plan_position() {
void get_cartesian_from_steppers() {
#if ENABLED(DELTA)
forward_kinematics(planner.get_axis_positions_mm());
#else
#if IS_SCARA
forward_kinematics(
planner.get_axis_position_degrees(A_AXIS)
, planner.get_axis_position_degrees(B_AXIS)
#if ENABLED(AXEL_TPARA)
, planner.get_axis_position_degrees(C_AXIS)
#endif
);
#else
cartes.x = planner.get_axis_position_mm(X_AXIS);
cartes.y = planner.get_axis_position_mm(Y_AXIS);
#endif
#elif IS_SCARA
forward_kinematics(
planner.get_axis_position_degrees(A_AXIS), planner.get_axis_position_degrees(B_AXIS)
OPTARG(AXEL_TPARA, planner.get_axis_position_degrees(C_AXIS))
);
cartes.z = planner.get_axis_position_mm(Z_AXIS);
#else
LINEAR_AXIS_CODE(
cartes.x = planner.get_axis_position_mm(X_AXIS),
cartes.y = planner.get_axis_position_mm(Y_AXIS),
cartes.z = planner.get_axis_position_mm(Z_AXIS),
cartes.i = planner.get_axis_position_mm(I_AXIS),
cartes.j = planner.get_axis_position_mm(J_AXIS),
cartes.k = planner.get_axis_position_mm(K_AXIS)
);
#endif
}
@ -366,13 +377,9 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
get_cartesian_from_steppers();
xyze_pos_t pos = cartes;
#if HAS_EXTRUDERS
pos.e = planner.get_axis_position_mm(E_AXIS);
#endif
TERN_(HAS_EXTRUDERS, pos.e = planner.get_axis_position_mm(E_AXIS));
#if HAS_POSITION_MODIFIERS
planner.unapply_modifiers(pos, true);
#endif
TERN_(HAS_POSITION_MODIFIERS, planner.unapply_modifiers(pos, true));
if (axis == ALL_AXES_ENUM)
current_position = pos;
@ -385,7 +392,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
* (or from wherever it has been told it is located).
*/
void line_to_current_position(const_feedRate_t fr_mm_s/*=feedrate_mm_s*/) {
planner.buffer_line(current_position, fr_mm_s, active_extruder);
planner.buffer_line(current_position, fr_mm_s);
}
#if HAS_EXTRUDERS
@ -411,7 +418,7 @@ void line_to_current_position(const_feedRate_t fr_mm_s/*=feedrate_mm_s*/) {
#else
if (current_position == destination) return;
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
planner.buffer_line(destination, scaled_fr_mm_s);
#endif
current_position = destination;
@ -449,25 +456,26 @@ void _internal_move_to_destination(const_feedRate_t fr_mm_s/*=0.0f*/
}
/**
* Plan a move to (X, Y, Z) with separation of the XY and Z components.
* Plan a move to (X, Y, Z, [I, [J, [K]]]) and set the current_position
* Plan a move to (X, Y, Z) with separation of Z from other components.
*
* - If Z is moving up, the Z move is done before XY.
* - If Z is moving down, the Z move is done after XY.
* - If Z is moving up, the Z move is done before XY, etc.
* - If Z is moving down, the Z move is done after XY, etc.
* - Delta may lower Z first to get into the free motion zone.
* - Before returning, wait for the planner buffer to empty.
*/
void do_blocking_move_to(
LINEAR_AXIS_LIST(const float rx, const float ry, const float rz),
const_feedRate_t fr_mm_s/*=0.0f*/
) {
void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s/*=0.0f*/) {
DEBUG_SECTION(log_move, "do_blocking_move_to", DEBUGGING(LEVELING));
if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", LINEAR_AXIS_LIST(rx, ry, rz));
if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", LINEAR_AXIS_ARGS());
const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS),
xy_feedrate = fr_mm_s ?: feedRate_t(XY_PROBE_FEEDRATE_MM_S);
const feedRate_t xy_feedrate = fr_mm_s ?: feedRate_t(XY_PROBE_FEEDRATE_MM_S);
#if HAS_Z_AXIS
const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS);
#endif
#if EITHER(DELTA, IS_SCARA)
if (!position_is_reachable(rx, ry)) return;
if (!position_is_reachable(x, y)) return;
destination = current_position; // sync destination at the start
#endif
@ -479,8 +487,8 @@ void do_blocking_move_to(
// when in the danger zone
if (current_position.z > delta_clip_start_height) {
if (rz > delta_clip_start_height) { // staying in the danger zone
destination.set(rx, ry, rz); // move directly (uninterpolated)
if (z > delta_clip_start_height) { // staying in the danger zone
destination.set(x, y, z); // move directly (uninterpolated)
prepare_internal_fast_move_to_destination(); // set current_position from destination
if (DEBUGGING(LEVELING)) DEBUG_POS("danger zone move", current_position);
return;
@ -490,18 +498,18 @@ void do_blocking_move_to(
if (DEBUGGING(LEVELING)) DEBUG_POS("zone border move", current_position);
}
if (rz > current_position.z) { // raising?
destination.z = rz;
if (z > current_position.z) { // raising?
destination.z = z;
prepare_internal_fast_move_to_destination(z_feedrate); // set current_position from destination
if (DEBUGGING(LEVELING)) DEBUG_POS("z raise move", current_position);
}
destination.set(rx, ry);
destination.set(x, y);
prepare_internal_move_to_destination(); // set current_position from destination
if (DEBUGGING(LEVELING)) DEBUG_POS("xy move", current_position);
if (rz < current_position.z) { // lowering?
destination.z = rz;
if (z < current_position.z) { // lowering?
destination.z = z;
prepare_internal_fast_move_to_destination(z_feedrate); // set current_position from destination
if (DEBUGGING(LEVELING)) DEBUG_POS("z lower move", current_position);
}
@ -509,36 +517,40 @@ void do_blocking_move_to(
#elif IS_SCARA
// If Z needs to raise, do it before moving XY
if (destination.z < rz) {
destination.z = rz;
if (destination.z < z) {
destination.z = z;
prepare_internal_fast_move_to_destination(z_feedrate);
}
destination.set(rx, ry);
destination.set(x, y);
prepare_internal_fast_move_to_destination(xy_feedrate);
// If Z needs to lower, do it after moving XY
if (destination.z > rz) {
destination.z = rz;
if (destination.z > z) {
destination.z = z;
prepare_internal_fast_move_to_destination(z_feedrate);
}
#else
// If Z needs to raise, do it before moving XY
if (current_position.z < rz) {
current_position.z = rz;
line_to_current_position(z_feedrate);
}
#if HAS_Z_AXIS
// If Z needs to raise, do it before moving XY
if (current_position.z < z) {
current_position.z = z;
line_to_current_position(z_feedrate);
}
#endif
current_position.set(rx, ry);
current_position.set(x, y);
line_to_current_position(xy_feedrate);
// If Z needs to lower, do it after moving XY
if (current_position.z > rz) {
current_position.z = rz;
line_to_current_position(z_feedrate);
}
#if HAS_Z_AXIS
// If Z needs to lower, do it after moving XY
if (current_position.z > z) {
current_position.z = z;
line_to_current_position(z_feedrate);
}
#endif
#endif
@ -546,53 +558,94 @@ void do_blocking_move_to(
}
void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i), fr_mm_s);
do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i, current_position.j, current_position.k), fr_mm_s);
}
void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, raw.z), fr_mm_s);
do_blocking_move_to(LINEAR_AXIS_ELEM(raw), fr_mm_s);
}
void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, raw.z), fr_mm_s);
do_blocking_move_to(LINEAR_AXIS_ELEM(raw), fr_mm_s);
}
void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to(
LINEAR_AXIS_LIST(rx, current_position.y, current_position.z),
fr_mm_s
);
}
void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to(
LINEAR_AXIS_LIST(current_position.x, ry, current_position.z),
fr_mm_s
);
}
void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xy_z(current_position, rz, fr_mm_s);
}
void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to(
LINEAR_AXIS_LIST(rx, ry, current_position.z),
fr_mm_s
);
}
void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to_xy(raw.x, raw.y, fr_mm_s);
}
void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(
LINEAR_AXIS_LIST(raw.x, raw.y, z),
LINEAR_AXIS_LIST(rx, current_position.y, current_position.z, current_position.i, current_position.j, current_position.k),
fr_mm_s
);
}
void do_z_clearance(const_float_t zclear, const bool lower_allowed/*=false*/) {
float zdest = zclear;
if (!lower_allowed) NOLESS(zdest, current_position.z);
do_blocking_move_to_z(_MIN(zdest, Z_MAX_POS), TERN(HAS_BED_PROBE, z_probe_fast_mm_s, homing_feedrate(Z_AXIS)));
}
#if HAS_Y_AXIS
void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to(
LINEAR_AXIS_LIST(current_position.x, ry, current_position.z, current_position.i, current_position.j, current_position.k),
fr_mm_s
);
}
#endif
#if HAS_Z_AXIS
void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xy_z(current_position, rz, fr_mm_s);
}
#endif
#if LINEAR_AXES == 4
void do_blocking_move_to_i(const_float_t ri, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xyz_i(current_position, ri, fr_mm_s);
}
void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(raw.x, raw.y, raw.z, i, fr_mm_s);
}
#endif
#if LINEAR_AXES >= 5
void do_blocking_move_to_i(const_float_t ri, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xyz_i(current_position, ri, fr_mm_s);
}
void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(raw.x, raw.y, raw.z, i, raw.j, fr_mm_s);
}
void do_blocking_move_to_j(const_float_t rj, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xyzi_j(current_position, rj, fr_mm_s);
}
void do_blocking_move_to_xyzi_j(const xyze_pos_t &raw, const_float_t j, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(raw.x, raw.y, raw.z, raw.i, j, fr_mm_s);
}
#endif
#if LINEAR_AXES >= 6
void do_blocking_move_to_k(const_float_t rk, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xyzij_k(current_position, rk, fr_mm_s);
}
void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(raw.x, raw.y, raw.z, raw.i, raw.j, k, fr_mm_s);
}
#endif
#if HAS_Y_AXIS
void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to(
LINEAR_AXIS_LIST(rx, ry, current_position.z, current_position.i, current_position.j, current_position.k),
fr_mm_s
);
}
void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to_xy(raw.x, raw.y, fr_mm_s);
}
#endif
#if HAS_Z_AXIS
void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(
LINEAR_AXIS_LIST(raw.x, raw.y, z, current_position.i, current_position.j, current_position.k),
fr_mm_s
);
}
void do_z_clearance(const_float_t zclear, const bool lower_allowed/*=false*/) {
float zdest = zclear;
if (!lower_allowed) NOLESS(zdest, current_position.z);
do_blocking_move_to_z(_MIN(zdest, Z_MAX_POS), TERN(HAS_BED_PROBE, z_probe_fast_mm_s, homing_feedrate(Z_AXIS)));
}
#endif
//
// Prepare to do endstop or probe moves with custom feedrates.
@ -618,8 +671,8 @@ void restore_feedrate_and_scaling() {
// Software Endstops are based on the configured limits.
soft_endstops_t soft_endstop = {
true, false,
LINEAR_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS),
LINEAR_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS)
LINEAR_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS, I_MIN_POS, J_MIN_POS, K_MIN_POS),
LINEAR_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS, I_MAX_POS, J_MAX_POS, K_MAX_POS)
};
/**
@ -746,25 +799,59 @@ void restore_feedrate_and_scaling() {
#endif
}
if (axis_was_homed(Y_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Y)
NOLESS(target.y, soft_endstop.min.y);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Y)
NOMORE(target.y, soft_endstop.max.y);
#endif
}
#if HAS_Y_AXIS
if (axis_was_homed(Y_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Y)
NOLESS(target.y, soft_endstop.min.y);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Y)
NOMORE(target.y, soft_endstop.max.y);
#endif
}
#endif
#endif
if (axis_was_homed(Z_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Z)
NOLESS(target.z, soft_endstop.min.z);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Z)
NOMORE(target.z, soft_endstop.max.z);
#endif
}
#if HAS_Z_AXIS
if (axis_was_homed(Z_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Z)
NOLESS(target.z, soft_endstop.min.z);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Z)
NOMORE(target.z, soft_endstop.max.z);
#endif
}
#endif
#if LINEAR_AXES >= 4 // TODO (DerAndere): Find out why this was missing / removed
if (axis_was_homed(I_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_I)
NOLESS(target.i, soft_endstop.min.i);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_I)
NOMORE(target.i, soft_endstop.max.i);
#endif
}
#endif
#if LINEAR_AXES >= 5
if (axis_was_homed(J_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_J)
NOLESS(target.j, soft_endstop.min.j);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_J)
NOMORE(target.j, soft_endstop.max.j);
#endif
}
#endif
#if LINEAR_AXES >= 6
if (axis_was_homed(K_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_K)
NOLESS(target.k, soft_endstop.min.k);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_K)
NOMORE(target.k, soft_endstop.max.k);
#endif
}
#endif
}
#else // !HAS_SOFTWARE_ENDSTOPS
@ -824,7 +911,7 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
// If the move is only in Z/E don't split up the move
if (!diff.x && !diff.y) {
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
planner.buffer_line(destination, scaled_fr_mm_s);
return false; // caller will update current_position
}
@ -880,15 +967,11 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
while (--segments) {
segment_idle(next_idle_ms);
raw += segment_distance;
if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
)) break;
if (!planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, cartesian_segment_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration))) break;
}
// Ensure last segment arrives at target location.
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, cartesian_segment_mm
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
);
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, cartesian_segment_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration));
return false; // caller will update current_position
}
@ -910,7 +993,7 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
// If the move is only in Z/E don't split up the move
if (!diff.x && !diff.y) {
planner.buffer_line(destination, fr_mm_s, active_extruder);
planner.buffer_line(destination, fr_mm_s);
return;
}
@ -947,18 +1030,12 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
while (--segments) {
segment_idle(next_idle_ms);
raw += segment_distance;
if (!planner.buffer_line(raw, fr_mm_s, active_extruder, cartesian_segment_mm
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
)) break;
if (!planner.buffer_line(raw, fr_mm_s, active_extruder, cartesian_segment_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration))) break;
}
// Since segment_distance is only approximate,
// the final move must be to the exact destination.
planner.buffer_line(destination, fr_mm_s, active_extruder, cartesian_segment_mm
#if ENABLED(SCARA_FEEDRATE_SCALING)
, inv_duration
#endif
);
planner.buffer_line(destination, fr_mm_s, active_extruder, cartesian_segment_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration));
}
#endif // SEGMENT_LEVELED_MOVES
@ -998,7 +1075,7 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
}
#endif // HAS_MESH
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder);
planner.buffer_line(destination, scaled_fr_mm_s);
return false; // caller will update current_position
}
@ -1080,12 +1157,12 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
// Un-park the active extruder
//
const feedRate_t fr_zfast = planner.settings.max_feedrate_mm_s[Z_AXIS];
#define CURPOS current_position
#define RAISED raised_parked_position
// 1. Move to the raised parked XYZ. Presumably the tool is already at XY.
if (planner.buffer_line(RAISED.x, RAISED.y, RAISED.z, CURPOS.e, fr_zfast, active_extruder)) {
xyze_pos_t raised = raised_parked_position; raised.e = current_position.e;
if (planner.buffer_line(raised, fr_zfast)) {
// 2. Move to the current native XY and raised Z. Presumably this is a null move.
if (planner.buffer_line(CURPOS.x, CURPOS.y, RAISED.z, CURPOS.e, PLANNER_XY_FEEDRATE(), active_extruder)) {
xyze_pos_t curpos = current_position; curpos.z = raised_parked_position.z;
if (planner.buffer_line(curpos, PLANNER_XY_FEEDRATE())) {
// 3. Lower Z back down
line_to_current_position(fr_zfast);
}
@ -1099,21 +1176,24 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) {
case DXC_MIRRORED_MODE:
case DXC_DUPLICATION_MODE:
if (active_extruder == 0) {
xyze_pos_t new_pos = current_position;
// Restore planner to parked head (T1) X position
xyze_pos_t pos_now = current_position;
pos_now.x = inactive_extruder_x;
planner.set_position_mm(pos_now);
// Keep the same X or add the duplication X offset
xyze_pos_t new_pos = pos_now;
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE)
new_pos.x += duplicate_extruder_x_offset;
else
new_pos.x = inactive_extruder_x;
// Move duplicate extruder into correct duplication position.
// Move duplicate extruder into the correct position
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Set planner X", inactive_extruder_x, " ... Line to X", new_pos.x);
planner.set_position_mm(inactive_extruder_x, current_position.y, current_position.z, current_position.e);
if (!planner.buffer_line(new_pos, planner.settings.max_feedrate_mm_s[X_AXIS], 1)) break;
planner.synchronize();
sync_plan_position();
set_duplication_enabled(true);
idex_set_parked(false);
sync_plan_position(); // Extra sync for good measure
set_duplication_enabled(true); // Enable Duplication
idex_set_parked(false); // No longer parked
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("set_duplication_enabled(true)\nidex_set_parked(false)");
}
else if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Active extruder not 0");
@ -1207,22 +1287,24 @@ void prepare_line_to_destination() {
};
// Clear test bits that are trusted
LINEAR_AXIS_CODE(
set_should(axis_bits, X_AXIS),
set_should(axis_bits, Y_AXIS),
set_should(axis_bits, Z_AXIS)
set_should(axis_bits, X_AXIS), set_should(axis_bits, Y_AXIS), set_should(axis_bits, Z_AXIS),
set_should(axis_bits, I_AXIS), set_should(axis_bits, J_AXIS), set_should(axis_bits, K_AXIS)
);
return axis_bits;
}
bool homing_needed_error(linear_axis_bits_t axis_bits/*=linear_bits*/) {
if ((axis_bits = axes_should_home(axis_bits))) {
PGM_P home_first = GET_TEXT(MSG_HOME_FIRST);
PGM_P home_first = GET_TEXT(MSG_HOME_FIRST); // TODO: (DerAndere) Set this up for extra axes
char msg[strlen_P(home_first)+1];
sprintf_P(msg, home_first,
LINEAR_AXIS_LIST(
TEST(axis_bits, X_AXIS) ? "X" : "",
TEST(axis_bits, Y_AXIS) ? "Y" : "",
TEST(axis_bits, Z_AXIS) ? "Z" : ""
TEST(axis_bits, Z_AXIS) ? "Z" : "",
TEST(axis_bits, I_AXIS) ? AXIS4_STR : "",
TEST(axis_bits, J_AXIS) ? AXIS5_STR : "",
TEST(axis_bits, K_AXIS) ? AXIS6_STR : ""
)
);
SERIAL_ECHO_START();
@ -1374,6 +1456,9 @@ void prepare_line_to_destination() {
case X_AXIS: if (ENABLED(X_SPI_SENSORLESS)) endstops.tmc_spi_homing.x = false; break;
case Y_AXIS: if (ENABLED(Y_SPI_SENSORLESS)) endstops.tmc_spi_homing.y = false; break;
case Z_AXIS: if (ENABLED(Z_SPI_SENSORLESS)) endstops.tmc_spi_homing.z = false; break;
case I_AXIS: if (ENABLED(I_SPI_SENSORLESS)) endstops.tmc_spi_homing.i = false; break;
case J_AXIS: if (ENABLED(J_SPI_SENSORLESS)) endstops.tmc_spi_homing.j = false; break;
case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = false; break;
default: break;
}
#endif
@ -1446,12 +1531,7 @@ void prepare_line_to_destination() {
// Set delta/cartesian axes directly
target[axis] = distance; // The move will be towards the endstop
planner.buffer_segment(target
#if HAS_DIST_MM_ARG
, cart_dist_mm
#endif
, home_fr_mm_s, active_extruder
);
planner.buffer_segment(target OPTARG(HAS_DIST_MM_ARG, cart_dist_mm), home_fr_mm_s, active_extruder);
#endif
planner.synchronize();
@ -1531,6 +1611,30 @@ void prepare_line_to_destination() {
stepperBackoutDir = INVERT_Z_DIR ? effectorBackoutDir : -effectorBackoutDir;
break;
#endif
#ifdef I_MICROSTEPS
case I_AXIS:
phasePerUStep = PHASE_PER_MICROSTEP(I);
phaseCurrent = stepperI.get_microstep_counter();
effectorBackoutDir = -I_HOME_DIR;
stepperBackoutDir = INVERT_I_DIR ? effectorBackoutDir : -effectorBackoutDir;
break;
#endif
#ifdef J_MICROSTEPS
case J_AXIS:
phasePerUStep = PHASE_PER_MICROSTEP(J);
phaseCurrent = stepperJ.get_microstep_counter();
effectorBackoutDir = -J_HOME_DIR;
stepperBackoutDir = INVERT_J_DIR ? effectorBackoutDir : -effectorBackoutDir;
break;
#endif
#ifdef K_MICROSTEPS
case K_AXIS:
phasePerUStep = PHASE_PER_MICROSTEP(K);
phaseCurrent = stepperK.get_microstep_counter();
effectorBackoutDir = -K_HOME_DIR;
stepperBackoutDir = INVERT_K_DIR ? effectorBackoutDir : -effectorBackoutDir;
break;
#endif
default: return;
}
@ -1583,11 +1687,18 @@ void prepare_line_to_destination() {
#else
#define _CAN_HOME(A) (axis == _AXIS(A) && ( \
ENABLED(A##_SPI_SENSORLESS) \
|| (_AXIS(A) == Z_AXIS && ENABLED(HOMING_Z_WITH_PROBE)) \
|| TERN0(HAS_Z_AXIS, TERN0(HOMING_Z_WITH_PROBE, _AXIS(A) == Z_AXIS)) \
|| TERN0(A##_HOME_TO_MIN, A##_MIN_PIN > -1) \
|| TERN0(A##_HOME_TO_MAX, A##_MAX_PIN > -1) \
))
if (!_CAN_HOME(X) && !_CAN_HOME(Y) && !_CAN_HOME(Z)) return;
if (LINEAR_AXIS_GANG(
!_CAN_HOME(X),
&& !_CAN_HOME(Y),
&& !_CAN_HOME(Z),
&& !_CAN_HOME(I),
&& !_CAN_HOME(J),
&& !_CAN_HOME(K))
) return;
#endif
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> homeaxis(", AS_CHAR(AXIS_CHAR(axis)), ")");
@ -1636,9 +1747,9 @@ void prepare_line_to_destination() {
// Determine if a homing bump will be done and the bumps distance
// When homing Z with probe respect probe clearance
const bool use_probe_bump = TERN0(HOMING_Z_WITH_PROBE, axis == Z_AXIS && home_bump_mm(Z_AXIS));
const bool use_probe_bump = TERN0(HOMING_Z_WITH_PROBE, axis == Z_AXIS && home_bump_mm(axis));
const float bump = axis_home_dir * (
use_probe_bump ? _MAX(TERN0(HOMING_Z_WITH_PROBE, Z_CLEARANCE_BETWEEN_PROBES), home_bump_mm(Z_AXIS)) : home_bump_mm(axis)
use_probe_bump ? _MAX(TERN0(HOMING_Z_WITH_PROBE, Z_CLEARANCE_BETWEEN_PROBES), home_bump_mm(axis)) : home_bump_mm(axis)
);
//

View File

@ -44,7 +44,7 @@ extern xyze_pos_t current_position, // High-level current tool position
// G60/G61 Position Save and Return
#if SAVED_POSITIONS
extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3];
extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for LINEAR_AXES >= 4
extern xyze_pos_t stored_position[SAVED_POSITIONS];
#endif
@ -53,7 +53,7 @@ extern xyz_pos_t cartes;
// Until kinematics.cpp is created, declare this here
#if IS_KINEMATIC
extern abc_pos_t delta;
extern abce_pos_t delta;
#endif
#if HAS_ABL_NOT_UBL
@ -75,16 +75,16 @@ extern xyz_pos_t cartes;
*/
constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M;
FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) {
float v;
#if ENABLED(DELTA)
v = homing_feedrate_mm_m.z;
#else
switch (a) {
case X_AXIS: v = homing_feedrate_mm_m.x; break;
case Y_AXIS: v = homing_feedrate_mm_m.y; break;
case Z_AXIS:
default: v = homing_feedrate_mm_m.z;
}
float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z);
#if DISABLED(DELTA)
LINEAR_AXIS_CODE(
if (a == X_AXIS) v = homing_feedrate_mm_m.x,
else if (a == Y_AXIS) v = homing_feedrate_mm_m.y,
else if (a == Z_AXIS) v = homing_feedrate_mm_m.z,
else if (a == I_AXIS) v = homing_feedrate_mm_m.i,
else if (a == J_AXIS) v = homing_feedrate_mm_m.j,
else if (a == K_AXIS) v = homing_feedrate_mm_m.k
);
#endif
return MMM_TO_MMS(v);
}
@ -124,7 +124,7 @@ inline int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm
#define XYZ_DEFS(T, NAME, OPT) \
inline T NAME(const AxisEnum axis) { \
static const XYZval<T> NAME##_P DEFS_PROGMEM = LINEAR_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT); \
static const XYZval<T> NAME##_P DEFS_PROGMEM = LINEAR_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT); \
return pgm_read_any(&NAME##_P[axis]); \
}
XYZ_DEFS(float, base_min_pos, MIN_POS);
@ -168,13 +168,36 @@ inline float home_bump_mm(const AxisEnum axis) {
TERN_(MIN_SOFTWARE_ENDSTOP_X, amin = min.x);
TERN_(MAX_SOFTWARE_ENDSTOP_X, amax = max.x);
break;
case Y_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_Y, amin = min.y);
TERN_(MAX_SOFTWARE_ENDSTOP_Y, amax = max.y);
break;
case Z_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_Z, amin = min.z);
TERN_(MAX_SOFTWARE_ENDSTOP_Z, amax = max.z);
#if HAS_Y_AXIS
case Y_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_Y, amin = min.y);
TERN_(MAX_SOFTWARE_ENDSTOP_Y, amax = max.y);
break;
#endif
#if HAS_Z_AXIS
case Z_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_Z, amin = min.z);
TERN_(MAX_SOFTWARE_ENDSTOP_Z, amax = max.z);
break;
#endif
#if LINEAR_AXES >= 4 // TODO (DerAndere): Test for LINEAR_AXES >= 4
case I_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_I, amin = min.i);
TERN_(MIN_SOFTWARE_ENDSTOP_I, amax = max.i);
break;
#endif
#if LINEAR_AXES >= 5
case J_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_J, amin = min.j);
TERN_(MIN_SOFTWARE_ENDSTOP_J, amax = max.j);
break;
#endif
#if LINEAR_AXES >= 6
case K_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_K, amin = min.k);
TERN_(MIN_SOFTWARE_ENDSTOP_K, amax = max.k);
break;
#endif
default: break;
}
#endif
@ -298,32 +321,53 @@ inline void prepare_internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f)
/**
* Blocking movement and shorthand functions
*/
void do_blocking_move_to(
LINEAR_AXIS_LIST(const float rx, const float ry, const float rz),
const_feedRate_t fr_mm_s=0.0f
);
void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s=0.0f);
#if HAS_Y_AXIS
void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
#endif
#if HAS_Z_AXIS
void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s=0.0f);
#endif
#if LINEAR_AXES >= 4
void do_blocking_move_to_i(const_float_t ri, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s=0.0f);
#endif
#if LINEAR_AXES >= 5
void do_blocking_move_to_j(const_float_t rj, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_xyzi_j(const xyze_pos_t &raw, const_float_t j, const_feedRate_t fr_mm_s=0.0f);
#endif
#if LINEAR_AXES >= 6
void do_blocking_move_to_k(const_float_t rk, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s=0.0f);
#endif
void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
FORCE_INLINE void do_blocking_move_to_xy(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
FORCE_INLINE void do_blocking_move_to_xy(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
#if HAS_Y_AXIS
void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
FORCE_INLINE void do_blocking_move_to_xy(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
FORCE_INLINE void do_blocking_move_to_xy(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy(xy_pos_t(raw), fr_mm_s); }
#endif
void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f);
FORCE_INLINE void do_blocking_move_to_xy_z(const xyz_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
FORCE_INLINE void do_blocking_move_to_xy_z(const xyze_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
#if HAS_Z_AXIS
void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f);
FORCE_INLINE void do_blocking_move_to_xy_z(const xyz_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
FORCE_INLINE void do_blocking_move_to_xy_z(const xyze_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s=0.0f) { do_blocking_move_to_xy_z(xy_pos_t(raw), z, fr_mm_s); }
#endif
void remember_feedrate_and_scaling();
void remember_feedrate_scaling_off();
void restore_feedrate_and_scaling();
void do_z_clearance(const_float_t zclear, const bool lower_allowed=false);
#if HAS_Z_AXIS
void do_z_clearance(const_float_t zclear, const bool lower_allowed=false);
#else
inline void do_z_clearance(float, bool=false) {}
#endif
/**
* Homing and Trusted Axes
@ -421,11 +465,27 @@ FORCE_INLINE bool all_axes_trusted() { return linear_bits
FORCE_INLINE void toNative(xyze_pos_t&) {}
#endif
#define LOGICAL_X_POSITION(POS) NATIVE_TO_LOGICAL(POS, X_AXIS)
#define LOGICAL_Y_POSITION(POS) NATIVE_TO_LOGICAL(POS, Y_AXIS)
#define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
#define RAW_X_POSITION(POS) LOGICAL_TO_NATIVE(POS, X_AXIS)
#define RAW_Y_POSITION(POS) LOGICAL_TO_NATIVE(POS, Y_AXIS)
#define RAW_Z_POSITION(POS) LOGICAL_TO_NATIVE(POS, Z_AXIS)
#if HAS_Y_AXIS
#define LOGICAL_Y_POSITION(POS) NATIVE_TO_LOGICAL(POS, Y_AXIS)
#define RAW_Y_POSITION(POS) LOGICAL_TO_NATIVE(POS, Y_AXIS)
#endif
#if HAS_Z_AXIS
#define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
#define RAW_Z_POSITION(POS) LOGICAL_TO_NATIVE(POS, Z_AXIS)
#endif
#if LINEAR_AXES >= 4
#define LOGICAL_I_POSITION(POS) NATIVE_TO_LOGICAL(POS, I_AXIS)
#define RAW_I_POSITION(POS) LOGICAL_TO_NATIVE(POS, I_AXIS)
#endif
#if LINEAR_AXES >= 5
#define LOGICAL_J_POSITION(POS) NATIVE_TO_LOGICAL(POS, J_AXIS)
#define RAW_J_POSITION(POS) LOGICAL_TO_NATIVE(POS, J_AXIS)
#endif
#if LINEAR_AXES >= 6
#define LOGICAL_K_POSITION(POS) NATIVE_TO_LOGICAL(POS, K_AXIS)
#define RAW_K_POSITION(POS) LOGICAL_TO_NATIVE(POS, K_AXIS)
#endif
/**
* position_is_reachable family of functions

View File

@ -1310,7 +1310,7 @@ void Planner::recalculate() {
*/
void Planner::check_axes_activity() {
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_E)
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z , DISABLE_I , DISABLE_J , DISABLE_K, DISABLE_E)
xyze_bool_t axis_active = { false };
#endif
@ -1342,14 +1342,17 @@ void Planner::check_axes_activity() {
TERN_(HAS_HEATER_2, tail_e_to_p_pressure = block->e_to_p_pressure);
#endif
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_E)
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_E)
for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
block_t *block = &block_buffer[b];
LOGICAL_AXIS_CODE(
if (TERN0(DISABLE_E, block->steps.e)) axis_active.e = true,
if (TERN0(DISABLE_X, block->steps.x)) axis_active.x = true,
if (TERN0(DISABLE_Y, block->steps.y)) axis_active.y = true,
if (TERN0(DISABLE_Z, block->steps.z)) axis_active.z = true
if (TERN0(DISABLE_Z, block->steps.z)) axis_active.z = true,
if (TERN0(DISABLE_I, block->steps.i)) axis_active.i = true,
if (TERN0(DISABLE_J, block->steps.j)) axis_active.j = true,
if (TERN0(DISABLE_K, block->steps.k)) axis_active.k = true
);
}
#endif
@ -1375,7 +1378,10 @@ void Planner::check_axes_activity() {
if (TERN0(DISABLE_E, !axis_active.e)) disable_e_steppers(),
if (TERN0(DISABLE_X, !axis_active.x)) DISABLE_AXIS_X(),
if (TERN0(DISABLE_Y, !axis_active.y)) DISABLE_AXIS_Y(),
if (TERN0(DISABLE_Z, !axis_active.z)) DISABLE_AXIS_Z()
if (TERN0(DISABLE_Z, !axis_active.z)) DISABLE_AXIS_Z(),
if (TERN0(DISABLE_I, !axis_active.i)) DISABLE_AXIS_I(),
if (TERN0(DISABLE_J, !axis_active.j)) DISABLE_AXIS_J(),
if (TERN0(DISABLE_K, !axis_active.k)) DISABLE_AXIS_K()
);
//
@ -1445,7 +1451,7 @@ void Planner::check_axes_activity() {
float high = 0.0;
for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
block_t *block = &block_buffer[b];
if (block->steps.x || block->steps.y || block->steps.z) {
if (LINEAR_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, block->steps.i, || block->steps.j, || block->steps.k)) {
const float se = (float)block->steps.e / block->step_event_count * SQRT(block->nominal_speed_sqr); // mm/sec;
NOLESS(high, se);
}
@ -1831,7 +1837,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
de = target.e - position.e,
da = target.a - position.a,
db = target.b - position.b,
dc = target.c - position.c
dc = target.c - position.c,
di = target.i - position.i,
dj = target.j - position.j,
dk = target.k - position.k
);
/* <-- add a slash to enable
@ -1910,7 +1919,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
LINEAR_AXIS_CODE(
if (da < 0) SBI(dm, X_AXIS),
if (db < 0) SBI(dm, Y_AXIS),
if (dc < 0) SBI(dm, Z_AXIS)
if (dc < 0) SBI(dm, Z_AXIS),
if (di < 0) SBI(dm, I_AXIS),
if (dj < 0) SBI(dm, J_AXIS),
if (dk < 0) SBI(dm, K_AXIS)
);
#endif
#if HAS_EXTRUDERS
@ -1951,7 +1963,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
block->steps.set(ABS(da), ABS(db), ABS(dc));
#else
// default non-h-bot planning
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc)));
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#endif
/**
@ -1997,7 +2009,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
LINEAR_AXIS_CODE(
steps_dist_mm.a = da * steps_to_mm[A_AXIS],
steps_dist_mm.b = db * steps_to_mm[B_AXIS],
steps_dist_mm.c = dc * steps_to_mm[C_AXIS]
steps_dist_mm.c = dc * steps_to_mm[C_AXIS],
steps_dist_mm.i = di * steps_to_mm[I_AXIS],
steps_dist_mm.j = dj * steps_to_mm[J_AXIS],
steps_dist_mm.k = dk * steps_to_mm[K_AXIS]
);
#endif
@ -2010,7 +2025,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
if (true LINEAR_AXIS_GANG(
&& block->steps.a < MIN_STEPS_PER_SEGMENT,
&& block->steps.b < MIN_STEPS_PER_SEGMENT,
&& block->steps.c < MIN_STEPS_PER_SEGMENT
&& block->steps.c < MIN_STEPS_PER_SEGMENT,
&& block->steps.i < MIN_STEPS_PER_SEGMENT,
&& block->steps.j < MIN_STEPS_PER_SEGMENT,
&& block->steps.k < MIN_STEPS_PER_SEGMENT
)
) {
block->millimeters = TERN0(HAS_EXTRUDERS, ABS(steps_dist_mm.e));
@ -2022,19 +2040,30 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
block->millimeters = SQRT(
#if EITHER(CORE_IS_XY, MARKFORGED_XY)
LINEAR_AXIS_GANG(
sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z)
sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z),
+ sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k)
)
#elif CORE_IS_XZ
LINEAR_AXIS_GANG(
sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z)
sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z),
+ sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k)
)
#elif CORE_IS_YZ
LINEAR_AXIS_GANG(
sq(steps_dist_mm.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.head.z)
sq(steps_dist_mm.x) + sq(steps_dist_mm.head.y) + sq(steps_dist_mm.head.z)
+ sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k)
)
#elif ENABLED(FOAMCUTTER_XYUV)
// Return the largest distance move from either X/Y or I/J plane
#if LINEAR_AXES >= 5
_MAX(sq(steps_dist_mm.x) + sq(steps_dist_mm.y), sq(steps_dist_mm.i) + sq(steps_dist_mm.j))
#else
sq(steps_dist_mm.x) + sq(steps_dist_mm.y)
#endif
#else
LINEAR_AXIS_GANG(
sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z)
sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z),
+ sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k)
)
#endif
);
@ -2055,7 +2084,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
TERN_(HAS_EXTRUDERS, block->steps.e = esteps);
block->step_event_count = _MAX(LOGICAL_AXIS_LIST(
esteps, block->steps.a, block->steps.b, block->steps.c
esteps, block->steps.a, block->steps.b, block->steps.c, block->steps.i, block->steps.j, block->steps.k
));
// Bail if this is a zero-length block
@ -2082,7 +2111,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
if (LINEAR_AXIS_GANG(
block->steps.x,
|| block->steps.y,
|| block->steps.z
|| block->steps.z,
|| block->steps.i,
|| block->steps.j,
|| block->steps.k
)) powerManager.power_on();
#endif
@ -2111,7 +2143,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
LINEAR_AXIS_CODE(
if (block->steps.x) ENABLE_AXIS_X(),
if (block->steps.y) ENABLE_AXIS_Y(),
if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) ENABLE_AXIS_Z()
if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) ENABLE_AXIS_Z(),
if (block->steps.i) ENABLE_AXIS_I(),
if (block->steps.j) ENABLE_AXIS_J(),
if (block->steps.k) ENABLE_AXIS_K()
);
#endif
@ -2301,8 +2336,9 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
const float steps_per_mm = block->step_event_count * inverse_millimeters;
uint32_t accel;
if (LINEAR_AXIS_GANG(
!block->steps.a, && !block->steps.b, && !block->steps.c
)) { // Is this a retract / recover move?
!block->steps.a, && !block->steps.b, && !block->steps.c,
&& !block->steps.i, && !block->steps.j, && !block->steps.k)
) { // Is this a retract / recover move?
accel = CEIL(settings.retract_acceleration * steps_per_mm); // Convert to: acceleration steps/sec^2
TERN_(LIN_ADVANCE, block->use_advance_lead = false); // No linear advance for simple retract/recover
}
@ -2371,7 +2407,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
LIMIT_ACCEL_LONG(E_AXIS, E_INDEX_N(extruder)),
LIMIT_ACCEL_LONG(A_AXIS, 0),
LIMIT_ACCEL_LONG(B_AXIS, 0),
LIMIT_ACCEL_LONG(C_AXIS, 0)
LIMIT_ACCEL_LONG(C_AXIS, 0),
LIMIT_ACCEL_LONG(I_AXIS, 0),
LIMIT_ACCEL_LONG(J_AXIS, 0),
LIMIT_ACCEL_LONG(K_AXIS, 0)
);
}
else {
@ -2379,7 +2418,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
LIMIT_ACCEL_FLOAT(E_AXIS, E_INDEX_N(extruder)),
LIMIT_ACCEL_FLOAT(A_AXIS, 0),
LIMIT_ACCEL_FLOAT(B_AXIS, 0),
LIMIT_ACCEL_FLOAT(C_AXIS, 0)
LIMIT_ACCEL_FLOAT(C_AXIS, 0),
LIMIT_ACCEL_FLOAT(I_AXIS, 0),
LIMIT_ACCEL_FLOAT(J_AXIS, 0),
LIMIT_ACCEL_FLOAT(K_AXIS, 0)
);
}
}
@ -2444,7 +2486,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#if HAS_DIST_MM_ARG
cart_dist_mm
#else
LOGICAL_AXIS_ARRAY(steps_dist_mm.e, steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z)
LOGICAL_AXIS_ARRAY(steps_dist_mm.e, steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z, steps_dist_mm.i, steps_dist_mm.j, steps_dist_mm.k)
#endif
;
@ -2467,7 +2509,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
+ (-prev_unit_vec.e * unit_vec.e),
(-prev_unit_vec.x * unit_vec.x),
+ (-prev_unit_vec.y * unit_vec.y),
+ (-prev_unit_vec.z * unit_vec.z)
+ (-prev_unit_vec.z * unit_vec.z),
+ (-prev_unit_vec.i * unit_vec.i),
+ (-prev_unit_vec.j * unit_vec.j),
+ (-prev_unit_vec.k * unit_vec.k)
);
// NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
@ -2783,10 +2828,9 @@ void Planner::buffer_sync_block(TERN_(LASER_SYNCHRONOUS_M106_M107, uint8_t sync_
*
* Return 'false' if no segment was queued due to cleaning, cold extrusion, full queue, etc.
*/
bool Planner::buffer_segment(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
bool Planner::buffer_segment(const abce_pos_t &abce
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
, const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters/*=0.0*/
, const_feedRate_t fr_mm_s, const uint8_t extruder/*=active_extruder*/, const_float_t millimeters/*=0.0*/
) {
// If we are cleaning, do not accept queuing of movements
@ -2804,54 +2848,70 @@ bool Planner::buffer_segment(
// Calculate target position in absolute steps
const abce_long_t target = {
LOGICAL_AXIS_LIST(
int32_t(LROUND(e * settings.axis_steps_per_mm[E_AXIS_N(extruder)])),
int32_t(LROUND(a * settings.axis_steps_per_mm[A_AXIS])),
int32_t(LROUND(b * settings.axis_steps_per_mm[B_AXIS])),
int32_t(LROUND(c * settings.axis_steps_per_mm[C_AXIS]))
int32_t(LROUND(abce.e * settings.axis_steps_per_mm[E_AXIS_N(extruder)])),
int32_t(LROUND(abce.a * settings.axis_steps_per_mm[A_AXIS])),
int32_t(LROUND(abce.b * settings.axis_steps_per_mm[B_AXIS])),
int32_t(LROUND(abce.c * settings.axis_steps_per_mm[C_AXIS])),
int32_t(LROUND(abce.i * settings.axis_steps_per_mm[I_AXIS])), // FIXME (DerAndere): Multiplication by 4.0 is a work-around for issue with wrong internal steps per mm
int32_t(LROUND(abce.j * settings.axis_steps_per_mm[J_AXIS])),
int32_t(LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS]))
)
};
#if HAS_POSITION_FLOAT
const xyze_pos_t target_float = LOGICAL_AXIS_ARRAY(e, a, b, c);
const xyze_pos_t target_float = abce;
#endif
#if HAS_EXTRUDERS
// DRYRUN prevents E moves from taking place
if (DEBUGGING(DRYRUN) || TERN0(CANCEL_OBJECTS, cancelable.skipping)) {
position.e = target.e;
TERN_(HAS_POSITION_FLOAT, position_float.e = e);
TERN_(HAS_POSITION_FLOAT, position_float.e = abce.e);
}
#endif
/* <-- add a slash to enable
SERIAL_ECHOPAIR(" buffer_segment FR:", fr_mm_s);
#if IS_KINEMATIC
SERIAL_ECHOPAIR(" A:", a);
SERIAL_ECHOPAIR(" (", position.a);
SERIAL_ECHOPAIR("->", target.a);
SERIAL_ECHOPAIR(") B:", b);
SERIAL_ECHOPAIR(" A:", abce.a, " (", position.a, "->", target.a, ") B:", abce.b);
#else
SERIAL_ECHOPAIR_P(SP_X_LBL, a);
SERIAL_ECHOPAIR(" (", position.x);
SERIAL_ECHOPAIR("->", target.x);
SERIAL_ECHOPAIR_P(SP_X_LBL, abce.a);
SERIAL_ECHOPAIR(" (", position.x, "->", target.x);
SERIAL_CHAR(')');
SERIAL_ECHOPAIR_P(SP_Y_LBL, b);
SERIAL_ECHOPAIR_P(SP_Y_LBL, abce.b);
#endif
SERIAL_ECHOPAIR(" (", position.y);
SERIAL_ECHOPAIR("->", target.y);
#if ENABLED(DELTA)
SERIAL_ECHOPAIR(") C:", c);
SERIAL_ECHOPAIR(" (", position.y, "->", target.y);
#if LINEAR_AXES >= ABC
#if ENABLED(DELTA)
SERIAL_ECHOPAIR(") C:", abce.c);
#else
SERIAL_CHAR(')');
SERIAL_ECHOPAIR_P(SP_Z_LBL, abce.c);
#endif
SERIAL_ECHOPAIR(" (", position.z, "->", target.z);
SERIAL_CHAR(')');
#endif
#if LINEAR_AXES >= 4
SERIAL_ECHOPAIR_P(SP_I_LBL, abce.i);
SERIAL_ECHOPAIR(" (", position.i, "->", target.i); // FIXME (DerAndere): Introduce work-around for issue with wrong internal steps per mm and feedrate for I_AXIS
SERIAL_CHAR(')');
#endif
#if LINEAR_AXES >= 5
SERIAL_ECHOPAIR_P(SP_J_LBL, abce.j);
SERIAL_ECHOPAIR(" (", position.j, "->", target.j);
SERIAL_CHAR(')');
#endif
#if LINEAR_AXES >= 6
SERIAL_ECHOPAIR_P(SP_K_LBL, abce.k);
SERIAL_ECHOPAIR(" (", position.k, "->", target.k);
SERIAL_CHAR(')');
#endif
#if HAS_EXTRUDERS
SERIAL_ECHOPAIR_P(SP_E_LBL, abce.e);
SERIAL_ECHOLNPAIR(" (", position.e, "->", target.e, ")");
#else
SERIAL_CHAR(')');
SERIAL_ECHOPAIR_P(SP_Z_LBL, c);
SERIAL_EOL();
#endif
SERIAL_ECHOPAIR(" (", position.z);
SERIAL_ECHOPAIR("->", target.z);
SERIAL_CHAR(')');
SERIAL_ECHOPAIR_P(SP_E_LBL, e);
SERIAL_ECHOPAIR(" (", position.e);
SERIAL_ECHOPAIR("->", target.e);
SERIAL_ECHOLNPGM(")");
//*/
// Queue the movement. Return 'false' if the move was not queued.
@ -2874,34 +2934,34 @@ bool Planner::buffer_segment(
* The target is cartesian. It's translated to
* delta/scara if needed.
*
* rx,ry,rz,e - target position in mm or degrees
* fr_mm_s - (target) speed of the move (mm/s)
* extruder - target extruder
* millimeters - the length of the movement, if known
* inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
* cart - target position in mm or degrees
* fr_mm_s - (target) speed of the move (mm/s)
* extruder - target extruder
* millimeters - the length of the movement, if known
* inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
*/
bool Planner::buffer_line(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters
OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration)
bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, const uint8_t extruder/*=active_extruder*/, const float millimeters/*=0.0*/
OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration/*=0.0*/)
) {
xyze_pos_t machine = LOGICAL_AXIS_ARRAY(e, rx, ry, rz);
xyze_pos_t machine = cart;
TERN_(HAS_POSITION_MODIFIERS, apply_modifiers(machine));
#if IS_KINEMATIC
#if HAS_JUNCTION_DEVIATION
const xyze_pos_t cart_dist_mm = {
rx - position_cart.x, ry - position_cart.y,
rz - position_cart.z, e - position_cart.e
};
const xyze_pos_t cart_dist_mm = LOGICAL_AXIS_ARRAY(
cart.e - position_cart.e,
cart.x - position_cart.x, cart.y - position_cart.y, cart.z - position_cart.z,
cart.i - position_cart.i, cart.j - position_cart.j, cart.j - position_cart.k
);
#else
const xyz_pos_t cart_dist_mm = { rx - position_cart.x, ry - position_cart.y, rz - position_cart.z };
const xyz_pos_t cart_dist_mm = LINEAR_AXIS_ARRAY(
cart.x - position_cart.x, cart.y - position_cart.y, cart.z - position_cart.z,
cart.i - position_cart.i, cart.j - position_cart.j, cart.j - position_cart.k
);
#endif
float mm = millimeters;
if (mm == 0.0)
mm = (cart_dist_mm.x != 0.0 || cart_dist_mm.y != 0.0) ? cart_dist_mm.magnitude() : ABS(cart_dist_mm.z);
const float mm = millimeters ?: (cart_dist_mm.x || cart_dist_mm.y) ? cart_dist_mm.magnitude() : TERN0(HAS_Z_AXIS, ABS(cart_dist_mm.z));
// Cartesian XYZ to kinematic ABC, stored in global 'delta'
inverse_kinematics(machine);
@ -2915,17 +2975,12 @@ bool Planner::buffer_line(
#else
const feedRate_t feedrate = fr_mm_s;
#endif
if (buffer_segment(delta.a, delta.b, delta.c, machine.e
#if HAS_JUNCTION_DEVIATION
, cart_dist_mm
#endif
, feedrate, extruder, mm
)) {
position_cart.set(rx, ry, rz, e);
delta.e = machine.e;
if (buffer_segment(delta OPTARG(HAS_DIST_MM_ARG, cart_dist_mm), feedrate, extruder, mm)) {
position_cart = cart;
return true;
}
else
return false;
return false;
#else
return buffer_segment(machine, fr_mm_s, extruder, millimeters);
#endif
@ -2991,23 +3046,23 @@ bool Planner::buffer_line(
#endif // DIRECT_STEPPING
/**
* Directly set the planner ABC position (and stepper positions)
* Directly set the planner ABCE position (and stepper positions)
* converting mm (or angles for SCARA) into steps.
*
* The provided ABC position is in machine units.
* The provided ABCE position is in machine units.
*/
void Planner::set_machine_position_mm(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
) {
void Planner::set_machine_position_mm(const abce_pos_t &abce) {
TERN_(DISTINCT_E_FACTORS, last_extruder = active_extruder);
TERN_(HAS_POSITION_FLOAT, position_float.set(LOGICAL_AXIS_LIST(e, a, b, c)));
TERN_(HAS_POSITION_FLOAT, position_float = abce);
position.set(
LOGICAL_AXIS_LIST(
LROUND(e * settings.axis_steps_per_mm[E_AXIS_N(active_extruder)]),
LROUND(a * settings.axis_steps_per_mm[A_AXIS]),
LROUND(b * settings.axis_steps_per_mm[B_AXIS]),
LROUND(c * settings.axis_steps_per_mm[C_AXIS])
LROUND(abce.e * settings.axis_steps_per_mm[E_AXIS_N(active_extruder)]),
LROUND(abce.a * settings.axis_steps_per_mm[A_AXIS]),
LROUND(abce.b * settings.axis_steps_per_mm[B_AXIS]),
LROUND(abce.c * settings.axis_steps_per_mm[C_AXIS]),
LROUND(abce.i * settings.axis_steps_per_mm[I_AXIS]),
LROUND(abce.j * settings.axis_steps_per_mm[J_AXIS]),
LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])
)
);
if (has_blocks_queued()) {
@ -3019,15 +3074,14 @@ void Planner::set_machine_position_mm(
stepper.set_position(position);
}
void Planner::set_position_mm(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
) {
xyze_pos_t machine = LOGICAL_AXIS_ARRAY(e, rx, ry, rz);
void Planner::set_position_mm(const xyze_pos_t &xyze) {
xyze_pos_t machine = xyze;
TERN_(HAS_POSITION_MODIFIERS, apply_modifiers(machine, true));
#if IS_KINEMATIC
position_cart.set(rx, ry, rz, e);
position_cart = xyze;
inverse_kinematics(machine);
set_machine_position_mm(delta.a, delta.b, delta.c, machine.e);
delta.e = machine.e;
set_machine_position_mm(delta);
#else
set_machine_position_mm(machine);
#endif
@ -3045,7 +3099,7 @@ void Planner::set_position_mm(
const float e_new = DIFF_TERN(FWRETRACT, e, fwretract.current_retract[active_extruder]);
position.e = LROUND(settings.axis_steps_per_mm[axis_index] * e_new);
TERN_(HAS_POSITION_FLOAT, position_float.e = e_new);
TERN_(IS_KINEMATIC, position_cart.e = e);
TERN_(IS_KINEMATIC, TERN_(HAS_EXTRUDERS, position_cart.e = e));
if (has_blocks_queued())
buffer_sync_block();
@ -3057,15 +3111,11 @@ void Planner::set_position_mm(
// Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
void Planner::reset_acceleration_rates() {
#if ENABLED(DISTINCT_E_FACTORS)
#define AXIS_CONDITION (i < E_AXIS || i == E_AXIS_N(active_extruder))
#else
#define AXIS_CONDITION true
#endif
uint32_t highest_rate = 1;
LOOP_DISTINCT_AXES(i) {
max_acceleration_steps_per_s2[i] = settings.max_acceleration_mm_per_s2[i] * settings.axis_steps_per_mm[i];
if (AXIS_CONDITION) NOLESS(highest_rate, max_acceleration_steps_per_s2[i]);
if (TERN1(DISTINCT_E_FACTORS, i < E_AXIS || i == E_AXIS_N(active_extruder)))
NOLESS(highest_rate, max_acceleration_steps_per_s2[i]);
}
acceleration_long_cutoff = 4294967295UL / highest_rate; // 0xFFFFFFFFUL
TERN_(HAS_LINEAR_E_JERK, recalculate_max_e_jerk());

View File

@ -76,7 +76,9 @@
// Feedrate for manual moves
#ifdef MANUAL_FEEDRATE
constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE,
manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f, _mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f);
manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f,
_mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f,
_mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f);
#endif
#if IS_KINEMATIC && HAS_JUNCTION_DEVIATION
@ -758,23 +760,11 @@ class Planner {
* extruder - target extruder
* millimeters - the length of the movement, if known
*/
static bool buffer_segment(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
static bool buffer_segment(const abce_pos_t &abce
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
, const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
, const_feedRate_t fr_mm_s, const uint8_t extruder=active_extruder, const_float_t millimeters=0.0
);
FORCE_INLINE static bool buffer_segment(abce_pos_t &abce
OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
, const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
) {
return buffer_segment(
LOGICAL_AXIS_LIST(abce.e, abce.a, abce.b, abce.c)
OPTARG(HAS_DIST_MM_ARG, cart_dist_mm)
, fr_mm_s, extruder, millimeters
);
}
public:
/**
@ -782,28 +772,16 @@ class Planner {
* The target is cartesian. It's translated to
* delta/scara if needed.
*
* rx,ry,rz,e - target position in mm or degrees
* cart - target position in mm or degrees
* fr_mm_s - (target) speed of the move (mm/s)
* extruder - target extruder
* millimeters - the length of the movement, if known
* inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
*/
static bool buffer_line(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
, const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
static bool buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, const uint8_t extruder=active_extruder, const float millimeters=0.0
OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
);
FORCE_INLINE static bool buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, const uint8_t extruder, const float millimeters=0.0
OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
) {
return buffer_line(
LOGICAL_AXIS_LIST(cart.e, cart.x, cart.y, cart.z)
, fr_mm_s, extruder, millimeters
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
);
}
#if ENABLED(DIRECT_STEPPING)
static void buffer_page(const page_idx_t page_idx, const uint8_t extruder, const uint16_t num_steps);
#endif
@ -821,12 +799,7 @@ class Planner {
*
* Clears previous speed values.
*/
static void set_position_mm(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
);
FORCE_INLINE static void set_position_mm(const xyze_pos_t &cart) {
set_position_mm(LOGICAL_AXIS_LIST(cart.e, cart.x, cart.y, cart.z, cart.i, cart.j, cart.k));
}
static void set_position_mm(const xyze_pos_t &xyze);
#if HAS_EXTRUDERS
static void set_e_position_mm(const_float_t e);
@ -838,12 +811,7 @@ class Planner {
* The supplied position is in machine space, and no additional
* conversions are applied.
*/
static void set_machine_position_mm(
LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
);
FORCE_INLINE static void set_machine_position_mm(const abce_pos_t &abce) {
set_machine_position_mm(LOGICAL_AXIS_LIST(abce.e, abce.a, abce.b, abce.c));
}
static void set_machine_position_mm(const abce_pos_t &abce);
/**
* Get an axis position according to stepper position(s)
@ -854,7 +822,8 @@ class Planner {
static inline abce_pos_t get_axis_positions_mm() {
const abce_pos_t out = LOGICAL_AXIS_ARRAY(
get_axis_position_mm(E_AXIS),
get_axis_position_mm(A_AXIS), get_axis_position_mm(B_AXIS), get_axis_position_mm(C_AXIS)
get_axis_position_mm(A_AXIS), get_axis_position_mm(B_AXIS), get_axis_position_mm(C_AXIS),
get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS)
);
return out;
}

View File

@ -182,9 +182,13 @@ void cubic_b_spline(
// Compute and send new position
xyze_pos_t new_bez = LOGICAL_AXIS_ARRAY(
interp(position.e, target.e, t), // FIXME. These two are wrong, since the parameter t is not linear in the distance.
new_pos0, new_pos1,
interp(position.z, target.z, t)
interp(position.e, target.e, t), // FIXME. Wrong, since t is not linear in the distance.
new_pos0,
new_pos1,
interp(position.z, target.z, t), // FIXME. Wrong, since t is not linear in the distance.
interp(position.i, target.i, t), // FIXME. Wrong, since t is not linear in the distance.
interp(position.j, target.j, t), // FIXME. Wrong, since t is not linear in the distance.
interp(position.k, target.k, t) // FIXME. Wrong, since t is not linear in the distance.
);
apply_motion_limits(new_bez);
bez_target = new_bez;

View File

@ -110,7 +110,7 @@ public:
#else
static constexpr xyz_pos_t offset = xyz_pos_t({ 0, 0, 0 }); // See #16767
static constexpr xyz_pos_t offset = xyz_pos_t(LINEAR_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767
static bool set_deployed(const bool) { return false; }
@ -222,20 +222,20 @@ public:
#define VALIDATE_PROBE_PT(N) static_assert(Probe::build_time::can_reach(xy_pos_t{PROBE_PT_##N##_X, PROBE_PT_##N##_Y}), \
"PROBE_PT_" STRINGIFY(N) "_(X|Y) is unreachable using default NOZZLE_TO_PROBE_OFFSET and PROBING_MARGIN");
VALIDATE_PROBE_PT(1); VALIDATE_PROBE_PT(2); VALIDATE_PROBE_PT(3);
points[0].set(PROBE_PT_1_X, PROBE_PT_1_Y);
points[1].set(PROBE_PT_2_X, PROBE_PT_2_Y);
points[2].set(PROBE_PT_3_X, PROBE_PT_3_Y);
points[0] = xy_float_t({ PROBE_PT_1_X, PROBE_PT_1_Y });
points[1] = xy_float_t({ PROBE_PT_2_X, PROBE_PT_2_Y });
points[2] = xy_float_t({ PROBE_PT_3_X, PROBE_PT_3_Y });
#else
#if IS_KINEMATIC
constexpr float SIN0 = 0.0, SIN120 = 0.866025, SIN240 = -0.866025,
COS0 = 1.0, COS120 = -0.5 , COS240 = -0.5;
points[0].set((X_CENTER) + probe_radius() * COS0, (Y_CENTER) + probe_radius() * SIN0);
points[1].set((X_CENTER) + probe_radius() * COS120, (Y_CENTER) + probe_radius() * SIN120);
points[2].set((X_CENTER) + probe_radius() * COS240, (Y_CENTER) + probe_radius() * SIN240);
points[0] = xy_float_t({ (X_CENTER) + probe_radius() * COS0, (Y_CENTER) + probe_radius() * SIN0 });
points[1] = xy_float_t({ (X_CENTER) + probe_radius() * COS120, (Y_CENTER) + probe_radius() * SIN120 });
points[2] = xy_float_t({ (X_CENTER) + probe_radius() * COS240, (Y_CENTER) + probe_radius() * SIN240 });
#else
points[0].set(min_x(), min_y());
points[1].set(max_x(), min_y());
points[2].set((min_x() + max_x()) / 2, max_y());
points[0] = xy_float_t({ min_x(), min_y() });
points[1] = xy_float_t({ max_x(), min_y() });
points[2] = xy_float_t({ (min_x() + max_x()) / 2, max_y() });
#endif
#endif
}

View File

@ -168,10 +168,14 @@
void M554_report();
#endif
typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_stepper_current_t;
typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_hybrid_threshold_t;
typedef struct { int16_t LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4; } tmc_sgt_t;
typedef struct { bool LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_stealth_enabled_t;
#define _EN_ITEM(N) , E##N
typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stepper_current_t;
typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_hybrid_threshold_t;
typedef struct { int16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4; } tmc_sgt_t;
typedef struct { bool LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stealth_enabled_t;
#undef _EN_ITEM
// Limit an index to an array size
#define ALIM(I,ARR) _MIN(I, (signed)COUNT(ARR) - 1)
@ -387,7 +391,7 @@ typedef struct SettingsDataStruct {
#ifndef MOTOR_CURRENT_COUNT
#define MOTOR_CURRENT_COUNT LINEAR_AXES
#endif
uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // M907 X Z E
uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // M907 X Z E ...
//
// CNC_COORDINATE_SYSTEMS
@ -654,7 +658,7 @@ void MarlinSettings::postprocess() {
EEPROM_WRITE(dummyf);
#endif
#else
const xyze_pos_t planner_max_jerk = LOGICAL_AXIS_ARRAY(float(DEFAULT_EJERK), 10, 10, 0.4);
const xyze_pos_t planner_max_jerk = LOGICAL_AXIS_ARRAY(float(DEFAULT_EJERK), 10, 10, 0.4, 0.4, 0.4, 0.4);
EEPROM_WRITE(planner_max_jerk);
#endif
@ -1087,6 +1091,15 @@ void MarlinSettings::postprocess() {
#if AXIS_IS_TMC(Z)
tmc_stepper_current.Z = stepperZ.getMilliamps();
#endif
#if AXIS_IS_TMC(I)
tmc_stepper_current.I = stepperI.getMilliamps();
#endif
#if AXIS_IS_TMC(J)
tmc_stepper_current.J = stepperJ.getMilliamps();
#endif
#if AXIS_IS_TMC(K)
tmc_stepper_current.K = stepperK.getMilliamps();
#endif
#if AXIS_IS_TMC(X2)
tmc_stepper_current.X2 = stepperX2.getMilliamps();
#endif
@ -1138,61 +1151,33 @@ void MarlinSettings::postprocess() {
#if ENABLED(HYBRID_THRESHOLD)
tmc_hybrid_threshold_t tmc_hybrid_threshold{0};
#if AXIS_HAS_STEALTHCHOP(X)
tmc_hybrid_threshold.X = stepperX.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(Y)
tmc_hybrid_threshold.Y = stepperY.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(Z)
tmc_hybrid_threshold.Z = stepperZ.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(X2)
tmc_hybrid_threshold.X2 = stepperX2.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(Y2)
tmc_hybrid_threshold.Y2 = stepperY2.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(Z2)
tmc_hybrid_threshold.Z2 = stepperZ2.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(Z3)
tmc_hybrid_threshold.Z3 = stepperZ3.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(Z4)
tmc_hybrid_threshold.Z4 = stepperZ4.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E0)
tmc_hybrid_threshold.E0 = stepperE0.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E1)
tmc_hybrid_threshold.E1 = stepperE1.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E2)
tmc_hybrid_threshold.E2 = stepperE2.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E3)
tmc_hybrid_threshold.E3 = stepperE3.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E4)
tmc_hybrid_threshold.E4 = stepperE4.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E5)
tmc_hybrid_threshold.E5 = stepperE5.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E6)
tmc_hybrid_threshold.E6 = stepperE6.get_pwm_thrs();
#endif
#if AXIS_HAS_STEALTHCHOP(E7)
tmc_hybrid_threshold.E7 = stepperE7.get_pwm_thrs();
#endif
TERN_(X_HAS_STEALTHCHOP, tmc_hybrid_threshold.X = stepperX.get_pwm_thrs());
TERN_(Y_HAS_STEALTHCHOP, tmc_hybrid_threshold.Y = stepperY.get_pwm_thrs());
TERN_(Z_HAS_STEALTHCHOP, tmc_hybrid_threshold.Z = stepperZ.get_pwm_thrs());
TERN_(I_HAS_STEALTHCHOP, tmc_hybrid_threshold.I = stepperI.get_pwm_thrs());
TERN_(J_HAS_STEALTHCHOP, tmc_hybrid_threshold.J = stepperJ.get_pwm_thrs());
TERN_(K_HAS_STEALTHCHOP, tmc_hybrid_threshold.K = stepperK.get_pwm_thrs());
TERN_(X2_HAS_STEALTHCHOP, tmc_hybrid_threshold.X2 = stepperX2.get_pwm_thrs());
TERN_(Y2_HAS_STEALTHCHOP, tmc_hybrid_threshold.Y2 = stepperY2.get_pwm_thrs());
TERN_(Z2_HAS_STEALTHCHOP, tmc_hybrid_threshold.Z2 = stepperZ2.get_pwm_thrs());
TERN_(Z3_HAS_STEALTHCHOP, tmc_hybrid_threshold.Z3 = stepperZ3.get_pwm_thrs());
TERN_(Z4_HAS_STEALTHCHOP, tmc_hybrid_threshold.Z4 = stepperZ4.get_pwm_thrs());
TERN_(E0_HAS_STEALTHCHOP, tmc_hybrid_threshold.E0 = stepperE0.get_pwm_thrs());
TERN_(E1_HAS_STEALTHCHOP, tmc_hybrid_threshold.E1 = stepperE1.get_pwm_thrs());
TERN_(E2_HAS_STEALTHCHOP, tmc_hybrid_threshold.E2 = stepperE2.get_pwm_thrs());
TERN_(E3_HAS_STEALTHCHOP, tmc_hybrid_threshold.E3 = stepperE3.get_pwm_thrs());
TERN_(E4_HAS_STEALTHCHOP, tmc_hybrid_threshold.E4 = stepperE4.get_pwm_thrs());
TERN_(E5_HAS_STEALTHCHOP, tmc_hybrid_threshold.E5 = stepperE5.get_pwm_thrs());
TERN_(E6_HAS_STEALTHCHOP, tmc_hybrid_threshold.E6 = stepperE6.get_pwm_thrs());
TERN_(E7_HAS_STEALTHCHOP, tmc_hybrid_threshold.E7 = stepperE7.get_pwm_thrs());
#else
#define _EN_ITEM(N) , .E##N = 30
const tmc_hybrid_threshold_t tmc_hybrid_threshold = {
LINEAR_AXIS_LIST(.X = 100, .Y = 100, .Z = 3),
.X2 = 100, .Y2 = 100, .Z2 = 3, .Z3 = 3, .Z4 = 3,
.E0 = 30, .E1 = 30, .E2 = 30, .E3 = 30,
.E4 = 30, .E5 = 30, .E6 = 30, .E7 = 30
LINEAR_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3),
.X2 = 100, .Y2 = 100, .Z2 = 3, .Z3 = 3, .Z4 = 3
REPEAT(EXTRUDERS, _EN_ITEM)
};
#undef _EN_ITEM
#endif
EEPROM_WRITE(tmc_hybrid_threshold);
}
@ -1203,11 +1188,16 @@ void MarlinSettings::postprocess() {
{
tmc_sgt_t tmc_sgt{0};
#if USE_SENSORLESS
TERN_(X_SENSORLESS, tmc_sgt.X = stepperX.homing_threshold());
LINEAR_AXIS_CODE(
TERN_(X_SENSORLESS, tmc_sgt.X = stepperX.homing_threshold()),
TERN_(Y_SENSORLESS, tmc_sgt.Y = stepperY.homing_threshold()),
TERN_(Z_SENSORLESS, tmc_sgt.Z = stepperZ.homing_threshold()),
TERN_(I_SENSORLESS, tmc_sgt.I = stepperI.homing_threshold()),
TERN_(J_SENSORLESS, tmc_sgt.J = stepperJ.homing_threshold()),
TERN_(K_SENSORLESS, tmc_sgt.K = stepperK.homing_threshold())
);
TERN_(X2_SENSORLESS, tmc_sgt.X2 = stepperX2.homing_threshold());
TERN_(Y_SENSORLESS, tmc_sgt.Y = stepperY.homing_threshold());
TERN_(Y2_SENSORLESS, tmc_sgt.Y2 = stepperY2.homing_threshold());
TERN_(Z_SENSORLESS, tmc_sgt.Z = stepperZ.homing_threshold());
TERN_(Z2_SENSORLESS, tmc_sgt.Z2 = stepperZ2.homing_threshold());
TERN_(Z3_SENSORLESS, tmc_sgt.Z3 = stepperZ3.homing_threshold());
TERN_(Z4_SENSORLESS, tmc_sgt.Z4 = stepperZ4.homing_threshold());
@ -1222,54 +1212,25 @@ void MarlinSettings::postprocess() {
_FIELD_TEST(tmc_stealth_enabled);
tmc_stealth_enabled_t tmc_stealth_enabled = { false };
#if AXIS_HAS_STEALTHCHOP(X)
tmc_stealth_enabled.X = stepperX.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(Y)
tmc_stealth_enabled.Y = stepperY.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(Z)
tmc_stealth_enabled.Z = stepperZ.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(X2)
tmc_stealth_enabled.X2 = stepperX2.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(Y2)
tmc_stealth_enabled.Y2 = stepperY2.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(Z2)
tmc_stealth_enabled.Z2 = stepperZ2.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(Z3)
tmc_stealth_enabled.Z3 = stepperZ3.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(Z4)
tmc_stealth_enabled.Z4 = stepperZ4.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E0)
tmc_stealth_enabled.E0 = stepperE0.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E1)
tmc_stealth_enabled.E1 = stepperE1.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E2)
tmc_stealth_enabled.E2 = stepperE2.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E3)
tmc_stealth_enabled.E3 = stepperE3.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E4)
tmc_stealth_enabled.E4 = stepperE4.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E5)
tmc_stealth_enabled.E5 = stepperE5.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E6)
tmc_stealth_enabled.E6 = stepperE6.get_stored_stealthChop();
#endif
#if AXIS_HAS_STEALTHCHOP(E7)
tmc_stealth_enabled.E7 = stepperE7.get_stored_stealthChop();
#endif
TERN_(X_HAS_STEALTHCHOP, tmc_stealth_enabled.X = stepperX.get_stored_stealthChop());
TERN_(Y_HAS_STEALTHCHOP, tmc_stealth_enabled.Y = stepperY.get_stored_stealthChop());
TERN_(Z_HAS_STEALTHCHOP, tmc_stealth_enabled.Z = stepperZ.get_stored_stealthChop());
TERN_(I_HAS_STEALTHCHOP, tmc_stealth_enabled.I = stepperI.get_stored_stealthChop());
TERN_(J_HAS_STEALTHCHOP, tmc_stealth_enabled.J = stepperJ.get_stored_stealthChop());
TERN_(K_HAS_STEALTHCHOP, tmc_stealth_enabled.K = stepperK.get_stored_stealthChop());
TERN_(X2_HAS_STEALTHCHOP, tmc_stealth_enabled.X2 = stepperX2.get_stored_stealthChop());
TERN_(Y2_HAS_STEALTHCHOP, tmc_stealth_enabled.Y2 = stepperY2.get_stored_stealthChop());
TERN_(Z2_HAS_STEALTHCHOP, tmc_stealth_enabled.Z2 = stepperZ2.get_stored_stealthChop());
TERN_(Z3_HAS_STEALTHCHOP, tmc_stealth_enabled.Z3 = stepperZ3.get_stored_stealthChop());
TERN_(Z4_HAS_STEALTHCHOP, tmc_stealth_enabled.Z4 = stepperZ4.get_stored_stealthChop());
TERN_(E0_HAS_STEALTHCHOP, tmc_stealth_enabled.E0 = stepperE0.get_stored_stealthChop());
TERN_(E1_HAS_STEALTHCHOP, tmc_stealth_enabled.E1 = stepperE1.get_stored_stealthChop());
TERN_(E2_HAS_STEALTHCHOP, tmc_stealth_enabled.E2 = stepperE2.get_stored_stealthChop());
TERN_(E3_HAS_STEALTHCHOP, tmc_stealth_enabled.E3 = stepperE3.get_stored_stealthChop());
TERN_(E4_HAS_STEALTHCHOP, tmc_stealth_enabled.E4 = stepperE4.get_stored_stealthChop());
TERN_(E5_HAS_STEALTHCHOP, tmc_stealth_enabled.E5 = stepperE5.get_stored_stealthChop());
TERN_(E6_HAS_STEALTHCHOP, tmc_stealth_enabled.E6 = stepperE6.get_stored_stealthChop());
TERN_(E7_HAS_STEALTHCHOP, tmc_stealth_enabled.E7 = stepperE7.get_stored_stealthChop());
EEPROM_WRITE(tmc_stealth_enabled);
}
@ -1992,6 +1953,15 @@ void MarlinSettings::postprocess() {
#if AXIS_IS_TMC(Z4)
SET_CURR(Z4);
#endif
#if AXIS_IS_TMC(I)
SET_CURR(I);
#endif
#if AXIS_IS_TMC(J)
SET_CURR(J);
#endif
#if AXIS_IS_TMC(K)
SET_CURR(K);
#endif
#if AXIS_IS_TMC(E0)
SET_CURR(E0);
#endif
@ -2028,54 +1998,25 @@ void MarlinSettings::postprocess() {
#if ENABLED(HYBRID_THRESHOLD)
if (!validating) {
#if AXIS_HAS_STEALTHCHOP(X)
stepperX.set_pwm_thrs(tmc_hybrid_threshold.X);
#endif
#if AXIS_HAS_STEALTHCHOP(Y)
stepperY.set_pwm_thrs(tmc_hybrid_threshold.Y);
#endif
#if AXIS_HAS_STEALTHCHOP(Z)
stepperZ.set_pwm_thrs(tmc_hybrid_threshold.Z);
#endif
#if AXIS_HAS_STEALTHCHOP(X2)
stepperX2.set_pwm_thrs(tmc_hybrid_threshold.X2);
#endif
#if AXIS_HAS_STEALTHCHOP(Y2)
stepperY2.set_pwm_thrs(tmc_hybrid_threshold.Y2);
#endif
#if AXIS_HAS_STEALTHCHOP(Z2)
stepperZ2.set_pwm_thrs(tmc_hybrid_threshold.Z2);
#endif
#if AXIS_HAS_STEALTHCHOP(Z3)
stepperZ3.set_pwm_thrs(tmc_hybrid_threshold.Z3);
#endif
#if AXIS_HAS_STEALTHCHOP(Z4)
stepperZ4.set_pwm_thrs(tmc_hybrid_threshold.Z4);
#endif
#if AXIS_HAS_STEALTHCHOP(E0)
stepperE0.set_pwm_thrs(tmc_hybrid_threshold.E0);
#endif
#if AXIS_HAS_STEALTHCHOP(E1)
stepperE1.set_pwm_thrs(tmc_hybrid_threshold.E1);
#endif
#if AXIS_HAS_STEALTHCHOP(E2)
stepperE2.set_pwm_thrs(tmc_hybrid_threshold.E2);
#endif
#if AXIS_HAS_STEALTHCHOP(E3)
stepperE3.set_pwm_thrs(tmc_hybrid_threshold.E3);
#endif
#if AXIS_HAS_STEALTHCHOP(E4)
stepperE4.set_pwm_thrs(tmc_hybrid_threshold.E4);
#endif
#if AXIS_HAS_STEALTHCHOP(E5)
stepperE5.set_pwm_thrs(tmc_hybrid_threshold.E5);
#endif
#if AXIS_HAS_STEALTHCHOP(E6)
stepperE6.set_pwm_thrs(tmc_hybrid_threshold.E6);
#endif
#if AXIS_HAS_STEALTHCHOP(E7)
stepperE7.set_pwm_thrs(tmc_hybrid_threshold.E7);
#endif
TERN_(X_HAS_STEALTHCHOP, stepperX.set_pwm_thrs(tmc_hybrid_threshold.X));
TERN_(Y_HAS_STEALTHCHOP, stepperY.set_pwm_thrs(tmc_hybrid_threshold.Y));
TERN_(Z_HAS_STEALTHCHOP, stepperZ.set_pwm_thrs(tmc_hybrid_threshold.Z));
TERN_(X2_HAS_STEALTHCHOP, stepperX2.set_pwm_thrs(tmc_hybrid_threshold.X2));
TERN_(Y2_HAS_STEALTHCHOP, stepperY2.set_pwm_thrs(tmc_hybrid_threshold.Y2));
TERN_(Z2_HAS_STEALTHCHOP, stepperZ2.set_pwm_thrs(tmc_hybrid_threshold.Z2));
TERN_(Z3_HAS_STEALTHCHOP, stepperZ3.set_pwm_thrs(tmc_hybrid_threshold.Z3));
TERN_(Z4_HAS_STEALTHCHOP, stepperZ4.set_pwm_thrs(tmc_hybrid_threshold.Z4));
TERN_(I_HAS_STEALTHCHOP, stepperI.set_pwm_thrs(tmc_hybrid_threshold.I));
TERN_(J_HAS_STEALTHCHOP, stepperJ.set_pwm_thrs(tmc_hybrid_threshold.J));
TERN_(K_HAS_STEALTHCHOP, stepperK.set_pwm_thrs(tmc_hybrid_threshold.K));
TERN_(E0_HAS_STEALTHCHOP, stepperE0.set_pwm_thrs(tmc_hybrid_threshold.E0));
TERN_(E1_HAS_STEALTHCHOP, stepperE1.set_pwm_thrs(tmc_hybrid_threshold.E1));
TERN_(E2_HAS_STEALTHCHOP, stepperE2.set_pwm_thrs(tmc_hybrid_threshold.E2));
TERN_(E3_HAS_STEALTHCHOP, stepperE3.set_pwm_thrs(tmc_hybrid_threshold.E3));
TERN_(E4_HAS_STEALTHCHOP, stepperE4.set_pwm_thrs(tmc_hybrid_threshold.E4));
TERN_(E5_HAS_STEALTHCHOP, stepperE5.set_pwm_thrs(tmc_hybrid_threshold.E5));
TERN_(E6_HAS_STEALTHCHOP, stepperE6.set_pwm_thrs(tmc_hybrid_threshold.E6));
TERN_(E7_HAS_STEALTHCHOP, stepperE7.set_pwm_thrs(tmc_hybrid_threshold.E7));
}
#endif
}
@ -2089,11 +2030,16 @@ void MarlinSettings::postprocess() {
EEPROM_READ(tmc_sgt);
#if USE_SENSORLESS
if (!validating) {
TERN_(X_SENSORLESS, stepperX.homing_threshold(tmc_sgt.X));
LINEAR_AXIS_CODE(
TERN_(X_SENSORLESS, stepperX.homing_threshold(tmc_sgt.X)),
TERN_(Y_SENSORLESS, stepperY.homing_threshold(tmc_sgt.Y)),
TERN_(Z_SENSORLESS, stepperZ.homing_threshold(tmc_sgt.Z)),
TERN_(I_SENSORLESS, stepperI.homing_threshold(tmc_sgt.I)),
TERN_(J_SENSORLESS, stepperJ.homing_threshold(tmc_sgt.J)),
TERN_(K_SENSORLESS, stepperK.homing_threshold(tmc_sgt.K))
);
TERN_(X2_SENSORLESS, stepperX2.homing_threshold(tmc_sgt.X2));
TERN_(Y_SENSORLESS, stepperY.homing_threshold(tmc_sgt.Y));
TERN_(Y2_SENSORLESS, stepperY2.homing_threshold(tmc_sgt.Y2));
TERN_(Z_SENSORLESS, stepperZ.homing_threshold(tmc_sgt.Z));
TERN_(Z2_SENSORLESS, stepperZ2.homing_threshold(tmc_sgt.Z2));
TERN_(Z3_SENSORLESS, stepperZ3.homing_threshold(tmc_sgt.Z3));
TERN_(Z4_SENSORLESS, stepperZ4.homing_threshold(tmc_sgt.Z4));
@ -2112,54 +2058,25 @@ void MarlinSettings::postprocess() {
#define SET_STEPPING_MODE(ST) stepper##ST.stored.stealthChop_enabled = tmc_stealth_enabled.ST; stepper##ST.refresh_stepping_mode();
if (!validating) {
#if AXIS_HAS_STEALTHCHOP(X)
SET_STEPPING_MODE(X);
#endif
#if AXIS_HAS_STEALTHCHOP(Y)
SET_STEPPING_MODE(Y);
#endif
#if AXIS_HAS_STEALTHCHOP(Z)
SET_STEPPING_MODE(Z);
#endif
#if AXIS_HAS_STEALTHCHOP(X2)
SET_STEPPING_MODE(X2);
#endif
#if AXIS_HAS_STEALTHCHOP(Y2)
SET_STEPPING_MODE(Y2);
#endif
#if AXIS_HAS_STEALTHCHOP(Z2)
SET_STEPPING_MODE(Z2);
#endif
#if AXIS_HAS_STEALTHCHOP(Z3)
SET_STEPPING_MODE(Z3);
#endif
#if AXIS_HAS_STEALTHCHOP(Z4)
SET_STEPPING_MODE(Z4);
#endif
#if AXIS_HAS_STEALTHCHOP(E0)
SET_STEPPING_MODE(E0);
#endif
#if AXIS_HAS_STEALTHCHOP(E1)
SET_STEPPING_MODE(E1);
#endif
#if AXIS_HAS_STEALTHCHOP(E2)
SET_STEPPING_MODE(E2);
#endif
#if AXIS_HAS_STEALTHCHOP(E3)
SET_STEPPING_MODE(E3);
#endif
#if AXIS_HAS_STEALTHCHOP(E4)
SET_STEPPING_MODE(E4);
#endif
#if AXIS_HAS_STEALTHCHOP(E5)
SET_STEPPING_MODE(E5);
#endif
#if AXIS_HAS_STEALTHCHOP(E6)
SET_STEPPING_MODE(E6);
#endif
#if AXIS_HAS_STEALTHCHOP(E7)
SET_STEPPING_MODE(E7);
#endif
TERN_(X_HAS_STEALTHCHOP, SET_STEPPING_MODE(X));
TERN_(Y_HAS_STEALTHCHOP, SET_STEPPING_MODE(Y));
TERN_(Z_HAS_STEALTHCHOP, SET_STEPPING_MODE(Z));
TERN_(I_HAS_STEALTHCHOP, SET_STEPPING_MODE(I));
TERN_(J_HAS_STEALTHCHOP, SET_STEPPING_MODE(J));
TERN_(K_HAS_STEALTHCHOP, SET_STEPPING_MODE(K));
TERN_(X2_HAS_STEALTHCHOP, SET_STEPPING_MODE(X2));
TERN_(Y2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Y2));
TERN_(Z2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Z2));
TERN_(Z3_HAS_STEALTHCHOP, SET_STEPPING_MODE(Z3));
TERN_(Z4_HAS_STEALTHCHOP, SET_STEPPING_MODE(Z4));
TERN_(E0_HAS_STEALTHCHOP, SET_STEPPING_MODE(E0));
TERN_(E1_HAS_STEALTHCHOP, SET_STEPPING_MODE(E1));
TERN_(E2_HAS_STEALTHCHOP, SET_STEPPING_MODE(E2));
TERN_(E3_HAS_STEALTHCHOP, SET_STEPPING_MODE(E3));
TERN_(E4_HAS_STEALTHCHOP, SET_STEPPING_MODE(E4));
TERN_(E5_HAS_STEALTHCHOP, SET_STEPPING_MODE(E5));
TERN_(E6_HAS_STEALTHCHOP, SET_STEPPING_MODE(E6));
TERN_(E7_HAS_STEALTHCHOP, SET_STEPPING_MODE(E7));
}
#endif
}
@ -2598,14 +2515,25 @@ void MarlinSettings::reset() {
#ifndef DEFAULT_XJERK
#define DEFAULT_XJERK 0
#endif
#ifndef DEFAULT_YJERK
#if HAS_Y_AXIS && !defined(DEFAULT_YJERK)
#define DEFAULT_YJERK 0
#endif
#ifndef DEFAULT_ZJERK
#if HAS_Z_AXIS && !defined(DEFAULT_ZJERK)
#define DEFAULT_ZJERK 0
#endif
planner.max_jerk.set(LINEAR_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK));
TERN_(HAS_CLASSIC_E_JERK, planner.max_jerk.e = DEFAULT_EJERK;);
#if LINEAR_AXES >= 4 && !defined(DEFAULT_IJERK)
#define DEFAULT_IJERK 0
#endif
#if LINEAR_AXES >= 5 && !defined(DEFAULT_JJERK)
#define DEFAULT_JJERK 0
#endif
#if LINEAR_AXES >= 6 && !defined(DEFAULT_KJERK)
#define DEFAULT_KJERK 0
#endif
planner.max_jerk.set(
LINEAR_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_IJERK, DEFAULT_JJERK, DEFAULT_KJERK)
);
TERN_(HAS_CLASSIC_E_JERK, planner.max_jerk.e = DEFAULT_EJERK);
#endif
#if HAS_JUNCTION_DEVIATION
@ -2703,11 +2631,11 @@ void MarlinSettings::reset() {
#if HAS_BED_PROBE
constexpr float dpo[] = NOZZLE_TO_PROBE_OFFSET;
static_assert(COUNT(dpo) == 3, "NOZZLE_TO_PROBE_OFFSET must contain offsets for X, Y, and Z.");
static_assert(COUNT(dpo) == LINEAR_AXES, "NOZZLE_TO_PROBE_OFFSET must contain offsets for each linear axis X, Y, Z....");
#if HAS_PROBE_XY_OFFSET
LOOP_LINEAR_AXES(a) probe.offset[a] = dpo[a];
#else
probe.offset.set(0, 0, dpo[Z_AXIS]);
probe.offset.set(LINEAR_AXIS_LIST(0, 0, dpo[Z_AXIS], 0, 0, 0));
#endif
#endif
@ -3145,7 +3073,10 @@ void MarlinSettings::reset() {
LIST_N(DOUBLE(LINEAR_AXES),
PSTR(" M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS]),
SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS]),
SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS])
SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS]),
SP_I_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[I_AXIS]),
SP_J_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[J_AXIS]),
SP_K_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[K_AXIS])
)
#if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
, SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_feedrate_mm_s[E_AXIS])
@ -3167,7 +3098,10 @@ void MarlinSettings::reset() {
LIST_N(DOUBLE(LINEAR_AXES),
PSTR(" M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS]),
SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS]),
SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS])
SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS]),
SP_I_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[I_AXIS]),
SP_J_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[J_AXIS]),
SP_K_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS])
)
#if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
, SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_acceleration_mm_per_s2[E_AXIS])
@ -3210,9 +3144,14 @@ void MarlinSettings::reset() {
, PSTR(" J"), LINEAR_UNIT(planner.junction_deviation_mm)
#endif
#if HAS_CLASSIC_JERK
, SP_X_STR, LINEAR_UNIT(planner.max_jerk.x)
, SP_Y_STR, LINEAR_UNIT(planner.max_jerk.y)
, SP_Z_STR, LINEAR_UNIT(planner.max_jerk.z)
, LIST_N(DOUBLE(LINEAR_AXES),
SP_X_STR, LINEAR_UNIT(planner.max_jerk.x),
SP_Y_STR, LINEAR_UNIT(planner.max_jerk.y),
SP_Z_STR, LINEAR_UNIT(planner.max_jerk.z),
SP_I_STR, LINEAR_UNIT(planner.max_jerk.i),
SP_J_STR, LINEAR_UNIT(planner.max_jerk.j),
SP_K_STR, LINEAR_UNIT(planner.max_jerk.k)
)
#if HAS_CLASSIC_E_JERK
, SP_E_STR, LINEAR_UNIT(planner.max_jerk.e)
#endif
@ -3224,13 +3163,17 @@ void MarlinSettings::reset() {
CONFIG_ECHO_START();
SERIAL_ECHOLNPAIR_P(
#if IS_CARTESIAN
PSTR(" M206 X"), LINEAR_UNIT(home_offset.x)
, SP_Y_STR, LINEAR_UNIT(home_offset.y)
, SP_Z_STR
LIST_N(LINEAR_AXES,
PSTR(" M206 X"), LINEAR_UNIT(home_offset.x),
SP_Y_STR, LINEAR_UNIT(home_offset.y),
SP_Z_STR, LINEAR_UNIT(home_offset.z),
SP_I_STR, LINEAR_UNIT(home_offset.i),
SP_J_STR, LINEAR_UNIT(home_offset.j),
SP_K_STR, LINEAR_UNIT(home_offset.k)
)
#else
PSTR(" M206 Z")
PSTR(" M206 Z"), LINEAR_UNIT(home_offset.z)
#endif
, LINEAR_UNIT(home_offset.z)
);
#endif
@ -3582,6 +3525,19 @@ void MarlinSettings::reset() {
SERIAL_ECHOLNPAIR(" I3 Z", stepperZ4.getMilliamps());
#endif
#if AXIS_IS_TMC(I)
say_M906(forReplay);
SERIAL_ECHOLNPAIR_P(SP_I_STR, stepperI.getMilliamps());
#endif
#if AXIS_IS_TMC(J)
say_M906(forReplay);
SERIAL_ECHOLNPAIR_P(SP_J_STR, stepperJ.getMilliamps());
#endif
#if AXIS_IS_TMC(K)
say_M906(forReplay);
SERIAL_ECHOLNPAIR_P(SP_K_STR, stepperK.getMilliamps());
#endif
#if AXIS_IS_TMC(E0)
say_M906(forReplay);
SERIAL_ECHOLNPAIR(" T0 E", stepperE0.getMilliamps());
@ -3621,74 +3577,87 @@ void MarlinSettings::reset() {
*/
#if ENABLED(HYBRID_THRESHOLD)
CONFIG_ECHO_HEADING("Hybrid Threshold:");
#if AXIS_HAS_STEALTHCHOP(X) || AXIS_HAS_STEALTHCHOP(Y) || AXIS_HAS_STEALTHCHOP(Z)
#if X_HAS_STEALTHCHOP || Y_HAS_STEALTHCHOP || Z_HAS_STEALTHCHOP
say_M913(forReplay);
#if AXIS_HAS_STEALTHCHOP(X)
#if X_HAS_STEALTHCHOP
SERIAL_ECHOPAIR_P(SP_X_STR, stepperX.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(Y)
#if Y_HAS_STEALTHCHOP
SERIAL_ECHOPAIR_P(SP_Y_STR, stepperY.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(Z)
#if Z_HAS_STEALTHCHOP
SERIAL_ECHOPAIR_P(SP_Z_STR, stepperZ.get_pwm_thrs());
#endif
SERIAL_EOL();
#endif
#if AXIS_HAS_STEALTHCHOP(X2) || AXIS_HAS_STEALTHCHOP(Y2) || AXIS_HAS_STEALTHCHOP(Z2)
#if X2_HAS_STEALTHCHOP || Y2_HAS_STEALTHCHOP || Z2_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOPGM(" I1");
#if AXIS_HAS_STEALTHCHOP(X2)
#if X2_HAS_STEALTHCHOP
SERIAL_ECHOPAIR_P(SP_X_STR, stepperX2.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(Y2)
#if Y2_HAS_STEALTHCHOP
SERIAL_ECHOPAIR_P(SP_Y_STR, stepperY2.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(Z2)
#if Z2_HAS_STEALTHCHOP
SERIAL_ECHOPAIR_P(SP_Z_STR, stepperZ2.get_pwm_thrs());
#endif
SERIAL_EOL();
#endif
#if AXIS_HAS_STEALTHCHOP(Z3)
#if Z3_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" I2 Z", stepperZ3.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(Z4)
#if Z4_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" I3 Z", stepperZ4.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E0)
#if I_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR_P(SP_I_STR, stepperI.get_pwm_thrs());
#endif
#if J_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR_P(SP_J_STR, stepperJ.get_pwm_thrs());
#endif
#if K_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR_P(SP_K_STR, stepperK.get_pwm_thrs());
#endif
#if E0_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T0 E", stepperE0.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E1)
#if E1_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T1 E", stepperE1.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E2)
#if E2_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T2 E", stepperE2.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E3)
#if E3_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T3 E", stepperE3.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E4)
#if E4_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T4 E", stepperE4.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E5)
#if E5_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T5 E", stepperE5.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E6)
#if E6_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T6 E", stepperE6.get_pwm_thrs());
#endif
#if AXIS_HAS_STEALTHCHOP(E7)
#if E7_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPAIR(" T7 E", stepperE7.get_pwm_thrs());
#endif
@ -3743,6 +3712,22 @@ void MarlinSettings::reset() {
SERIAL_ECHOLNPAIR(" I3 Z", stepperZ4.homing_threshold());
#endif
#if I_SENSORLESS
CONFIG_ECHO_START();
say_M914();
SERIAL_ECHOLNPAIR_P(SP_I_STR, stepperI.homing_threshold());
#endif
#if J_SENSORLESS
CONFIG_ECHO_START();
say_M914();
SERIAL_ECHOLNPAIR_P(SP_J_STR, stepperJ.homing_threshold());
#endif
#if K_SENSORLESS
CONFIG_ECHO_START();
say_M914();
SERIAL_ECHOLNPAIR_P(SP_K_STR, stepperK.homing_threshold());
#endif
#endif // USE_SENSORLESS
/**
@ -3750,45 +3735,29 @@ void MarlinSettings::reset() {
*/
#if HAS_STEALTHCHOP
CONFIG_ECHO_HEADING("Driver stepping mode:");
#if AXIS_HAS_STEALTHCHOP(X)
const bool chop_x = stepperX.get_stored_stealthChop();
#else
constexpr bool chop_x = false;
#endif
#if AXIS_HAS_STEALTHCHOP(Y)
const bool chop_y = stepperY.get_stored_stealthChop();
#else
constexpr bool chop_y = false;
#endif
#if AXIS_HAS_STEALTHCHOP(Z)
const bool chop_z = stepperZ.get_stored_stealthChop();
#else
constexpr bool chop_z = false;
#endif
const bool chop_x = TERN0(X_HAS_STEALTHCHOP, stepperX.get_stored_stealthChop()),
chop_y = TERN0(Y_HAS_STEALTHCHOP, stepperY.get_stored_stealthChop()),
chop_z = TERN0(Z_HAS_STEALTHCHOP, stepperZ.get_stored_stealthChop()),
chop_i = TERN0(I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop()),
chop_j = TERN0(J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop()),
chop_k = TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop());
if (chop_x || chop_y || chop_z) {
if (chop_x || chop_y || chop_z || chop_i || chop_j || chop_k) {
say_M569(forReplay);
if (chop_x) SERIAL_ECHOPGM_P(SP_X_STR);
if (chop_y) SERIAL_ECHOPGM_P(SP_Y_STR);
if (chop_z) SERIAL_ECHOPGM_P(SP_Z_STR);
LINEAR_AXIS_CODE(
if (chop_x) SERIAL_ECHOPGM_P(SP_X_STR),
if (chop_y) SERIAL_ECHOPGM_P(SP_Y_STR),
if (chop_z) SERIAL_ECHOPGM_P(SP_Z_STR),
if (chop_i) SERIAL_ECHOPGM_P(SP_I_STR),
if (chop_j) SERIAL_ECHOPGM_P(SP_J_STR),
if (chop_k) SERIAL_ECHOPGM_P(SP_K_STR)
);
SERIAL_EOL();
}
#if AXIS_HAS_STEALTHCHOP(X2)
const bool chop_x2 = stepperX2.get_stored_stealthChop();
#else
constexpr bool chop_x2 = false;
#endif
#if AXIS_HAS_STEALTHCHOP(Y2)
const bool chop_y2 = stepperY2.get_stored_stealthChop();
#else
constexpr bool chop_y2 = false;
#endif
#if AXIS_HAS_STEALTHCHOP(Z2)
const bool chop_z2 = stepperZ2.get_stored_stealthChop();
#else
constexpr bool chop_z2 = false;
#endif
const bool chop_x2 = TERN0(X2_HAS_STEALTHCHOP, stepperX2.get_stored_stealthChop()),
chop_y2 = TERN0(Y2_HAS_STEALTHCHOP, stepperY2.get_stored_stealthChop()),
chop_z2 = TERN0(Z2_HAS_STEALTHCHOP, stepperZ2.get_stored_stealthChop());
if (chop_x2 || chop_y2 || chop_z2) {
say_M569(forReplay, PSTR("I1"));
@ -3798,38 +3767,21 @@ void MarlinSettings::reset() {
SERIAL_EOL();
}
#if AXIS_HAS_STEALTHCHOP(Z3)
if (stepperZ3.get_stored_stealthChop()) { say_M569(forReplay, PSTR("I2 Z"), true); }
#endif
if (TERN0(Z3_HAS_STEALTHCHOP, stepperZ3.get_stored_stealthChop())) { say_M569(forReplay, PSTR("I2 Z"), true); }
if (TERN0(Z4_HAS_STEALTHCHOP, stepperZ4.get_stored_stealthChop())) { say_M569(forReplay, PSTR("I3 Z"), true); }
#if AXIS_HAS_STEALTHCHOP(Z4)
if (stepperZ4.get_stored_stealthChop()) { say_M569(forReplay, PSTR("I3 Z"), true); }
#endif
if (TERN0( I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop())) { say_M569(forReplay, SP_I_STR, true); }
if (TERN0( J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop())) { say_M569(forReplay, SP_J_STR, true); }
if (TERN0( K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop())) { say_M569(forReplay, SP_K_STR, true); }
#if AXIS_HAS_STEALTHCHOP(E0)
if (stepperE0.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T0 E"), true); }
#endif
#if AXIS_HAS_STEALTHCHOP(E1)
if (stepperE1.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T1 E"), true); }
#endif
#if AXIS_HAS_STEALTHCHOP(E2)
if (stepperE2.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T2 E"), true); }
#endif
#if AXIS_HAS_STEALTHCHOP(E3)
if (stepperE3.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T3 E"), true); }
#endif
#if AXIS_HAS_STEALTHCHOP(E4)
if (stepperE4.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T4 E"), true); }
#endif
#if AXIS_HAS_STEALTHCHOP(E5)
if (stepperE5.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T5 E"), true); }
#endif
#if AXIS_HAS_STEALTHCHOP(E6)
if (stepperE6.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T6 E"), true); }
#endif
#if AXIS_HAS_STEALTHCHOP(E7)
if (stepperE7.get_stored_stealthChop()) { say_M569(forReplay, PSTR("T7 E"), true); }
#endif
if (TERN0(E0_HAS_STEALTHCHOP, stepperE0.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T0 E"), true); }
if (TERN0(E1_HAS_STEALTHCHOP, stepperE1.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T1 E"), true); }
if (TERN0(E2_HAS_STEALTHCHOP, stepperE2.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T2 E"), true); }
if (TERN0(E3_HAS_STEALTHCHOP, stepperE3.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T3 E"), true); }
if (TERN0(E4_HAS_STEALTHCHOP, stepperE4.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T4 E"), true); }
if (TERN0(E5_HAS_STEALTHCHOP, stepperE5.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T5 E"), true); }
if (TERN0(E6_HAS_STEALTHCHOP, stepperE6.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T6 E"), true); }
if (TERN0(E7_HAS_STEALTHCHOP, stepperE7.get_stored_stealthChop())) { say_M569(forReplay, PSTR("T7 E"), true); }
#endif // HAS_STEALTHCHOP
@ -3859,7 +3811,7 @@ void MarlinSettings::reset() {
);
#elif HAS_MOTOR_CURRENT_SPI
SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values:
LOOP_LOGICAL_AXES(q) { // X Y Z E (map to X Y Z E0 by default)
LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default)
SERIAL_CHAR(' ', axis_codes[q]);
SERIAL_ECHO(stepper.motor_current_setting[q]);
}
@ -3869,7 +3821,7 @@ void MarlinSettings::reset() {
#elif ENABLED(HAS_MOTOR_CURRENT_I2C) // i2c-based has any number of values
// Values sent over i2c are not stored.
// Indexes map directly to drivers, not axes.
#elif ENABLED(HAS_MOTOR_CURRENT_DAC) // DAC-based has 4 values, for X Y Z E
#elif ENABLED(HAS_MOTOR_CURRENT_DAC) // DAC-based has 4 values, for X Y Z (I J K) E
// Values sent over i2c are not stored. Uses indirect mapping.
#endif
@ -3901,7 +3853,10 @@ void MarlinSettings::reset() {
, LIST_N(DOUBLE(LINEAR_AXES),
SP_X_STR, LINEAR_UNIT(backlash.distance_mm.x),
SP_Y_STR, LINEAR_UNIT(backlash.distance_mm.y),
SP_Z_STR, LINEAR_UNIT(backlash.distance_mm.z)
SP_Z_STR, LINEAR_UNIT(backlash.distance_mm.z),
SP_I_STR, LINEAR_UNIT(backlash.distance_mm.i),
SP_J_STR, LINEAR_UNIT(backlash.distance_mm.j),
SP_K_STR, LINEAR_UNIT(backlash.distance_mm.k)
)
#ifdef BACKLASH_SMOOTHING_MM
, PSTR(" S"), LINEAR_UNIT(backlash.smoothing_mm)

View File

@ -378,7 +378,7 @@ xyze_int8_t Stepper::count_direction{0};
#else
#define Y_APPLY_STEP(v,Q) do{ Y_STEP_WRITE(v); Y2_STEP_WRITE(v); }while(0)
#endif
#else
#elif HAS_Y_AXIS
#define Y_APPLY_DIR(v,Q) Y_DIR_WRITE(v)
#define Y_APPLY_STEP(v,Q) Y_STEP_WRITE(v)
#endif
@ -415,11 +415,24 @@ xyze_int8_t Stepper::count_direction{0};
#else
#define Z_APPLY_STEP(v,Q) do{ Z_STEP_WRITE(v); Z2_STEP_WRITE(v); }while(0)
#endif
#else
#elif HAS_Z_AXIS
#define Z_APPLY_DIR(v,Q) Z_DIR_WRITE(v)
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v)
#endif
#if LINEAR_AXES >= 4
#define I_APPLY_DIR(v,Q) I_DIR_WRITE(v)
#define I_APPLY_STEP(v,Q) I_STEP_WRITE(v)
#endif
#if LINEAR_AXES >= 5
#define J_APPLY_DIR(v,Q) J_DIR_WRITE(v)
#define J_APPLY_STEP(v,Q) J_STEP_WRITE(v)
#endif
#if LINEAR_AXES >= 6
#define K_APPLY_DIR(v,Q) K_DIR_WRITE(v)
#define K_APPLY_STEP(v,Q) K_STEP_WRITE(v)
#endif
#if DISABLED(MIXING_EXTRUDER)
#define E_APPLY_STEP(v,Q) E_STEP_WRITE(stepper_extruder, v)
#endif
@ -486,6 +499,18 @@ void Stepper::set_directions() {
SET_STEP_DIR(Z); // C
#endif
#if HAS_I_DIR
SET_STEP_DIR(I); // I
#endif
#if HAS_J_DIR
SET_STEP_DIR(J); // J
#endif
#if HAS_K_DIR
SET_STEP_DIR(K); // K
#endif
#if DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
// Because this is valid for the whole block we don't know
@ -1584,7 +1609,7 @@ void Stepper::pulse_phase_isr() {
const bool is_page = IS_PAGE(current_block);
#if ENABLED(DIRECT_STEPPING)
// TODO (DerAndere): Add support for LINEAR_AXES >= 4
if (is_page) {
#if STEPPER_PAGE_FORMAT == SP_4x4D_128
@ -1700,6 +1725,15 @@ void Stepper::pulse_phase_isr() {
#if HAS_Z_STEP
PULSE_PREP(Z);
#endif
#if HAS_I_STEP
PULSE_PREP(I);
#endif
#if HAS_J_STEP
PULSE_PREP(J);
#endif
#if HAS_K_STEP
PULSE_PREP(K);
#endif
#if EITHER(LIN_ADVANCE, MIXING_EXTRUDER)
delta_error.e += advance_dividend.e;
@ -1735,6 +1769,15 @@ void Stepper::pulse_phase_isr() {
#if HAS_Z_STEP
PULSE_START(Z);
#endif
#if HAS_I_STEP
PULSE_START(I);
#endif
#if HAS_J_STEP
PULSE_START(J);
#endif
#if HAS_K_STEP
PULSE_START(K);
#endif
#if DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
@ -1764,6 +1807,15 @@ void Stepper::pulse_phase_isr() {
#if HAS_Z_STEP
PULSE_STOP(Z);
#endif
#if HAS_I_STEP
PULSE_STOP(I);
#endif
#if HAS_J_STEP
PULSE_STOP(J);
#endif
#if HAS_K_STEP
PULSE_STOP(K);
#endif
#if DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
@ -1798,6 +1850,7 @@ uint32_t Stepper::block_phase_isr() {
// If current block is finished, reset pointer and finalize state
if (step_events_completed >= step_event_count) {
#if ENABLED(DIRECT_STEPPING)
// TODO (DerAndere): Add support for LINEAR_AXES >= 4
#if STEPPER_PAGE_FORMAT == SP_4x4D_128
#define PAGE_SEGMENT_UPDATE_POS(AXIS) \
count_position[_AXIS(AXIS)] += page_step_state.bd[_AXIS(AXIS)] - 128 * 7;
@ -2104,9 +2157,12 @@ uint32_t Stepper::block_phase_isr() {
uint8_t axis_bits = 0;
LINEAR_AXIS_CODE(
if (X_MOVE_TEST) SBI(axis_bits, A_AXIS),
if (Y_MOVE_TEST) SBI(axis_bits, B_AXIS),
if (Z_MOVE_TEST) SBI(axis_bits, C_AXIS)
if (X_MOVE_TEST) SBI(axis_bits, A_AXIS),
if (Y_MOVE_TEST) SBI(axis_bits, B_AXIS),
if (Z_MOVE_TEST) SBI(axis_bits, C_AXIS),
if (current_block->steps.i) SBI(axis_bits, I_AXIS),
if (current_block->steps.j) SBI(axis_bits, J_AXIS),
if (current_block->steps.k) SBI(axis_bits, K_AXIS)
);
//if (current_block->steps.e) SBI(axis_bits, E_AXIS);
//if (current_block->steps.a) SBI(axis_bits, X_HEAD);
@ -2441,6 +2497,15 @@ void Stepper::init() {
Z4_DIR_INIT();
#endif
#endif
#if HAS_I_DIR
I_DIR_INIT();
#endif
#if HAS_J_DIR
J_DIR_INIT();
#endif
#if HAS_K_DIR
K_DIR_INIT();
#endif
#if HAS_E0_DIR
E0_DIR_INIT();
#endif
@ -2499,6 +2564,18 @@ void Stepper::init() {
if (!Z_ENABLE_ON) Z4_ENABLE_WRITE(HIGH);
#endif
#endif
#if HAS_I_ENABLE
I_ENABLE_INIT();
if (!I_ENABLE_ON) I_ENABLE_WRITE(HIGH);
#endif
#if HAS_J_ENABLE
J_ENABLE_INIT();
if (!J_ENABLE_ON) J_ENABLE_WRITE(HIGH);
#endif
#if HAS_K_ENABLE
K_ENABLE_INIT();
if (!K_ENABLE_ON) K_ENABLE_WRITE(HIGH);
#endif
#if HAS_E0_ENABLE
E0_ENABLE_INIT();
if (!E_ENABLE_ON) E0_ENABLE_WRITE(HIGH);
@ -2575,6 +2652,15 @@ void Stepper::init() {
#endif
AXIS_INIT(Z, Z);
#endif
#if HAS_I_STEP
AXIS_INIT(I, I);
#endif
#if HAS_J_STEP
AXIS_INIT(J, J);
#endif
#if HAS_K_STEP
AXIS_INIT(K, K);
#endif
#if E_STEPPERS && HAS_E0_STEP
E_AXIS_INIT(0);
@ -2612,7 +2698,10 @@ void Stepper::init() {
LINEAR_AXIS_GANG(
| TERN0(INVERT_X_DIR, _BV(X_AXIS)),
| TERN0(INVERT_Y_DIR, _BV(Y_AXIS)),
| TERN0(INVERT_Z_DIR, _BV(Z_AXIS))
| TERN0(INVERT_Z_DIR, _BV(Z_AXIS)),
| TERN0(INVERT_I_DIR, _BV(I_AXIS)),
| TERN0(INVERT_J_DIR, _BV(J_AXIS)),
| TERN0(INVERT_K_DIR, _BV(K_AXIS))
)
);
@ -2625,32 +2714,32 @@ void Stepper::init() {
/**
* Set the stepper positions directly in steps
*
* The input is based on the typical per-axis XYZ steps.
* The input is based on the typical per-axis XYZE steps.
* For CORE machines XYZ needs to be translated to ABC.
*
* This allows get_axis_position_mm to correctly
* derive the current XYZ position later on.
* derive the current XYZE position later on.
*/
void Stepper::_set_position(
LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
) {
#if CORE_IS_XY
// corexy positioning
// these equations follow the form of the dA and dB equations on https://www.corexy.com/theory.html
count_position.set(a + b, CORESIGN(a - b), c);
#elif CORE_IS_XZ
// corexz planning
count_position.set(a + c, b, CORESIGN(a - c));
#elif CORE_IS_YZ
// coreyz planning
count_position.set(a, b + c, CORESIGN(b - c));
#elif ENABLED(MARKFORGED_XY)
count_position.set(a - b, b, c);
void Stepper::_set_position(const abce_long_t &spos) {
#if EITHER(IS_CORE, MARKFORGED_XY)
#if CORE_IS_XY
// corexy positioning
// these equations follow the form of the dA and dB equations on https://www.corexy.com/theory.html
count_position.set(spos.a + spos.b, CORESIGN(spos.a - spos.b), spos.c);
#elif CORE_IS_XZ
// corexz planning
count_position.set(spos.a + spos.c, spos.b, CORESIGN(spos.a - spos.c));
#elif CORE_IS_YZ
// coreyz planning
count_position.set(spos.a, spos.b + spos.c, CORESIGN(spos.b - spos.c));
#elif ENABLED(MARKFORGED_XY)
count_position.set(spos.a - spos.b, spos.b, spos.c);
#endif
TERN_(HAS_EXTRUDERS, count_position.e = spos.e);
#else
// default non-h-bot planning
count_position.set(LINEAR_AXIS_LIST(a, b, c));
count_position = spos;
#endif
TERN_(HAS_EXTRUDERS, count_position.e = e);
}
/**
@ -2673,13 +2762,10 @@ int32_t Stepper::position(const AxisEnum axis) {
}
// Set the current position in steps
//TODO: Test for LINEAR_AXES >= 4
void Stepper::set_position(
LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
) {
void Stepper::set_position(const xyze_long_t &spos) {
planner.synchronize();
const bool was_enabled = suspend();
_set_position(LOGICAL_AXIS_LIST(e, a, b, c));
_set_position(spos);
if (was_enabled) wake_up();
}
@ -2747,18 +2833,24 @@ int32_t Stepper::triggered_position(const AxisEnum axis) {
return v;
}
#if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA)
#define USES_ABC 1
#endif
#if ANY(USES_ABC, MARKFORGED_XY, IS_SCARA)
#define USES_AB 1
#endif
void Stepper::report_a_position(const xyz_long_t &pos) {
#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, DELTA, IS_SCARA)
SERIAL_ECHOPAIR(STR_COUNT_A, pos.x, " B:", pos.y);
#else
SERIAL_ECHOPAIR_P(PSTR(STR_COUNT_X), pos.x, SP_Y_LBL, pos.y);
#endif
#if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA)
SERIAL_ECHOPAIR(" C:", pos.z);
#elif LINEAR_AXES >= 3
SERIAL_ECHOPAIR_P(SP_Z_LBL, pos.z);
#endif
SERIAL_EOL();
SERIAL_ECHOLNPAIR_P(
LIST_N(DOUBLE(LINEAR_AXES),
TERN(USES_AB, PSTR(STR_COUNT_A), PSTR(STR_COUNT_X)), pos.x,
TERN(USES_AB, PSTR("B:"), SP_Y_LBL), pos.y,
TERN(USES_ABC, PSTR("C:"), SP_Z_LBL), pos.z,
SP_I_LBL, pos.i,
SP_J_LBL, pos.j,
SP_K_LBL, pos.k
)
);
}
void Stepper::report_positions() {
@ -2866,9 +2958,7 @@ void Stepper::report_positions() {
// No other ISR should ever interrupt this!
void Stepper::do_babystep(const AxisEnum axis, const bool direction) {
#if DISABLED(INTEGRATED_BABYSTEPPING)
cli();
#endif
IF_DISABLED(INTEGRATED_BABYSTEPPING, cli());
switch (axis) {
@ -2912,35 +3002,90 @@ void Stepper::report_positions() {
ENABLE_AXIS_X();
ENABLE_AXIS_Y();
ENABLE_AXIS_Z();
ENABLE_AXIS_I();
ENABLE_AXIS_J();
ENABLE_AXIS_K();
DIR_WAIT_BEFORE();
const xyz_byte_t old_dir = LINEAR_AXIS_ARRAY(X_DIR_READ(), Y_DIR_READ(), Z_DIR_READ());
const xyz_byte_t old_dir = LINEAR_AXIS_ARRAY(X_DIR_READ(), Y_DIR_READ(), Z_DIR_READ(), I_DIR_READ(), J_DIR_READ(), K_DIR_READ());
X_DIR_WRITE(INVERT_X_DIR ^ z_direction);
Y_DIR_WRITE(INVERT_Y_DIR ^ z_direction);
Z_DIR_WRITE(INVERT_Z_DIR ^ z_direction);
#ifdef Y_DIR_WRITE
Y_DIR_WRITE(INVERT_Y_DIR ^ z_direction);
#endif
#ifdef Z_DIR_WRITE
Z_DIR_WRITE(INVERT_Z_DIR ^ z_direction);
#endif
#ifdef I_DIR_WRITE
I_DIR_WRITE(INVERT_I_DIR ^ z_direction);
#endif
#ifdef J_DIR_WRITE
J_DIR_WRITE(INVERT_J_DIR ^ z_direction);
#endif
#ifdef K_DIR_WRITE
K_DIR_WRITE(INVERT_K_DIR ^ z_direction);
#endif
DIR_WAIT_AFTER();
_SAVE_START();
X_STEP_WRITE(!INVERT_X_STEP_PIN);
Y_STEP_WRITE(!INVERT_Y_STEP_PIN);
Z_STEP_WRITE(!INVERT_Z_STEP_PIN);
#ifdef Y_STEP_WRITE
Y_STEP_WRITE(!INVERT_Y_STEP_PIN);
#endif
#ifdef Z_STEP_WRITE
Z_STEP_WRITE(!INVERT_Z_STEP_PIN);
#endif
#ifdef I_STEP_WRITE
I_STEP_WRITE(!INVERT_I_STEP_PIN);
#endif
#ifdef J_STEP_WRITE
J_STEP_WRITE(!INVERT_J_STEP_PIN);
#endif
#ifdef K_STEP_WRITE
K_STEP_WRITE(!INVERT_K_STEP_PIN);
#endif
_PULSE_WAIT();
X_STEP_WRITE(INVERT_X_STEP_PIN);
Y_STEP_WRITE(INVERT_Y_STEP_PIN);
Z_STEP_WRITE(INVERT_Z_STEP_PIN);
#ifdef Y_STEP_WRITE
Y_STEP_WRITE(INVERT_Y_STEP_PIN);
#endif
#ifdef Z_STEP_WRITE
Z_STEP_WRITE(INVERT_Z_STEP_PIN);
#endif
#ifdef I_STEP_WRITE
I_STEP_WRITE(INVERT_I_STEP_PIN);
#endif
#ifdef J_STEP_WRITE
J_STEP_WRITE(INVERT_J_STEP_PIN);
#endif
#ifdef K_STEP_WRITE
K_STEP_WRITE(INVERT_K_STEP_PIN);
#endif
// Restore direction bits
EXTRA_DIR_WAIT_BEFORE();
X_DIR_WRITE(old_dir.x);
Y_DIR_WRITE(old_dir.y);
Z_DIR_WRITE(old_dir.z);
#ifdef Y_DIR_WRITE
Y_DIR_WRITE(old_dir.y);
#endif
#ifdef Z_DIR_WRITE
Z_DIR_WRITE(old_dir.z);
#endif
#ifdef I_DIR_WRITE
I_DIR_WRITE(old_dir.i);
#endif
#ifdef J_DIR_WRITE
J_DIR_WRITE(old_dir.j);
#endif
#ifdef K_DIR_WRITE
K_DIR_WRITE(old_dir.k);
#endif
EXTRA_DIR_WAIT_AFTER();
@ -2948,12 +3093,20 @@ void Stepper::report_positions() {
} break;
#if LINEAR_AXES >= 4
case I_AXIS: BABYSTEP_AXIS(I, 0, direction); break;
#endif
#if LINEAR_AXES >= 5
case J_AXIS: BABYSTEP_AXIS(J, 0, direction); break;
#endif
#if LINEAR_AXES >= 6
case K_AXIS: BABYSTEP_AXIS(K, 0, direction); break;
#endif
default: break;
}
#if DISABLED(INTEGRATED_BABYSTEPPING)
sei();
#endif
IF_DISABLED(INTEGRATED_BABYSTEPPING, sei());
}
#endif // BABYSTEPPING
@ -3288,6 +3441,15 @@ void Stepper::report_positions() {
#if HAS_E7_MS_PINS
case 10: WRITE(E7_MS1_PIN, ms1); break;
#endif
#if HAS_I_MICROSTEPS
case 11: WRITE(I_MS1_PIN, ms1); break
#endif
#if HAS_J_MICROSTEPS
case 12: WRITE(J_MS1_PIN, ms1); break
#endif
#if HAS_K_MICROSTEPS
case 13: WRITE(K_MS1_PIN, ms1); break
#endif
}
if (ms2 >= 0) switch (driver) {
#if HAS_X_MS_PINS || HAS_X2_MS_PINS
@ -3350,6 +3512,15 @@ void Stepper::report_positions() {
#if HAS_E7_MS_PINS
case 10: WRITE(E7_MS2_PIN, ms2); break;
#endif
#if HAS_I_M_PINS
case 11: WRITE(I_MS2_PIN, ms2); break
#endif
#if HAS_J_M_PINS
case 12: WRITE(J_MS2_PIN, ms2); break
#endif
#if HAS_K_M_PINS
case 13: WRITE(K_MS2_PIN, ms2); break
#endif
}
if (ms3 >= 0) switch (driver) {
#if HAS_X_MS_PINS || HAS_X2_MS_PINS
@ -3468,6 +3639,24 @@ void Stepper::report_positions() {
PIN_CHAR(Z_MS3);
#endif
#endif
#if HAS_I_MS_PINS
MS_LINE(I);
#if PIN_EXISTS(I_MS3)
PIN_CHAR(I_MS3);
#endif
#endif
#if HAS_J_MS_PINS
MS_LINE(J);
#if PIN_EXISTS(J_MS3)
PIN_CHAR(J_MS3);
#endif
#endif
#if HAS_K_MS_PINS
MS_LINE(K);
#if PIN_EXISTS(K_MS3)
PIN_CHAR(K_MS3);
#endif
#endif
#if HAS_E0_MS_PINS
MS_LINE(E0);
#if PIN_EXISTS(E0_MS3)

View File

@ -133,27 +133,6 @@
#endif
// Add time for each stepper
#if HAS_X_STEP
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_X_STEPPER_CYCLES 0UL
#endif
#if HAS_Y_STEP
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_START_Y_STEPPER_CYCLES 0UL
#define ISR_Y_STEPPER_CYCLES 0UL
#endif
#if HAS_Z_STEP
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_Z_STEPPER_CYCLES 0UL
#endif
// E is always interpolated, even for mixing extruders
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES
// If linear advance is disabled, the loop also handles them
#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER)
#define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
@ -161,8 +140,31 @@
#define ISR_MIXING_STEPPER_CYCLES 0UL
#endif
// Add time for each stepper
#if HAS_X_STEP
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_Y_STEP
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_Z_STEP
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_I_STEP
#define ISR_I_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_J_STEP
#define ISR_J_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_K_STEP
#define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_EXTRUDERS
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders
#endif
// And the total minimum loop time, not including the base
#define MIN_ISR_LOOP_CYCLES (ISR_X_STEPPER_CYCLES + ISR_Y_STEPPER_CYCLES + ISR_Z_STEPPER_CYCLES + ISR_E_STEPPER_CYCLES + ISR_MIXING_STEPPER_CYCLES)
#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES))
// Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate
#define _MIN_STEPPER_PULSE_CYCLES(N) _MAX(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N))
@ -433,12 +435,7 @@ class Stepper {
static int32_t position(const AxisEnum axis);
// Set the current position in steps
static void set_position(
LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
);
static inline void set_position(const xyze_long_t &abce) {
set_position(LOGICAL_AXIS_LIST(abce.e, abce.a, abce.b, abce.c));
}
static void set_position(const xyze_long_t &spos);
static void set_axis_position(const AxisEnum a, const int32_t &v);
// Report the positions of the steppers, in steps
@ -534,12 +531,7 @@ class Stepper {
private:
// Set the current position in steps
static void _set_position(
LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
);
FORCE_INLINE static void _set_position(const abce_long_t &spos) {
_set_position(LOGICAL_AXIS_LIST(spos.e, spos.a, spos.b, spos.c));
}
static void _set_position(const abce_long_t &spos);
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t *loops) {
uint32_t timer;

View File

@ -55,6 +55,15 @@
#if AXIS_IS_L64XX(Z4)
L64XX_CLASS(Z4) stepperZ4(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(I)
L64XX_CLASS(I) stepperI(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(J)
L64XX_CLASS(J) stepperJ(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(K)
L64XX_CLASS(K) stepperK(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(E0)
L64XX_CLASS(E0) stepperE0(L6470_CHAIN_SS_PIN);
#endif
@ -199,6 +208,15 @@ void L64XX_Marlin::init_to_defaults() {
#if AXIS_IS_L64XX(Z4)
L6470_INIT_CHIP(Z4);
#endif
#if AXIS_IS_L64XX(I)
L6470_INIT_CHIP(I);
#endif
#if AXIS_IS_L64XX(J)
L6470_INIT_CHIP(J);
#endif
#if AXIS_IS_L64XX(K)
L6470_INIT_CHIP(K);
#endif
#if AXIS_IS_L64XX(E0)
L6470_INIT_CHIP(E0);
#endif

View File

@ -206,6 +206,66 @@
#define DISABLE_STEPPER_Z4() stepperZ4.free()
#endif
// I Stepper
#if AXIS_IS_L64XX(I)
extern L64XX_CLASS(I) stepperI;
#define I_ENABLE_INIT() NOOP
#define I_ENABLE_WRITE(STATE) (STATE ? stepperI.hardStop() : stepperI.free())
#define I_ENABLE_READ() (stepperI.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_I(L6474)
#define I_DIR_INIT() SET_OUTPUT(I_DIR_PIN)
#define I_DIR_WRITE(STATE) L6474_DIR_WRITE(I, STATE)
#define I_DIR_READ() READ(I_DIR_PIN)
#else
#define I_DIR_INIT() NOOP
#define I_DIR_WRITE(STATE) L64XX_DIR_WRITE(I, STATE)
#define I_DIR_READ() (stepper##I.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_I(L6470)
#define DISABLE_STEPPER_I() stepperI.free()
#endif
#endif
#endif
// J Stepper
#if AXIS_IS_L64XX(J)
extern L64XX_CLASS(J) stepperJ;
#define J_ENABLE_INIT() NOOP
#define J_ENABLE_WRITE(STATE) (STATE ? stepperJ.hardStop() : stepperJ.free())
#define J_ENABLE_READ() (stepperJ.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_J(L6474)
#define J_DIR_INIT() SET_OUTPUT(J_DIR_PIN)
#define J_DIR_WRITE(STATE) L6474_DIR_WRITE(J, STATE)
#define J_DIR_READ() READ(J_DIR_PIN)
#else
#define J_DIR_INIT() NOOP
#define J_DIR_WRITE(STATE) L64XX_DIR_WRITE(J, STATE)
#define J_DIR_READ() (stepper##J.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_J(L6470)
#define DISABLE_STEPPER_J() stepperJ.free()
#endif
#endif
#endif
// K Stepper
#if AXIS_IS_L64XX(K)
extern L64XX_CLASS(K) stepperK;
#define K_ENABLE_INIT() NOOP
#define K_ENABLE_WRITE(STATE) (STATE ? stepperK.hardStop() : stepperK.free())
#define K_ENABLE_READ() (stepperK.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_K(L6474)
#define K_DIR_INIT() SET_OUTPUT(K_DIR_PIN)
#define K_DIR_WRITE(STATE) L6474_DIR_WRITE(K, STATE)
#define K_DIR_READ() READ(K_DIR_PIN)
#else
#define K_DIR_INIT() NOOP
#define K_DIR_WRITE(STATE) L64XX_DIR_WRITE(K, STATE)
#define K_DIR_READ() (stepper##K.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_K(L6470)
#define DISABLE_STEPPER_K() stepperK.free()
#endif
#endif
#endif
// E0 Stepper
#if AXIS_IS_L64XX(E0)
extern L64XX_CLASS(E0) stepperE0;

View File

@ -60,6 +60,15 @@
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
_TMC26X_DEFINE(Z4);
#endif
#if AXIS_DRIVER_TYPE_I(TMC26X)
_TMC26X_DEFINE(I);
#endif
#if AXIS_DRIVER_TYPE_J(TMC26X)
_TMC26X_DEFINE(J);
#endif
#if AXIS_DRIVER_TYPE_K(TMC26X)
_TMC26X_DEFINE(K);
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
_TMC26X_DEFINE(E0);
#endif
@ -115,6 +124,15 @@ void tmc26x_init_to_defaults() {
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
_TMC26X_INIT(Z4);
#endif
#if AXIS_DRIVER_TYPE_I(TMC26X)
_TMC26X_INIT(I);
#endif
#if AXIS_DRIVER_TYPE_J(TMC26X)
_TMC26X_INIT(J);
#endif
#if AXIS_DRIVER_TYPE_K(TMC26X)
_TMC26X_INIT(K);
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
_TMC26X_INIT(E0);
#endif

View File

@ -99,6 +99,30 @@ void tmc26x_init_to_defaults();
#define Z4_ENABLE_READ() stepperZ4.isEnabled()
#endif
// I Stepper
#if HAS_I_ENABLE && AXIS_DRIVER_TYPE_I(TMC26X)
extern TMC26XStepper stepperI;
#define I_ENABLE_INIT() NOOP
#define I_ENABLE_WRITE(STATE) stepperI.setEnabled(STATE)
#define I_ENABLE_READ() stepperI.isEnabled()
#endif
// J Stepper
#if HAS_J_ENABLE && AXIS_DRIVER_TYPE_J(TMC26X)
extern TMC26XStepper stepperJ;
#define J_ENABLE_INIT() NOOP
#define J_ENABLE_WRITE(STATE) stepperJ.setEnabled(STATE)
#define J_ENABLE_READ() stepperJ.isEnabled()
#endif
// K Stepper
#if HAS_K_ENABLE && AXIS_DRIVER_TYPE_K(TMC26X)
extern TMC26XStepper stepperK;
#define K_ENABLE_INIT() NOOP
#define K_ENABLE_WRITE(STATE) stepperK.setEnabled(STATE)
#define K_ENABLE_READ() stepperK.isEnabled()
#endif
// E0 Stepper
#if AXIS_DRIVER_TYPE_E0(TMC26X)
extern TMC26XStepper stepperE0;

View File

@ -37,9 +37,7 @@ void restore_stepper_drivers() {
}
void reset_stepper_drivers() {
#if HAS_DRIVER(TMC26X)
tmc26x_init_to_defaults();
#endif
TERN_(HAS_TMC26X, tmc26x_init_to_defaults());
TERN_(HAS_L64XX, L64xxManager.init_to_defaults());
TERN_(HAS_TRINAMIC_CONFIG, reset_trinamic_drivers());
}

View File

@ -36,7 +36,7 @@
#include "L64xx.h"
#endif
#if HAS_DRIVER(TMC26X)
#if HAS_TMC26X
#include "TMC26X.h"
#endif
@ -65,38 +65,42 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define X_STEP_READ() bool(READ(X_STEP_PIN))
// Y Stepper
#ifndef Y_ENABLE_INIT
#define Y_ENABLE_INIT() SET_OUTPUT(Y_ENABLE_PIN)
#define Y_ENABLE_WRITE(STATE) WRITE(Y_ENABLE_PIN,STATE)
#define Y_ENABLE_READ() bool(READ(Y_ENABLE_PIN))
#if HAS_Y_AXIS
#ifndef Y_ENABLE_INIT
#define Y_ENABLE_INIT() SET_OUTPUT(Y_ENABLE_PIN)
#define Y_ENABLE_WRITE(STATE) WRITE(Y_ENABLE_PIN,STATE)
#define Y_ENABLE_READ() bool(READ(Y_ENABLE_PIN))
#endif
#ifndef Y_DIR_INIT
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
#define Y_DIR_WRITE(STATE) WRITE(Y_DIR_PIN,STATE)
#define Y_DIR_READ() bool(READ(Y_DIR_PIN))
#endif
#define Y_STEP_INIT() SET_OUTPUT(Y_STEP_PIN)
#ifndef Y_STEP_WRITE
#define Y_STEP_WRITE(STATE) WRITE(Y_STEP_PIN,STATE)
#endif
#define Y_STEP_READ() bool(READ(Y_STEP_PIN))
#endif
#ifndef Y_DIR_INIT
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
#define Y_DIR_WRITE(STATE) WRITE(Y_DIR_PIN,STATE)
#define Y_DIR_READ() bool(READ(Y_DIR_PIN))
#endif
#define Y_STEP_INIT() SET_OUTPUT(Y_STEP_PIN)
#ifndef Y_STEP_WRITE
#define Y_STEP_WRITE(STATE) WRITE(Y_STEP_PIN,STATE)
#endif
#define Y_STEP_READ() bool(READ(Y_STEP_PIN))
// Z Stepper
#ifndef Z_ENABLE_INIT
#define Z_ENABLE_INIT() SET_OUTPUT(Z_ENABLE_PIN)
#define Z_ENABLE_WRITE(STATE) WRITE(Z_ENABLE_PIN,STATE)
#define Z_ENABLE_READ() bool(READ(Z_ENABLE_PIN))
#if HAS_Z_AXIS
#ifndef Z_ENABLE_INIT
#define Z_ENABLE_INIT() SET_OUTPUT(Z_ENABLE_PIN)
#define Z_ENABLE_WRITE(STATE) WRITE(Z_ENABLE_PIN,STATE)
#define Z_ENABLE_READ() bool(READ(Z_ENABLE_PIN))
#endif
#ifndef Z_DIR_INIT
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
#define Z_DIR_WRITE(STATE) WRITE(Z_DIR_PIN,STATE)
#define Z_DIR_READ() bool(READ(Z_DIR_PIN))
#endif
#define Z_STEP_INIT() SET_OUTPUT(Z_STEP_PIN)
#ifndef Z_STEP_WRITE
#define Z_STEP_WRITE(STATE) WRITE(Z_STEP_PIN,STATE)
#endif
#define Z_STEP_READ() bool(READ(Z_STEP_PIN))
#endif
#ifndef Z_DIR_INIT
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
#define Z_DIR_WRITE(STATE) WRITE(Z_DIR_PIN,STATE)
#define Z_DIR_READ() bool(READ(Z_DIR_PIN))
#endif
#define Z_STEP_INIT() SET_OUTPUT(Z_STEP_PIN)
#ifndef Z_STEP_WRITE
#define Z_STEP_WRITE(STATE) WRITE(Z_STEP_PIN,STATE)
#endif
#define Z_STEP_READ() bool(READ(Z_STEP_PIN))
// X2 Stepper
#if HAS_X2_ENABLE
@ -201,6 +205,63 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define Z4_DIR_WRITE(STATE) NOOP
#endif
// I Stepper
#if LINEAR_AXES >= 4
#ifndef I_ENABLE_INIT
#define I_ENABLE_INIT() SET_OUTPUT(I_ENABLE_PIN)
#define I_ENABLE_WRITE(STATE) WRITE(I_ENABLE_PIN,STATE)
#define I_ENABLE_READ() bool(READ(I_ENABLE_PIN))
#endif
#ifndef I_DIR_INIT
#define I_DIR_INIT() SET_OUTPUT(I_DIR_PIN)
#define I_DIR_WRITE(STATE) WRITE(I_DIR_PIN,STATE)
#define I_DIR_READ() bool(READ(I_DIR_PIN))
#endif
#define I_STEP_INIT() SET_OUTPUT(I_STEP_PIN)
#ifndef I_STEP_WRITE
#define I_STEP_WRITE(STATE) WRITE(I_STEP_PIN,STATE)
#endif
#define I_STEP_READ() bool(READ(I_STEP_PIN))
#endif
// J Stepper
#if LINEAR_AXES >= 5
#ifndef J_ENABLE_INIT
#define J_ENABLE_INIT() SET_OUTPUT(J_ENABLE_PIN)
#define J_ENABLE_WRITE(STATE) WRITE(J_ENABLE_PIN,STATE)
#define J_ENABLE_READ() bool(READ(J_ENABLE_PIN))
#endif
#ifndef J_DIR_INIT
#define J_DIR_INIT() SET_OUTPUT(J_DIR_PIN)
#define J_DIR_WRITE(STATE) WRITE(J_DIR_PIN,STATE)
#define J_DIR_READ() bool(READ(J_DIR_PIN))
#endif
#define J_STEP_INIT() SET_OUTPUT(J_STEP_PIN)
#ifndef J_STEP_WRITE
#define J_STEP_WRITE(STATE) WRITE(J_STEP_PIN,STATE)
#endif
#define J_STEP_READ() bool(READ(J_STEP_PIN))
#endif
// K Stepper
#if LINEAR_AXES >= 6
#ifndef K_ENABLE_INIT
#define K_ENABLE_INIT() SET_OUTPUT(K_ENABLE_PIN)
#define K_ENABLE_WRITE(STATE) WRITE(K_ENABLE_PIN,STATE)
#define K_ENABLE_READ() bool(READ(K_ENABLE_PIN))
#endif
#ifndef K_DIR_INIT
#define K_DIR_INIT() SET_OUTPUT(K_DIR_PIN)
#define K_DIR_WRITE(STATE) WRITE(K_DIR_PIN,STATE)
#define K_DIR_READ() bool(READ(K_DIR_PIN))
#endif
#define K_STEP_INIT() SET_OUTPUT(K_STEP_PIN)
#ifndef K_STEP_WRITE
#define K_STEP_WRITE(STATE) WRITE(K_STEP_PIN,STATE)
#endif
#define K_STEP_READ() bool(READ(K_STEP_PIN))
#endif
// E0 Stepper
#ifndef E0_ENABLE_INIT
#define E0_ENABLE_INIT() SET_OUTPUT(E0_ENABLE_PIN)
@ -720,6 +781,51 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#endif
#endif
#ifndef ENABLE_STEPPER_I
#if HAS_I_ENABLE
#define ENABLE_STEPPER_I() I_ENABLE_WRITE( I_ENABLE_ON)
#else
#define ENABLE_STEPPER_I() NOOP
#endif
#endif
#ifndef DISABLE_STEPPER_I
#if HAS_I_ENABLE
#define DISABLE_STEPPER_I() I_ENABLE_WRITE(!I_ENABLE_ON)
#else
#define DISABLE_STEPPER_I() NOOP
#endif
#endif
#ifndef ENABLE_STEPPER_J
#if HAS_J_ENABLE
#define ENABLE_STEPPER_J() J_ENABLE_WRITE( J_ENABLE_ON)
#else
#define ENABLE_STEPPER_J() NOOP
#endif
#endif
#ifndef DISABLE_STEPPER_J
#if HAS_J_ENABLE
#define DISABLE_STEPPER_J() J_ENABLE_WRITE(!J_ENABLE_ON)
#else
#define DISABLE_STEPPER_J() NOOP
#endif
#endif
#ifndef ENABLE_STEPPER_K
#if HAS_K_ENABLE
#define ENABLE_STEPPER_K() K_ENABLE_WRITE( K_ENABLE_ON)
#else
#define ENABLE_STEPPER_K() NOOP
#endif
#endif
#ifndef DISABLE_STEPPER_K
#if HAS_K_ENABLE
#define DISABLE_STEPPER_K() K_ENABLE_WRITE(!K_ENABLE_ON)
#else
#define DISABLE_STEPPER_K() NOOP
#endif
#endif
#ifndef ENABLE_STEPPER_E0
#if HAS_E0_ENABLE
#define ENABLE_STEPPER_E0() E0_ENABLE_WRITE( E_ENABLE_ON)
@ -857,10 +963,22 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define ENABLE_AXIS_X() if (SHOULD_ENABLE(x)) { ENABLE_STEPPER_X(); ENABLE_STEPPER_X2(); AFTER_CHANGE(x, true); }
#define DISABLE_AXIS_X() if (SHOULD_DISABLE(x)) { DISABLE_STEPPER_X(); DISABLE_STEPPER_X2(); AFTER_CHANGE(x, false); set_axis_untrusted(X_AXIS); }
#define ENABLE_AXIS_Y() if (SHOULD_ENABLE(y)) { ENABLE_STEPPER_Y(); ENABLE_STEPPER_Y2(); AFTER_CHANGE(y, true); }
#define DISABLE_AXIS_Y() if (SHOULD_DISABLE(y)) { DISABLE_STEPPER_Y(); DISABLE_STEPPER_Y2(); AFTER_CHANGE(y, false); set_axis_untrusted(Y_AXIS); }
#define ENABLE_AXIS_Z() if (SHOULD_ENABLE(z)) { ENABLE_STEPPER_Z(); ENABLE_STEPPER_Z2(); ENABLE_STEPPER_Z3(); ENABLE_STEPPER_Z4(); AFTER_CHANGE(z, true); }
#define DISABLE_AXIS_Z() if (SHOULD_DISABLE(z)) { DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); AFTER_CHANGE(z, false); set_axis_untrusted(Z_AXIS); Z_RESET(); }
#if HAS_Y_AXIS
#define ENABLE_AXIS_Y() if (SHOULD_ENABLE(y)) { ENABLE_STEPPER_Y(); ENABLE_STEPPER_Y2(); AFTER_CHANGE(y, true); }
#define DISABLE_AXIS_Y() if (SHOULD_DISABLE(y)) { DISABLE_STEPPER_Y(); DISABLE_STEPPER_Y2(); AFTER_CHANGE(y, false); set_axis_untrusted(Y_AXIS); }
#else
#define ENABLE_AXIS_Y() NOOP
#define DISABLE_AXIS_Y() NOOP
#endif
#if HAS_Z_AXIS
#define ENABLE_AXIS_Z() if (SHOULD_ENABLE(z)) { ENABLE_STEPPER_Z(); ENABLE_STEPPER_Z2(); ENABLE_STEPPER_Z3(); ENABLE_STEPPER_Z4(); AFTER_CHANGE(z, true); }
#define DISABLE_AXIS_Z() if (SHOULD_DISABLE(z)) { DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); AFTER_CHANGE(z, false); set_axis_untrusted(Z_AXIS); Z_RESET(); }
#else
#define ENABLE_AXIS_Z() NOOP
#define DISABLE_AXIS_Z() NOOP
#endif
#ifdef Z_IDLE_HEIGHT
#define Z_RESET() do{ current_position.z = Z_IDLE_HEIGHT; sync_plan_position(); }while(0)
@ -868,6 +986,28 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define Z_RESET()
#endif
#if LINEAR_AXES >= 4
#define ENABLE_AXIS_I() if (SHOULD_ENABLE(i)) { ENABLE_STEPPER_I(); AFTER_CHANGE(i, true); }
#define DISABLE_AXIS_I() if (SHOULD_DISABLE(i)) { DISABLE_STEPPER_I(); AFTER_CHANGE(i, false); set_axis_untrusted(I_AXIS); }
#else
#define ENABLE_AXIS_I() NOOP
#define DISABLE_AXIS_I() NOOP
#endif
#if LINEAR_AXES >= 5
#define ENABLE_AXIS_J() if (SHOULD_ENABLE(j)) { ENABLE_STEPPER_J(); AFTER_CHANGE(j, true); }
#define DISABLE_AXIS_J() if (SHOULD_DISABLE(j)) { DISABLE_STEPPER_J(); AFTER_CHANGE(j, false); set_axis_untrusted(J_AXIS); }
#else
#define ENABLE_AXIS_J() NOOP
#define DISABLE_AXIS_J() NOOP
#endif
#if LINEAR_AXES >= 6
#define ENABLE_AXIS_K() if (SHOULD_ENABLE(k)) { ENABLE_STEPPER_K(); AFTER_CHANGE(k, true); }
#define DISABLE_AXIS_K() if (SHOULD_DISABLE(k)) { DISABLE_STEPPER_K(); AFTER_CHANGE(k, false); set_axis_untrusted(K_AXIS); }
#else
#define ENABLE_AXIS_K() NOOP
#define DISABLE_AXIS_K() NOOP
#endif
//
// Extruder steppers enable / disable macros
//

View File

@ -36,7 +36,7 @@
#include <SPI.h>
enum StealthIndex : uint8_t {
LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z)
LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K)
};
#define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE)
@ -97,6 +97,15 @@ enum StealthIndex : uint8_t {
#if AXIS_HAS_SPI(Z4)
TMC_SPI_DEFINE(Z4, Z);
#endif
#if AXIS_HAS_SPI(I)
TMC_SPI_DEFINE(I, I);
#endif
#if AXIS_HAS_SPI(J)
TMC_SPI_DEFINE(J, J);
#endif
#if AXIS_HAS_SPI(K)
TMC_SPI_DEFINE(K, K);
#endif
#if AXIS_HAS_SPI(E0)
TMC_SPI_DEFINE_E(0);
#endif
@ -329,6 +338,34 @@ enum StealthIndex : uint8_t {
#define Z4_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(I)
#ifdef I_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, I, I);
#define I_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, I, I);
#define I_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(J)
#ifdef J_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, J, J);
#define J_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, J, J);
#define J_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(K)
#ifdef K_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, K, K);
#define K_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, K, K);
#define K_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E0)
#ifdef E0_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 0);
@ -402,7 +439,9 @@ enum StealthIndex : uint8_t {
#endif
#endif
enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7, TOTAL };
#define _EN_ITEM(N) , E##N
enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
#undef _EN_ITEM
void tmc_serial_begin() {
#if HAS_TMC_HW_SERIAL
@ -474,6 +513,27 @@ enum StealthIndex : uint8_t {
stepperZ4.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(I)
#ifdef I_HARDWARE_SERIAL
HW_SERIAL_BEGIN(I);
#else
stepperI.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(J)
#ifdef J_HARDWARE_SERIAL
HW_SERIAL_BEGIN(J);
#else
stepperJ.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(K)
#ifdef K_HARDWARE_SERIAL
HW_SERIAL_BEGIN(K);
#else
stepperK.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E0)
#ifdef E0_HARDWARE_SERIAL
HW_SERIAL_BEGIN(E0);
@ -740,6 +800,15 @@ void restore_trinamic_drivers() {
#if AXIS_IS_TMC(Z4)
stepperZ4.push();
#endif
#if AXIS_IS_TMC(I)
stepperI.push();
#endif
#if AXIS_IS_TMC(J)
stepperJ.push();
#endif
#if AXIS_IS_TMC(K)
stepperK.push();
#endif
#if AXIS_IS_TMC(E0)
stepperE0.push();
#endif
@ -771,7 +840,10 @@ void reset_trinamic_drivers() {
ENABLED(STEALTHCHOP_E),
ENABLED(STEALTHCHOP_XY),
ENABLED(STEALTHCHOP_XY),
ENABLED(STEALTHCHOP_Z)
ENABLED(STEALTHCHOP_Z),
ENABLED(STEALTHCHOP_I),
ENABLED(STEALTHCHOP_J),
ENABLED(STEALTHCHOP_K)
);
#if AXIS_IS_TMC(X)
@ -798,6 +870,15 @@ void reset_trinamic_drivers() {
#if AXIS_IS_TMC(Z4)
TMC_INIT(Z4, STEALTH_AXIS_Z);
#endif
#if AXIS_IS_TMC(I)
TMC_INIT(I, STEALTH_AXIS_I);
#endif
#if AXIS_IS_TMC(J)
TMC_INIT(J, STEALTH_AXIS_J);
#endif
#if AXIS_IS_TMC(K)
TMC_INIT(K, STEALTH_AXIS_K);
#endif
#if AXIS_IS_TMC(E0)
TMC_INIT(E0, STEALTH_AXIS_E);
#endif
@ -848,6 +929,24 @@ void reset_trinamic_drivers() {
stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY));
#endif
#endif
#if I_SENSORLESS
stepperI.homing_threshold(I_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(I)
stepperI.homing_threshold(CAT(TERN(I_SENSORLESS, I, I), _STALL_SENSITIVITY));
#endif
#endif
#if J_SENSORLESS
stepperJ.homing_threshold(J_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(J)
stepperJ.homing_threshold(CAT(TERN(J_SENSORLESS, J, J), _STALL_SENSITIVITY));
#endif
#endif
#if K_SENSORLESS
stepperK.homing_threshold(K_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(K)
stepperK.homing_threshold(CAT(TERN(K_SENSORLESS, K, K), _STALL_SENSITIVITY));
#endif
#endif
#endif // USE SENSORLESS
#ifdef TMC_ADV

View File

@ -46,6 +46,10 @@
#define TMC_Y_LABEL 'Y', '0'
#define TMC_Z_LABEL 'Z', '0'
#define TMC_I_LABEL 'I', '0'
#define TMC_J_LABEL 'J', '0'
#define TMC_K_LABEL 'K', '0'
#define TMC_X2_LABEL 'X', '2'
#define TMC_Y2_LABEL 'Y', '2'
#define TMC_Z2_LABEL 'Z', '2'
@ -79,13 +83,22 @@ typedef struct {
#ifndef CHOPPER_TIMING_X
#define CHOPPER_TIMING_X CHOPPER_TIMING
#endif
#ifndef CHOPPER_TIMING_Y
#if HAS_Y_AXIS && !defined(CHOPPER_TIMING_Y)
#define CHOPPER_TIMING_Y CHOPPER_TIMING
#endif
#ifndef CHOPPER_TIMING_Z
#if HAS_Z_AXIS && !defined(CHOPPER_TIMING_Z)
#define CHOPPER_TIMING_Z CHOPPER_TIMING
#endif
#ifndef CHOPPER_TIMING_E
#if LINEAR_AXES >= 4 && !defined(CHOPPER_TIMING_I)
#define CHOPPER_TIMING_I CHOPPER_TIMING
#endif
#if LINEAR_AXES >= 5 && !defined(CHOPPER_TIMING_J)
#define CHOPPER_TIMING_J CHOPPER_TIMING
#endif
#if LINEAR_AXES >= 6 && !defined(CHOPPER_TIMING_K)
#define CHOPPER_TIMING_K CHOPPER_TIMING
#endif
#if HAS_EXTRUDERS && !defined(CHOPPER_TIMING_E)
#define CHOPPER_TIMING_E CHOPPER_TIMING
#endif
@ -225,6 +238,48 @@ void reset_trinamic_drivers();
#endif
#endif
// I Stepper
#if AXIS_IS_TMC(I)
extern TMC_CLASS(I, I) stepperI;
static constexpr chopper_timing_t chopper_timing_I = CHOPPER_TIMING_I;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define I_ENABLE_INIT() NOOP
#define I_ENABLE_WRITE(STATE) stepperI.toff((STATE)==I_ENABLE_ON ? chopper_timing.toff : 0)
#define I_ENABLE_READ() stepperI.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(I)
#define I_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(I_STEP_PIN); }while(0)
#endif
#endif
// J Stepper
#if AXIS_IS_TMC(J)
extern TMC_CLASS(J, J) stepperJ;
static constexpr chopper_timing_t chopper_timing_J = CHOPPER_TIMING_J;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define J_ENABLE_INIT() NOOP
#define J_ENABLE_WRITE(STATE) stepperJ.toff((STATE)==J_ENABLE_ON ? chopper_timing.toff : 0)
#define J_ENABLE_READ() stepperJ.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(J)
#define J_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(J_STEP_PIN); }while(0)
#endif
#endif
// K Stepper
#if AXIS_IS_TMC(K)
extern TMC_CLASS(K, K) stepperK;
static constexpr chopper_timing_t chopper_timing_K = CHOPPER_TIMING_K;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define K_ENABLE_INIT() NOOP
#define K_ENABLE_WRITE(STATE) stepperK.toff((STATE)==K_ENABLE_ON ? chopper_timing.toff : 0)
#define K_ENABLE_READ() stepperK.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(K)
#define K_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(K_STEP_PIN); }while(0)
#endif
#endif
// E0 Stepper
#if AXIS_IS_TMC(E0)
extern TMC_CLASS_E(0) stepperE0;

View File

@ -49,7 +49,9 @@
bool toolchange_extruder_ready[EXTRUDERS];
#endif
#if EITHER(MAGNETIC_PARKING_EXTRUDER, TOOL_SENSOR) || defined(EVENT_GCODE_AFTER_TOOLCHANGE) || (ENABLED(PARKING_EXTRUDER) && PARKING_EXTRUDER_SOLENOIDS_DELAY > 0)
#if EITHER(MAGNETIC_PARKING_EXTRUDER, TOOL_SENSOR) \
|| defined(EVENT_GCODE_TOOLCHANGE_T0) || defined(EVENT_GCODE_TOOLCHANGE_T1) || defined(EVENT_GCODE_AFTER_TOOLCHANGE) \
|| (ENABLED(PARKING_EXTRUDER) && PARKING_EXTRUDER_SOLENOIDS_DELAY > 0)
#include "../gcode/gcode.h"
#endif
@ -1311,10 +1313,22 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
TERN_(HAS_FANMUX, fanmux_switch(active_extruder));
#ifdef EVENT_GCODE_AFTER_TOOLCHANGE
if (!no_move && TERN1(DUAL_X_CARRIAGE, dual_x_carriage_mode == DXC_AUTO_PARK_MODE))
gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_AFTER_TOOLCHANGE));
#endif
if (!no_move) {
#ifdef EVENT_GCODE_TOOLCHANGE_T0
if (new_tool == 0)
gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_TOOLCHANGE_T0));
#endif
#ifdef EVENT_GCODE_TOOLCHANGE_T1
if (new_tool == 1)
gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_TOOLCHANGE_T1));
#endif
#ifdef EVENT_GCODE_AFTER_TOOLCHANGE
if (TERN1(DUAL_X_CARRIAGE, dual_x_carriage_mode == DXC_AUTO_PARK_MODE))
gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_AFTER_TOOLCHANGE));
#endif
}
SERIAL_ECHO_MSG(STR_ACTIVE_EXTRUDER, active_extruder);