Support for up to 9 axes (#23112, #24036, #24231)

This commit is contained in:
Scott Lahteine
2022-04-29 15:21:15 -05:00
parent 369542db3b
commit fd13a928c1
103 changed files with 4553 additions and 799 deletions

View File

@ -237,6 +237,9 @@ void home_delta() {
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));
TERN_(U_SENSORLESS, sensorless_t stealth_states_u = start_sensorless_homing_per_axis(U_AXIS));
TERN_(V_SENSORLESS, sensorless_t stealth_states_v = start_sensorless_homing_per_axis(V_AXIS));
TERN_(W_SENSORLESS, sensorless_t stealth_states_w = start_sensorless_homing_per_axis(W_AXIS));
#if SENSORLESS_STALLGUARD_DELAY
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
#endif
@ -256,6 +259,9 @@ void home_delta() {
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));
TERN_(U_SENSORLESS, end_sensorless_homing_per_axis(U_AXIS, stealth_states_u));
TERN_(V_SENSORLESS, end_sensorless_homing_per_axis(V_AXIS, stealth_states_v));
TERN_(W_SENSORLESS, end_sensorless_homing_per_axis(W_AXIS, stealth_states_w));
#if SENSORLESS_STALLGUARD_DELAY
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
#endif

View File

@ -322,6 +322,66 @@ void Endstops::init() {
#endif
#endif
#if HAS_U_MIN
#if ENABLED(ENDSTOPPULLUP_UMIN)
SET_INPUT_PULLUP(U_MIN_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_UMIN)
SET_INPUT_PULLDOWN(U_MIN_PIN);
#else
SET_INPUT(U_MIN_PIN);
#endif
#endif
#if HAS_U_MAX
#if ENABLED(ENDSTOPPULLUP_UMAX)
SET_INPUT_PULLUP(U_MAX_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_UMIN)
SET_INPUT_PULLDOWN(U_MAX_PIN);
#else
SET_INPUT(U_MAX_PIN);
#endif
#endif
#if HAS_V_MIN
#if ENABLED(ENDSTOPPULLUP_VMIN)
SET_INPUT_PULLUP(V_MIN_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_VMIN)
SET_INPUT_PULLDOWN(V_MIN_PIN);
#else
SET_INPUT(V_MIN_PIN);
#endif
#endif
#if HAS_V_MAX
#if ENABLED(ENDSTOPPULLUP_VMAX)
SET_INPUT_PULLUP(V_MAX_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_VMIN)
SET_INPUT_PULLDOWN(V_MAX_PIN);
#else
SET_INPUT(V_MAX_PIN);
#endif
#endif
#if HAS_W_MIN
#if ENABLED(ENDSTOPPULLUP_WMIN)
SET_INPUT_PULLUP(W_MIN_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_WMIN)
SET_INPUT_PULLDOWN(W_MIN_PIN);
#else
SET_INPUT(W_MIN_PIN);
#endif
#endif
#if HAS_W_MAX
#if ENABLED(ENDSTOPPULLUP_WMAX)
SET_INPUT_PULLUP(W_MAX_PIN);
#elif ENABLED(ENDSTOPPULLDOWN_WMIN)
SET_INPUT_PULLDOWN(W_MAX_PIN);
#else
SET_INPUT(W_MAX_PIN);
#endif
#endif
#if PIN_EXISTS(CALIBRATION)
#if ENABLED(CALIBRATION_PIN_PULLUP)
SET_INPUT_PULLUP(CALIBRATION_PIN);
@ -427,7 +487,7 @@ void Endstops::event_handler() {
prev_hit_state = hit_state;
if (hit_state) {
#if HAS_STATUS_MESSAGE
char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' '),
char NUM_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' ', chrU = ' ', chrV = ' ', chrW = ' '),
chrP = ' ';
#define _SET_STOP_CHAR(A,C) (chr## A = C)
#else
@ -447,16 +507,22 @@ void Endstops::event_handler() {
#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')
#define ENDSTOP_HIT_TEST_U() _ENDSTOP_HIT_TEST(U,'U')
#define ENDSTOP_HIT_TEST_V() _ENDSTOP_HIT_TEST(V,'V')
#define ENDSTOP_HIT_TEST_W() _ENDSTOP_HIT_TEST(W,'W')
SERIAL_ECHO_START();
SERIAL_ECHOPGM(STR_ENDSTOPS_HIT);
LINEAR_AXIS_CODE(
NUM_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')
_ENDSTOP_HIT_TEST(K,'K'),
_ENDSTOP_HIT_TEST(U,'U'),
_ENDSTOP_HIT_TEST(V,'V'),
_ENDSTOP_HIT_TEST(W,'W')
);
#if USES_Z_MIN_PROBE_PIN
@ -467,9 +533,9 @@ void Endstops::event_handler() {
TERN_(HAS_STATUS_MESSAGE,
ui.status_printf(0,
F(S_FMT GANG_N_1(LINEAR_AXES, " %c") " %c"),
F(S_FMT GANG_N_1(NUM_AXES, " %c") " %c"),
GET_TEXT(MSG_LCD_ENDSTOPS),
LINEAR_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK), chrP
NUM_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK, chrU, chrV, chrW), chrP
)
);
@ -567,6 +633,24 @@ void __O2 Endstops::report_states() {
#if HAS_K_MAX
ES_REPORT(K_MAX);
#endif
#if HAS_U_MIN
ES_REPORT(U_MIN);
#endif
#if HAS_U_MAX
ES_REPORT(U_MAX);
#endif
#if HAS_V_MIN
ES_REPORT(V_MIN);
#endif
#if HAS_V_MAX
ES_REPORT(V_MAX);
#endif
#if HAS_W_MIN
ES_REPORT(W_MIN);
#endif
#if HAS_W_MAX
ES_REPORT(W_MAX);
#endif
#if ENABLED(PROBE_ACTIVATION_SWITCH)
print_es_state(probe_switch_activated(), F(STR_PROBE_EN));
#endif
@ -652,6 +736,9 @@ void Endstops::update() {
#define I_AXIS_HEAD I_AXIS
#define J_AXIS_HEAD J_AXIS
#define K_AXIS_HEAD K_AXIS
#define U_AXIS_HEAD U_AXIS
#define V_AXIS_HEAD V_AXIS
#define W_AXIS_HEAD W_AXIS
/**
* Check and update endstops
@ -838,6 +925,82 @@ void Endstops::update() {
#endif
#endif
#if HAS_U_MIN && !U_SPI_SENSORLESS
#if ENABLED(U_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(U, MIN);
#if HAS_U2_MIN
UPDATE_ENDSTOP_BIT(U2, MIN);
#else
COPY_LIVE_STATE(U_MIN, U2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(U, MIN);
#endif
#endif
#if HAS_U_MAX && !U_SPI_SENSORLESS
#if ENABLED(U_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(U, MAX);
#if HAS_U2_MAX
UPDATE_ENDSTOP_BIT(U2, MAX);
#else
COPY_LIVE_STATE(U_MAX, U2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(U, MAX);
#endif
#endif
#if HAS_V_MIN && !V_SPI_SENSORLESS
#if ENABLED(V_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(V, MIN);
#if HAS_V2_MIN
UPDATE_ENDSTOP_BIT(V2, MIN);
#else
COPY_LIVE_STATE(V_MIN, V2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(V, MIN);
#endif
#endif
#if HAS_V_MAX && !V_SPI_SENSORLESS
#if ENABLED(O_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(V, MAX);
#if HAS_V2_MAX
UPDATE_ENDSTOP_BIT(V2, MAX);
#else
COPY_LIVE_STATE(V_MAX, V2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(V, MAX);
#endif
#endif
#if HAS_W_MIN && !W_SPI_SENSORLESS
#if ENABLED(W_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(W, MIN);
#if HAS_W2_MIN
UPDATE_ENDSTOP_BIT(W2, MIN);
#else
COPY_LIVE_STATE(W_MIN, W2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(W, MIN);
#endif
#endif
#if HAS_W_MAX && !W_SPI_SENSORLESS
#if ENABLED(W_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(W, MAX);
#if HAS_W2_MAX
UPDATE_ENDSTOP_BIT(W2, MAX);
#else
COPY_LIVE_STATE(W_MAX, W2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(W, MAX);
#endif
#endif
#if ENDSTOP_NOISE_THRESHOLD
/**
@ -938,7 +1101,7 @@ void Endstops::update() {
#define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX)
#endif
#if HAS_G38_PROBE
#if HAS_G38_PROBE // TODO (DerAndere): Add support for HAS_I_AXIS
#define _G38_OPEN_STATE TERN(G38_PROBE_AWAY, (G38_move >= 4), LOW)
// For G38 moves check the probe's pin for ALL movement
if (G38_move && TEST_ENDSTOP(_ENDSTOP(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN))) != _G38_OPEN_STATE) {
@ -1108,6 +1271,51 @@ void Endstops::update() {
}
}
#endif
#if HAS_U_AXIS
if (stepper.axis_is_moving(U_AXIS)) {
if (stepper.motor_direction(U_AXIS_HEAD)) { // -direction
#if HAS_U_MIN || (U_SPI_SENSORLESS && U_HOME_TO_MIN)
PROCESS_ENDSTOP(U, MIN);
#endif
}
else { // +direction
#if HAS_U_MAX || (U_SPI_SENSORLESS && U_HOME_TO_MAX)
PROCESS_ENDSTOP(U, MAX);
#endif
}
}
#endif
#if HAS_V_AXIS
if (stepper.axis_is_moving(V_AXIS)) {
if (stepper.motor_direction(V_AXIS_HEAD)) { // -direction
#if HAS_V_MIN || (V_SPI_SENSORLESS && V_HOME_TO_MIN)
PROCESS_ENDSTOP(V, MIN);
#endif
}
else { // +direction
#if HAS_V_MAX || (V_SPI_SENSORLESS && V_HOME_TO_MAX)
PROCESS_ENDSTOP(V, MAX);
#endif
}
}
#endif
#if HAS_W_AXIS
if (stepper.axis_is_moving(W_AXIS)) {
if (stepper.motor_direction(W_AXIS_HEAD)) { // -direction
#if HAS_W_MIN || (W_SPI_SENSORLESS && W_HOME_TO_MIN)
PROCESS_ENDSTOP(W, MIN);
#endif
}
else { // +direction
#if HAS_W_MAX || (W_SPI_SENSORLESS && W_HOME_TO_MAX)
PROCESS_ENDSTOP(W, MAX);
#endif
}
}
#endif
} // Endstops::update()
#if ENABLED(SPI_ENDSTOPS)
@ -1169,6 +1377,24 @@ void Endstops::update() {
hit = true;
}
#endif
#if U_SPI_SENSORLESS
if (tmc_spi_homing.u && stepperU.test_stall_status()) {
SBI(live_state, U_ENDSTOP);
hit = true;
}
#endif
#if V_SPI_SENSORLESS
if (tmc_spi_homing.v && stepperV.test_stall_status()) {
SBI(live_state, V_ENDSTOP);
hit = true;
}
#endif
#if W_SPI_SENSORLESS
if (tmc_spi_homing.w && stepperW.test_stall_status()) {
SBI(live_state, W_ENDSTOP);
hit = true;
}
#endif
if (TERN0(ENDSTOP_INTERRUPTS_FEATURE, hit)) update();
@ -1182,6 +1408,9 @@ void Endstops::update() {
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));
TERN_(U_SPI_SENSORLESS, CBI(live_state, U_ENDSTOP));
TERN_(V_SPI_SENSORLESS, CBI(live_state, V_ENDSTOP));
TERN_(W_SPI_SENSORLESS, CBI(live_state, W_ENDSTOP));
}
#endif // SPI_ENDSTOPS
@ -1276,6 +1505,24 @@ void Endstops::update() {
#if HAS_K_MIN
ES_GET_STATE(K_MIN);
#endif
#if HAS_U_MAX
ES_GET_STATE(U_MAX);
#endif
#if HAS_U_MIN
ES_GET_STATE(U_MIN);
#endif
#if HAS_V_MAX
ES_GET_STATE(V_MAX);
#endif
#if HAS_V_MIN
ES_GET_STATE(V_MIN);
#endif
#if HAS_W_MAX
ES_GET_STATE(W_MAX);
#endif
#if HAS_W_MIN
ES_GET_STATE(W_MIN);
#endif
uint16_t endstop_change = live_state_local ^ old_live_state_local;
#define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPGM(" " STRINGIFY(S) ":", TEST(live_state_local, S))
@ -1350,6 +1597,25 @@ void Endstops::update() {
#if HAS_K_MAX
ES_REPORT_CHANGE(K_MAX);
#endif
#if HAS_U_MIN
ES_REPORT_CHANGE(U_MIN);
#endif
#if HAS_U_MAX
ES_REPORT_CHANGE(U_MAX);
#endif
#if HAS_V_MIN
ES_REPORT_CHANGE(V_MIN);
#endif
#if HAS_V_MAX
ES_REPORT_CHANGE(V_MAX);
#endif
#if HAS_W_MIN
ES_REPORT_CHANGE(W_MIN);
#endif
#if HAS_W_MAX
ES_REPORT_CHANGE(W_MAX);
#endif
SERIAL_ECHOLNPGM("\n");
hal.set_pwm_duty(pin_t(LED_PIN), local_LED_status);
local_LED_status ^= 255;

View File

@ -45,6 +45,12 @@ enum EndstopEnum : char {
_ES_ITEM(HAS_J_MAX, J_MAX)
_ES_ITEM(HAS_K_MIN, K_MIN)
_ES_ITEM(HAS_K_MAX, K_MAX)
_ES_ITEM(HAS_U_MIN, U_MIN)
_ES_ITEM(HAS_U_MAX, U_MAX)
_ES_ITEM(HAS_V_MIN, V_MIN)
_ES_ITEM(HAS_V_MAX, V_MAX)
_ES_ITEM(HAS_W_MIN, W_MIN)
_ES_ITEM(HAS_W_MAX, W_MAX)
// Extra Endstops for XYZ
#if ENABLED(X_DUAL_ENDSTOPS)
@ -234,7 +240,7 @@ class Endstops {
typedef struct {
union {
bool any;
struct { bool LINEAR_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); };
struct { bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); };
};
} tmc_spi_homing_t;
static tmc_spi_homing_t tmc_spi_homing;

View File

@ -84,7 +84,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, I_HOME_POS, J_HOME_POS, K_HOME_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, U_HOME_POS, V_HOME_POS, W_HOME_POS);
/**
* Cartesian Destination
@ -189,13 +189,16 @@ inline void report_more_positions() {
inline void report_logical_position(const xyze_pos_t &rpos) {
const xyze_pos_t lpos = rpos.asLogical();
SERIAL_ECHOPGM_P(
LIST_N(DOUBLE(LINEAR_AXES),
LIST_N(DOUBLE(NUM_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
SP_K_LBL, lpos.k,
SP_U_LBL, lpos.u,
SP_V_LBL, lpos.v,
SP_W_LBL, lpos.w
)
#if HAS_EXTRUDERS
, SP_E_LBL, lpos.e
@ -210,7 +213,8 @@ void report_real_position() {
xyze_pos_t npos = LOGICAL_AXIS_ARRAY(
planner.get_axis_position_mm(E_AXIS),
cartes.x, cartes.y, cartes.z,
cartes.i, cartes.j, cartes.k
cartes.i, cartes.j, cartes.k,
cartes.u, cartes.v, cartes.w
);
TERN_(HAS_POSITION_MODIFIERS, planner.unapply_modifiers(npos, true));
@ -257,13 +261,16 @@ void report_current_position_projected() {
const xyz_pos_t lpos = cartes.asLogical();
SERIAL_ECHOPGM_P(
LIST_N(DOUBLE(LINEAR_AXES),
LIST_N(DOUBLE(NUM_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
SP_K_LBL, lpos.k,
SP_U_LBL, lpos.u,
SP_V_LBL, lpos.v,
SP_W_LBL, lpos.w
)
#if HAS_EXTRUDERS
, SP_E_LBL, current_position.e
@ -354,13 +361,16 @@ void get_cartesian_from_steppers() {
);
cartes.z = planner.get_axis_position_mm(Z_AXIS);
#else
LINEAR_AXIS_CODE(
NUM_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)
cartes.k = planner.get_axis_position_mm(K_AXIS),
cartes.u = planner.get_axis_position_mm(U_AXIS),
cartes.v = planner.get_axis_position_mm(V_AXIS),
cartes.w = planner.get_axis_position_mm(W_AXIS)
);
#endif
}
@ -467,24 +477,23 @@ void _internal_move_to_destination(const_feedRate_t fr_mm_s/*=0.0f*/
* - 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_ARGS(const float), const_feedRate_t fr_mm_s/*=0.0f*/) {
void do_blocking_move_to(NUM_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_ARGS());
if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", NUM_AXIS_ARGS());
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 HAS_I_AXIS
const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS);
#endif
#if HAS_J_AXIS
const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS);
#endif
#if HAS_K_AXIS
const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS);
#endif
SECONDARY_AXIS_CODE(
const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS),
const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS),
const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS),
const feedRate_t u_feedrate = fr_mm_s ?: homing_feedrate(U_AXIS),
const feedRate_t v_feedrate = fr_mm_s ?: homing_feedrate(V_AXIS),
const feedRate_t w_feedrate = fr_mm_s ?: homing_feedrate(W_AXIS)
);
#if IS_KINEMATIC
if (!position_is_reachable(x, y)) return;
@ -553,7 +562,18 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s
#if HAS_K_AXIS
current_position.k = k; line_to_current_position(k_feedrate);
#endif
#if HAS_Z_AXIS // If Z needs to lower, do it after moving XY...
#if HAS_U_AXIS
current_position.u = u; line_to_current_position(u_feedrate);
#endif
#if HAS_V_AXIS
current_position.v = v; line_to_current_position(v_feedrate);
#endif
#if HAS_W_AXIS
current_position.w = w; line_to_current_position(w_feedrate);
#endif
#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
@ -563,17 +583,19 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s
}
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, current_position.j, current_position.k), fr_mm_s);
do_blocking_move_to(NUM_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i, current_position.j, current_position.k,
current_position.u, current_position.v, current_position.w), 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_ELEM(raw), fr_mm_s);
do_blocking_move_to(NUM_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_ELEM(raw), fr_mm_s);
do_blocking_move_to(NUM_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, current_position.i, current_position.j, current_position.k),
NUM_AXIS_LIST(rx, current_position.y, current_position.z, current_position.i, current_position.j, current_position.k,
current_position.u, current_position.v, current_position.w),
fr_mm_s
);
}
@ -581,7 +603,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
#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),
NUM_AXIS_LIST(current_position.x, ry, current_position.z, current_position.i, current_position.j, current_position.k,
current_position.u, current_position.v, current_position.w),
fr_mm_s
);
}
@ -599,7 +622,7 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
}
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(
LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, i, raw.j, raw.k),
NUM_AXIS_LIST(raw.x, raw.y, raw.z, i, raw.j, raw.k, raw.u, raw.v, raw.w),
fr_mm_s
);
}
@ -611,7 +634,7 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
}
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(
LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, j, raw.k),
NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, j, raw.k, raw.u, raw.v, raw.w),
fr_mm_s
);
}
@ -623,7 +646,43 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
}
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(
LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, k),
NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, k, raw.u, raw.v, raw.w),
fr_mm_s
);
}
#endif
#if HAS_U_AXIS
void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xyzijk_u(current_position, ru, fr_mm_s);
}
void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(
NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, u, raw.v, raw.w),
fr_mm_s
);
}
#endif
#if HAS_V_AXIS
void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xyzijku_v(current_position, rv, fr_mm_s);
}
void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(
NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, raw.u, v, raw.w),
fr_mm_s
);
}
#endif
#if HAS_W_AXIS
void do_blocking_move_to_w(const_float_t rw, const_feedRate_t fr_mm_s/*=0.0*/) {
do_blocking_move_to_xyzijkuv_w(current_position, rw, fr_mm_s);
}
void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const_float_t w, const_feedRate_t fr_mm_s/*=0.0f*/) {
do_blocking_move_to(
NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, raw.u, raw.v, w),
fr_mm_s
);
}
@ -632,7 +691,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
#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),
NUM_AXIS_LIST(rx, ry, current_position.z, current_position.i, current_position.j, current_position.k,
current_position.u, current_position.v, current_position.w),
fr_mm_s
);
}
@ -644,7 +704,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
#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),
NUM_AXIS_LIST(raw.x, raw.y, z, current_position.i, current_position.j, current_position.k,
current_position.u, current_position.v, current_position.w),
fr_mm_s
);
}
@ -679,8 +740,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, 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)
NUM_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS, I_MIN_POS, J_MIN_POS, K_MIN_POS, U_MIN_POS, V_MIN_POS, W_MIN_POS),
NUM_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS, I_MAX_POS, J_MAX_POS, K_MAX_POS, U_MAX_POS, V_MAX_POS, W_MAX_POS)
};
/**
@ -859,6 +920,36 @@ void restore_feedrate_and_scaling() {
#endif
}
#endif
#if HAS_U_AXIS
if (axis_was_homed(U_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_U)
NOLESS(target.u, soft_endstop.min.u);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_U)
NOMORE(target.u, soft_endstop.max.u);
#endif
}
#endif
#if HAS_V_AXIS
if (axis_was_homed(V_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_V)
NOLESS(target.v, soft_endstop.min.v);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_V)
NOMORE(target.v, soft_endstop.max.v);
#endif
}
#endif
#if HAS_W_AXIS
if (axis_was_homed(W_AXIS)) {
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_W)
NOLESS(target.w, soft_endstop.min.w);
#endif
#if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_W)
NOMORE(target.w, soft_endstop.max.w);
#endif
}
#endif
}
#else // !HAS_SOFTWARE_ENDSTOPS
@ -1297,9 +1388,10 @@ void prepare_line_to_destination() {
CBI(b, a);
};
// Clear test bits that are trusted
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
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)
set_should(axis_bits, I_AXIS), set_should(axis_bits, J_AXIS), set_should(axis_bits, K_AXIS),
set_should(axis_bits, U_AXIS), set_should(axis_bits, V_AXIS), set_should(axis_bits, W_AXIS)
);
return axis_bits;
}
@ -1309,13 +1401,16 @@ void prepare_line_to_destination() {
PGM_P home_first = GET_TEXT(MSG_HOME_FIRST);
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" : "",
NUM_AXIS_LIST(
TEST(axis_bits, X_AXIS) ? STR_A : "",
TEST(axis_bits, Y_AXIS) ? STR_B : "",
TEST(axis_bits, Z_AXIS) ? STR_C : "",
TEST(axis_bits, I_AXIS) ? STR_I : "",
TEST(axis_bits, J_AXIS) ? STR_J : "",
TEST(axis_bits, K_AXIS) ? STR_K : ""
TEST(axis_bits, K_AXIS) ? STR_K : "",
TEST(axis_bits, U_AXIS) ? STR_U : "",
TEST(axis_bits, V_AXIS) ? STR_V : "",
TEST(axis_bits, W_AXIS) ? STR_W : ""
)
);
SERIAL_ECHO_START();
@ -1395,6 +1490,15 @@ void prepare_line_to_destination() {
#if K_SENSORLESS
case K_AXIS: stealth_states.k = tmc_enable_stallguard(stepperK); break;
#endif
#if U_SENSORLESS
case U_AXIS: stealth_states.u = tmc_enable_stallguard(stepperU); break;
#endif
#if V_SENSORLESS
case V_AXIS: stealth_states.v = tmc_enable_stallguard(stepperV); break;
#endif
#if W_SENSORLESS
case W_AXIS: stealth_states.w = tmc_enable_stallguard(stepperW); break;
#endif
}
#if ENABLED(SPI_ENDSTOPS)
@ -1415,6 +1519,15 @@ void prepare_line_to_destination() {
#if HAS_K_AXIS
case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = true; break;
#endif
#if HAS_U_AXIS
case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = true; break;
#endif
#if HAS_V_AXIS
case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = true; break;
#endif
#if HAS_W_AXIS
case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = true; break;
#endif
default: break;
}
#endif
@ -1471,6 +1584,15 @@ void prepare_line_to_destination() {
#if K_SENSORLESS
case K_AXIS: tmc_disable_stallguard(stepperK, enable_stealth.k); break;
#endif
#if U_SENSORLESS
case U_AXIS: tmc_disable_stallguard(stepperU, enable_stealth.u); break;
#endif
#if V_SENSORLESS
case V_AXIS: tmc_disable_stallguard(stepperV, enable_stealth.v); break;
#endif
#if W_SENSORLESS
case W_AXIS: tmc_disable_stallguard(stepperW, enable_stealth.w); break;
#endif
}
#if ENABLED(SPI_ENDSTOPS)
@ -1491,6 +1613,15 @@ void prepare_line_to_destination() {
#if HAS_K_AXIS
case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = false; break;
#endif
#if HAS_U_AXIS
case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = false; break;
#endif
#if HAS_V_AXIS
case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = false; break;
#endif
#if HAS_W_AXIS
case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = false; break;
#endif
default: break;
}
#endif
@ -1677,6 +1808,30 @@ void prepare_line_to_destination() {
stepperBackoutDir = IF_DISABLED(INVERT_K_DIR, -)effectorBackoutDir;
break;
#endif
#ifdef U_MICROSTEPS
case U_AXIS:
phasePerUStep = PHASE_PER_MICROSTEP(U);
phaseCurrent = stepperU.get_microstep_counter();
effectorBackoutDir = -U_HOME_DIR;
stepperBackoutDir = IF_DISABLED(INVERT_U_DIR, -)effectorBackoutDir;
break;
#endif
#ifdef V_MICROSTEPS
case V_AXIS:
phasePerUStep = PHASE_PER_MICROSTEP(V);
phaseCurrent = stepperV.get_microstep_counter();
effectorBackoutDir = -V_HOME_DIR;
stepperBackoutDir = IF_DISABLED(INVERT_V_DIR, -)effectorBackoutDir;
break;
#endif
#ifdef W_MICROSTEPS
case W_AXIS:
phasePerUStep = PHASE_PER_MICROSTEP(W);
phaseCurrent = stepperW.get_microstep_counter();
effectorBackoutDir = -W_HOME_DIR;
stepperBackoutDir = IF_DISABLED(INVERT_W_DIR, -)effectorBackoutDir;
break;
#endif
default: return;
}
@ -1733,13 +1888,16 @@ void prepare_line_to_destination() {
|| TERN0(A##_HOME_TO_MIN, A##_MIN_PIN > -1) \
|| TERN0(A##_HOME_TO_MAX, A##_MAX_PIN > -1) \
))
if (LINEAR_AXIS_GANG(
if (NUM_AXIS_GANG(
!_CAN_HOME(X),
&& !_CAN_HOME(Y),
&& !_CAN_HOME(Z),
&& !_CAN_HOME(I),
&& !_CAN_HOME(J),
&& !_CAN_HOME(K))
&& !_CAN_HOME(K),
&& !_CAN_HOME(U),
&& !_CAN_HOME(V),
&& !_CAN_HOME(W))
) return;
#endif
@ -1832,6 +1990,15 @@ void prepare_line_to_destination() {
#if HAS_K_AXIS
case K_AXIS: es = K_ENDSTOP; break;
#endif
#if HAS_U_AXIS
case U_AXIS: es = U_ENDSTOP; break;
#endif
#if HAS_V_AXIS
case V_AXIS: es = V_ENDSTOP; break;
#endif
#if HAS_W_AXIS
case W_AXIS: es = W_ENDSTOP; break;
#endif
}
if (TEST(endstops.state(), es)) {
SERIAL_ECHO_MSG("Bad ", AS_CHAR(AXIS_CHAR(axis)), " Endstop?");

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]; // TODO: Add support for LINEAR_AXES >= 4
extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for HAS_I_AXIS
extern xyze_pos_t stored_position[SAVED_POSITIONS];
#endif
@ -77,13 +77,16 @@ constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M;
FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) {
float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z);
#if DISABLED(DELTA)
LINEAR_AXIS_CODE(
NUM_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
else if (a == K_AXIS) v = homing_feedrate_mm_m.k,
else if (a == U_AXIS) v = homing_feedrate_mm_m.u,
else if (a == V_AXIS) v = homing_feedrate_mm_m.v,
else if (a == W_AXIS) v = homing_feedrate_mm_m.w
);
#endif
return MMM_TO_MMS(v);
@ -124,7 +127,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, I_##OPT, J_##OPT, K_##OPT); \
static const XYZval<T> NAME##_P DEFS_PROGMEM = NUM_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT, U_##OPT, V_##OPT, W_##OPT); \
return pgm_read_any(&NAME##_P[axis]); \
}
XYZ_DEFS(float, base_min_pos, MIN_POS);
@ -198,6 +201,24 @@ inline float home_bump_mm(const AxisEnum axis) {
TERN_(MIN_SOFTWARE_ENDSTOP_K, amax = max.k);
break;
#endif
#if HAS_U_AXIS
case U_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_U, amin = min.u);
TERN_(MIN_SOFTWARE_ENDSTOP_U, amax = max.u);
break;
#endif
#if HAS_V_AXIS
case V_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_V, amin = min.v);
TERN_(MIN_SOFTWARE_ENDSTOP_V, amax = max.v);
break;
#endif
#if HAS_W_AXIS
case W_AXIS:
TERN_(MIN_SOFTWARE_ENDSTOP_W, amin = min.w);
TERN_(MIN_SOFTWARE_ENDSTOP_W, amax = max.w);
break;
#endif
default: break;
}
#endif
@ -323,7 +344,7 @@ 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_ARGS(const float), const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to(NUM_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);
@ -347,6 +368,18 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s=0.0f);
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
#if HAS_U_AXIS
void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s=0.0f);
#endif
#if HAS_V_AXIS
void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s=0.0f);
void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s=0.0f);
#endif
#if HAS_W_AXIS
void do_blocking_move_to_w(const float rw, const feedRate_t &fr_mm_s=0.0f);
void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const float w, const feedRate_t &fr_mm_s=0.0f);
#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.0f);
@ -374,8 +407,8 @@ void restore_feedrate_and_scaling();
/**
* Homing and Trusted Axes
*/
typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t;
constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1;
typedef IF<(NUM_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t;
constexpr linear_axis_bits_t linear_bits = _BV(NUM_AXES) - 1;
void set_axis_is_at_home(const AxisEnum axis);
@ -490,6 +523,18 @@ void home_if_needed(const bool keeplev=false);
#define LOGICAL_K_POSITION(POS) NATIVE_TO_LOGICAL(POS, K_AXIS)
#define RAW_K_POSITION(POS) LOGICAL_TO_NATIVE(POS, K_AXIS)
#endif
#if HAS_U_AXIS
#define LOGICAL_U_POSITION(POS) NATIVE_TO_LOGICAL(POS, U_AXIS)
#define RAW_U_POSITION(POS) LOGICAL_TO_NATIVE(POS, U_AXIS)
#endif
#if HAS_V_AXIS
#define LOGICAL_V_POSITION(POS) NATIVE_TO_LOGICAL(POS, V_AXIS)
#define RAW_V_POSITION(POS) LOGICAL_TO_NATIVE(POS, V_AXIS)
#endif
#if HAS_W_AXIS
#define LOGICAL_W_POSITION(POS) NATIVE_TO_LOGICAL(POS, W_AXIS)
#define RAW_W_POSITION(POS) LOGICAL_TO_NATIVE(POS, W_AXIS)
#endif
/**
* position_is_reachable family of functions

View File

@ -1300,7 +1300,7 @@ void Planner::recalculate() {
*/
void Planner::check_axes_activity() {
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_E)
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_U, DISABLE_V, DISABLE_W, DISABLE_E)
xyze_bool_t axis_active = { false };
#endif
@ -1350,7 +1350,10 @@ void Planner::check_axes_activity() {
if (TERN0(DISABLE_Z, bnext->steps.z)) axis_active.z = true,
if (TERN0(DISABLE_I, bnext->steps.i)) axis_active.i = true,
if (TERN0(DISABLE_J, bnext->steps.j)) axis_active.j = true,
if (TERN0(DISABLE_K, bnext->steps.k)) axis_active.k = true
if (TERN0(DISABLE_K, bnext->steps.k)) axis_active.k = true,
if (TERN0(DISABLE_U, bnext->steps.u)) axis_active.u = true,
if (TERN0(DISABLE_V, bnext->steps.v)) axis_active.v = true,
if (TERN0(DISABLE_W, bnext->steps.w)) axis_active.w = true
);
}
#endif
@ -1385,7 +1388,10 @@ void Planner::check_axes_activity() {
if (TERN0(DISABLE_Z, !axis_active.z)) stepper.disable_axis(Z_AXIS),
if (TERN0(DISABLE_I, !axis_active.i)) stepper.disable_axis(I_AXIS),
if (TERN0(DISABLE_J, !axis_active.j)) stepper.disable_axis(J_AXIS),
if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS)
if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS),
if (TERN0(DISABLE_U, !axis_active.u)) stepper.disable_axis(U_AXIS),
if (TERN0(DISABLE_V, !axis_active.v)) stepper.disable_axis(V_AXIS),
if (TERN0(DISABLE_W, !axis_active.w)) stepper.disable_axis(W_AXIS)
);
//
@ -1453,7 +1459,7 @@ void Planner::check_axes_activity() {
float high = 0.0f;
for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
const block_t * const block = &block_buffer[b];
if (LINEAR_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k)) {
if (NUM_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k, || block->steps.u, || block->steps.v, || block->steps.w)) {
const float se = (float)block->steps.e / block->step_event_count * SQRT(block->nominal_speed_sqr); // mm/sec;
NOLESS(high, se);
}
@ -1843,15 +1849,22 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
dc = target.c - position.c,
di = target.i - position.i,
dj = target.j - position.j,
dk = target.k - position.k
dk = target.k - position.k,
du = target.u - position.u,
dv = target.v - position.v,
dw = target.w - position.w
);
/* <-- add a slash to enable
SERIAL_ECHOLNPGM(
" _populate_block FR:", fr_mm_s,
" A:", target.a, " (", da, " steps)"
" B:", target.b, " (", db, " steps)"
" C:", target.c, " (", dc, " steps)"
#if HAS_Y_AXIS
" B:", target.b, " (", db, " steps)"
#endif
#if HAS_Z_AXIS
" C:", target.c, " (", dc, " steps)"
#endif
#if HAS_I_AXIS
" " STR_I ":", target.i, " (", di, " steps)"
#endif
@ -1861,6 +1874,14 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#if HAS_K_AXIS
" " STR_K ":", target.k, " (", dk, " steps)"
#endif
#if HAS_U_AXIS
" " STR_U ":", target.u, " (", du, " steps)"
#endif
#if HAS_V_AXIS
" " STR_V ":", target.v, " (", dv, " steps)"
#endif
#if HAS_W_AXIS
" " STR_W ":", target.w, " (", dw, " steps)"
#if HAS_EXTRUDERS
" E:", target.e, " (", de, " steps)"
#endif
@ -1925,15 +1946,6 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
if (db + dc < 0) SBI(dm, B_AXIS); // Motor B direction
if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
#endif
#if HAS_I_AXIS
if (di < 0) SBI(dm, I_AXIS);
#endif
#if HAS_J_AXIS
if (dj < 0) SBI(dm, J_AXIS);
#endif
#if HAS_K_AXIS
if (dk < 0) SBI(dm, K_AXIS);
#endif
#elif ENABLED(MARKFORGED_XY)
if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction
if (db < 0) SBI(dm, B_AXIS); // Motor B direction
@ -1941,16 +1953,22 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
if (da < 0) SBI(dm, A_AXIS); // Motor A direction
if (db + da < 0) SBI(dm, B_AXIS); // Motor B direction
#else
LINEAR_AXIS_CODE(
XYZ_CODE(
if (da < 0) SBI(dm, X_AXIS),
if (db < 0) SBI(dm, Y_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)
if (dc < 0) SBI(dm, Z_AXIS)
);
#endif
SECONDARY_AXIS_CODE(
if (di < 0) SBI(dm, I_AXIS),
if (dj < 0) SBI(dm, J_AXIS),
if (dk < 0) SBI(dm, K_AXIS),
if (du < 0) SBI(dm, U_AXIS),
if (dv < 0) SBI(dm, V_AXIS),
if (dw < 0) SBI(dm, W_AXIS)
);
#if HAS_EXTRUDERS
if (de < 0) SBI(dm, E_AXIS);
const float esteps_float = de * e_factor[extruder];
@ -1974,22 +1992,24 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
// Number of steps for each axis
// See https://www.corexy.com/theory.html
#if CORE_IS_XY
block->steps.set(LINEAR_AXIS_LIST(ABS(da + db), ABS(da - db), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#elif CORE_IS_XZ
block->steps.set(LINEAR_AXIS_LIST(ABS(da + dc), ABS(db), ABS(da - dc), ABS(di), ABS(dj), ABS(dk)));
#elif CORE_IS_YZ
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + dc), ABS(db - dc), ABS(di), ABS(dj), ABS(dk)));
#elif ENABLED(MARKFORGED_XY)
block->steps.set(LINEAR_AXIS_LIST(ABS(da + db), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#elif ENABLED(MARKFORGED_YX)
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + da), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#elif IS_SCARA
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#else
// default non-h-bot planning
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#endif
block->steps.set(NUM_AXIS_LIST(
#if CORE_IS_XY
ABS(da + db), ABS(da - db), ABS(dc)
#elif CORE_IS_XZ
ABS(da + dc), ABS(db), ABS(da - dc)
#elif CORE_IS_YZ
ABS(da), ABS(db + dc), ABS(db - dc)
#elif ENABLED(MARKFORGED_XY)
ABS(da + db), ABS(db), ABS(dc)
#elif ENABLED(MARKFORGED_YX)
ABS(da), ABS(db + da), ABS(dc)
#elif IS_SCARA
ABS(da), ABS(db), ABS(dc)
#else // default non-h-bot planning
ABS(da), ABS(db), ABS(dc)
#endif
, ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw)
));
/**
* This part of the code calculates the total length of the movement.
@ -2027,9 +2047,6 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
steps_dist_mm.b = (db + dc) * mm_per_step[B_AXIS];
steps_dist_mm.c = CORESIGN(db - dc) * mm_per_step[C_AXIS];
#endif
TERN_(HAS_I_AXIS, steps_dist_mm.i = di * mm_per_step[I_AXIS]);
TERN_(HAS_J_AXIS, steps_dist_mm.j = dj * mm_per_step[J_AXIS]);
TERN_(HAS_K_AXIS, steps_dist_mm.k = dk * mm_per_step[K_AXIS]);
#elif ENABLED(MARKFORGED_XY)
steps_dist_mm.a = (da - db) * mm_per_step[A_AXIS];
steps_dist_mm.b = db * mm_per_step[B_AXIS];
@ -2037,27 +2054,40 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
steps_dist_mm.a = da * mm_per_step[A_AXIS];
steps_dist_mm.b = (db - da) * mm_per_step[B_AXIS];
#else
LINEAR_AXIS_CODE(
XYZ_CODE(
steps_dist_mm.a = da * mm_per_step[A_AXIS],
steps_dist_mm.b = db * mm_per_step[B_AXIS],
steps_dist_mm.c = dc * mm_per_step[C_AXIS],
steps_dist_mm.i = di * mm_per_step[I_AXIS],
steps_dist_mm.j = dj * mm_per_step[J_AXIS],
steps_dist_mm.k = dk * mm_per_step[K_AXIS]
steps_dist_mm.c = dc * mm_per_step[C_AXIS]
);
#endif
SECONDARY_AXIS_CODE(
steps_dist_mm.i = di * mm_per_step[I_AXIS],
steps_dist_mm.j = dj * mm_per_step[J_AXIS],
steps_dist_mm.k = dk * mm_per_step[K_AXIS],
steps_dist_mm.u = du * mm_per_step[U_AXIS],
steps_dist_mm.v = dv * mm_per_step[V_AXIS],
steps_dist_mm.w = dw * mm_per_step[W_AXIS]
);
TERN_(HAS_EXTRUDERS, steps_dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]);
TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += steps_dist_mm.e);
if (true LINEAR_AXIS_GANG(
#if BOTH(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT)
bool cartesian_move = true;
#endif
if (true NUM_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.i < MIN_STEPS_PER_SEGMENT,
&& block->steps.j < MIN_STEPS_PER_SEGMENT,
&& block->steps.k < MIN_STEPS_PER_SEGMENT
&& block->steps.k < MIN_STEPS_PER_SEGMENT,
&& block->steps.u < MIN_STEPS_PER_SEGMENT,
&& block->steps.v < MIN_STEPS_PER_SEGMENT,
&& block->steps.w < MIN_STEPS_PER_SEGMENT
)
) {
block->millimeters = TERN0(HAS_EXTRUDERS, ABS(steps_dist_mm.e));
@ -2066,36 +2096,71 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
if (millimeters)
block->millimeters = millimeters;
else {
block->millimeters = SQRT(
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
LINEAR_AXIS_GANG(
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.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.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k)
)
/**
* Distance for interpretation of feedrate in accordance with LinuxCNC (the successor of NIST
* RS274NGC interpreter - version 3) and its default CANON_XYZ feed reference mode.
* Assume that X, Y, Z are the primary linear axes and U, V, W are secondary linear axes and A, B, C are
* rotational axes. Then dX, dY, dZ are the displacements of the primary linear axes and dU, dV, dW are the displacements of linear axes and
* dA, dB, dC are the displacements of rotational axes.
* The time it takes to execute move command with feedrate F is t = D/F, where D is the total distance, calculated as follows:
* D^2 = dX^2 + dY^2 + dZ^2
* if D^2 == 0 (none of XYZ move but any secondary linear axes move, whether other axes are moved or not):
* D^2 = dU^2 + dV^2 + dW^2
* if D^2 == 0 (only rotational axes are moved):
* D^2 = dA^2 + dB^2 + dC^2
*/
float distance_sqr = (
#if ENABLED(ARTICULATED_ROBOT_ARM)
// For articulated robots, interpreting feedrate like LinuxCNC would require inverse kinematics. As a workaround, pretend that motors sit on n mutually orthogonal
// axes and assume that we could think of distance as magnitude of an n-vector in an n-dimensional Euclidian space.
NUM_AXIS_GANG(
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),
+ sq(steps_dist_mm.u), + sq(steps_dist_mm.v), + sq(steps_dist_mm.w)
);
#elif ENABLED(FOAMCUTTER_XYUV)
// Return the largest distance move from either X/Y or I/J plane
#if HAS_J_AXIS
_MAX(sq(steps_dist_mm.x) + sq(steps_dist_mm.y), sq(steps_dist_mm.i) + sq(steps_dist_mm.j))
#else
// Special 5 axis kinematics. Return the largest distance move from either X/Y or I/J plane
_MAX(sq(steps_dist_mm.x) + sq(steps_dist_mm.y), sq(steps_dist_mm.i) + sq(steps_dist_mm.j))
#else // Foamcutter with only two axes (XY)
sq(steps_dist_mm.x) + sq(steps_dist_mm.y)
#endif
#elif ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
XYZ_GANG(sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z))
#elif CORE_IS_XZ
XYZ_GANG(sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z))
#elif CORE_IS_YZ
XYZ_GANG(sq(steps_dist_mm.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.head.z))
#else
LINEAR_AXIS_GANG(
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)
)
XYZ_GANG(sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z))
#endif
);
#if SECONDARY_LINEAR_AXES >= 1 && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM)
if (NEAR_ZERO(distance_sqr)) {
// Move does not involve any primary linear axes (xyz) but might involve secondary linear axes
distance_sqr = (0.0
SECONDARY_AXIS_GANG(
IF_DISABLED(AXIS4_ROTATES, + sq(steps_dist_mm.i)),
IF_DISABLED(AXIS5_ROTATES, + sq(steps_dist_mm.j)),
IF_DISABLED(AXIS6_ROTATES, + sq(steps_dist_mm.k)),
IF_DISABLED(AXIS7_ROTATES, + sq(steps_dist_mm.u)),
IF_DISABLED(AXIS8_ROTATES, + sq(steps_dist_mm.v)),
IF_DISABLED(AXIS9_ROTATES, + sq(steps_dist_mm.w))
)
);
}
#endif
#if HAS_ROTATIONAL_AXES && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM)
if (NEAR_ZERO(distance_sqr)) {
// Move involves only rotational axes. Calculate angular distance in accordance with LinuxCNC
TERN_(INCH_MODE_SUPPORT, cartesian_move = false);
distance_sqr = ROTATIONAL_AXIS_GANG(sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k), + sq(steps_dist_mm.u), + sq(steps_dist_mm.v), + sq(steps_dist_mm.w));
}
#endif
block->millimeters = SQRT(distance_sqr);
}
/**
@ -2112,8 +2177,10 @@ 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, block->steps.i, block->steps.j, block->steps.k
block->step_event_count = _MAX(LOGICAL_AXIS_LIST(esteps,
block->steps.a, block->steps.b, block->steps.c,
block->steps.i, block->steps.j, block->steps.k,
block->steps.u, block->steps.v, block->steps.w
));
// Bail if this is a zero-length block
@ -2135,13 +2202,16 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
E_TERN_(block->extruder = extruder);
#if ENABLED(AUTO_POWER_CONTROL)
if (LINEAR_AXIS_GANG(
if (NUM_AXIS_GANG(
block->steps.x,
|| block->steps.y,
|| block->steps.z,
|| block->steps.i,
|| block->steps.j,
|| block->steps.k
|| block->steps.k,
|| block->steps.u,
|| block->steps.v,
|| block->steps.w
)) powerManager.power_on();
#endif
@ -2167,19 +2237,27 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
}
if (block->steps.x) stepper.enable_axis(X_AXIS);
#else
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
if (block->steps.x) stepper.enable_axis(X_AXIS),
if (block->steps.y) stepper.enable_axis(Y_AXIS),
if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) stepper.enable_axis(Z_AXIS),
if (block->steps.i) stepper.enable_axis(I_AXIS),
if (block->steps.j) stepper.enable_axis(J_AXIS),
if (block->steps.k) stepper.enable_axis(K_AXIS)
if (block->steps.k) stepper.enable_axis(K_AXIS),
if (block->steps.u) stepper.enable_axis(U_AXIS),
if (block->steps.v) stepper.enable_axis(V_AXIS),
if (block->steps.w) stepper.enable_axis(W_AXIS)
);
#endif
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
TERN_(HAS_I_AXIS, if (block->steps.i) stepper.enable_axis(I_AXIS));
TERN_(HAS_J_AXIS, if (block->steps.j) stepper.enable_axis(J_AXIS));
TERN_(HAS_K_AXIS, if (block->steps.k) stepper.enable_axis(K_AXIS));
SECONDARY_AXIS_CODE(
if (block->steps.i) stepper.enable_axis(I_AXIS),
if (block->steps.j) stepper.enable_axis(J_AXIS),
if (block->steps.k) stepper.enable_axis(K_AXIS),
if (block->steps.u) stepper.enable_axis(U_AXIS),
if (block->steps.v) stepper.enable_axis(V_AXIS),
if (block->steps.w) stepper.enable_axis(W_AXIS)
);
#endif
// Enable extruder(s)
@ -2226,8 +2304,14 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
const float inverse_millimeters = 1.0f / block->millimeters; // Inverse millimeters to remove multiple divides
// Calculate inverse time for this move. No divide by zero due to previous checks.
// Example: At 120mm/s a 60mm move takes 0.5s. So this will give 2.0.
float inverse_secs = fr_mm_s * inverse_millimeters;
// Example: At 120mm/s a 60mm move involving XYZ axes takes 0.5s. So this will give 2.0.
// Example 2: At 120°/s a 60° move involving only rotational axes takes 0.5s. So this will give 2.0.
float inverse_secs;
#if BOTH(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT)
inverse_secs = inverse_millimeters * (cartesian_move ? fr_mm_s : LINEAR_UNIT(fr_mm_s));
#else
inverse_secs = fr_mm_s * inverse_millimeters;
#endif
// Get the number of non busy movements in queue (non busy means that they can be altered)
const uint8_t moves_queued = nonbusy_movesplanned();
@ -2273,13 +2357,13 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
filwidth.advance_e(steps_dist_mm.e);
#endif
// Calculate and limit speed in mm/sec
// Calculate and limit speed in mm/sec (linear) or degrees/sec (rotational)
xyze_float_t current_speed;
float speed_factor = 1.0f; // factor <1 decreases speed
// Linear axes first with less logic
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
current_speed[i] = steps_dist_mm[i] * inverse_secs;
const feedRate_t cs = ABS(current_speed[i]),
max_fr = settings.max_feedrate_mm_s[i];
@ -2367,9 +2451,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
// Compute and limit the acceleration rate for the trapezoid generator.
const float steps_per_mm = block->step_event_count * inverse_millimeters;
uint32_t accel;
if (LINEAR_AXIS_GANG(
if (NUM_AXIS_GANG(
!block->steps.a, && !block->steps.b, && !block->steps.c,
&& !block->steps.i, && !block->steps.j, && !block->steps.k)
&& !block->steps.i, && !block->steps.j, && !block->steps.k,
&& !block->steps.u, && !block->steps.v, && !block->steps.w)
) { // 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
@ -2442,7 +2527,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
LIMIT_ACCEL_LONG(C_AXIS, 0),
LIMIT_ACCEL_LONG(I_AXIS, 0),
LIMIT_ACCEL_LONG(J_AXIS, 0),
LIMIT_ACCEL_LONG(K_AXIS, 0)
LIMIT_ACCEL_LONG(K_AXIS, 0),
LIMIT_ACCEL_LONG(U_AXIS, 0),
LIMIT_ACCEL_LONG(V_AXIS, 0),
LIMIT_ACCEL_LONG(W_AXIS, 0)
);
}
else {
@ -2453,7 +2541,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
LIMIT_ACCEL_FLOAT(C_AXIS, 0),
LIMIT_ACCEL_FLOAT(I_AXIS, 0),
LIMIT_ACCEL_FLOAT(J_AXIS, 0),
LIMIT_ACCEL_FLOAT(K_AXIS, 0)
LIMIT_ACCEL_FLOAT(K_AXIS, 0),
LIMIT_ACCEL_FLOAT(U_AXIS, 0),
LIMIT_ACCEL_FLOAT(V_AXIS, 0),
LIMIT_ACCEL_FLOAT(W_AXIS, 0)
);
}
}
@ -2518,7 +2609,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, steps_dist_mm.i, steps_dist_mm.j, steps_dist_mm.k)
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, steps_dist_mm.u, steps_dist_mm.v, steps_dist_mm.w)
#endif
;
@ -2544,7 +2635,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
+ (-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)
+ (-prev_unit_vec.k * unit_vec.k),
+ (-prev_unit_vec.u * unit_vec.u),
+ (-prev_unit_vec.v * unit_vec.v),
+ (-prev_unit_vec.w * unit_vec.w)
);
// NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
@ -2691,7 +2785,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
const float extra_xyjerk = TERN0(HAS_EXTRUDERS, de <= 0) ? TRAVEL_EXTRA_XYJERK : 0;
uint8_t limited = 0;
TERN(HAS_LINEAR_E_JERK, LOOP_LINEAR_AXES, LOOP_LOGICAL_AXES)(i) {
TERN(HAS_LINEAR_E_JERK, LOOP_NUM_AXES, LOOP_LOGICAL_AXES)(i) {
const float jerk = ABS(current_speed[i]), // cs : Starting from zero, change in speed for this axis
maxj = (max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0.0f)); // mj : The max jerk setting for this axis
if (jerk > maxj) { // cs > mj : New current speed too fast?
@ -2729,7 +2823,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
vmax_junction = previous_nominal_speed;
// Now limit the jerk in all axes.
TERN(HAS_LINEAR_E_JERK, LOOP_LINEAR_AXES, LOOP_LOGICAL_AXES)(axis) {
TERN(HAS_LINEAR_E_JERK, LOOP_NUM_AXES, LOOP_LOGICAL_AXES)(axis) {
// Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop.
float v_exit = previous_speed[axis] * smaller_speed_factor,
v_entry = current_speed[axis];
@ -2831,7 +2925,7 @@ void Planner::buffer_sync_block(TERN_(LASER_SYNCHRONOUS_M106_M107, uint8_t sync_
block->position = position;
#if ENABLED(BACKLASH_COMPENSATION)
LOOP_LINEAR_AXES(axis) block->position[axis] += backlash.get_applied_steps((AxisEnum)axis);
LOOP_NUM_AXES(axis) block->position[axis] += backlash.get_applied_steps((AxisEnum)axis);
#endif
#if BOTH(HAS_FAN, LASER_SYNCHRONOUS_M106_M107)
@ -2893,7 +2987,10 @@ bool Planner::buffer_segment(const abce_pos_t &abce
int32_t(LROUND(abce.c * settings.axis_steps_per_mm[C_AXIS])),
int32_t(LROUND(abce.i * settings.axis_steps_per_mm[I_AXIS])),
int32_t(LROUND(abce.j * settings.axis_steps_per_mm[J_AXIS])),
int32_t(LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS]))
int32_t(LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])),
int32_t(LROUND(abce.u * settings.axis_steps_per_mm[U_AXIS])),
int32_t(LROUND(abce.v * settings.axis_steps_per_mm[V_AXIS])),
int32_t(LROUND(abce.w * settings.axis_steps_per_mm[W_AXIS]))
)
};
@ -2945,6 +3042,21 @@ bool Planner::buffer_segment(const abce_pos_t &abce
SERIAL_ECHOPGM(" (", position.k, "->", target.k);
SERIAL_CHAR(')');
#endif
#if HAS_U_AXIS
SERIAL_ECHOPGM_P(SP_U_LBL, abce.u);
SERIAL_ECHOPGM(" (", position.u, "->", target.u);
SERIAL_CHAR(')');
#endif
#if HAS_V_AXIS
SERIAL_ECHOPGM_P(SP_V_LBL, abce.v);
SERIAL_ECHOPGM(" (", position.v, "->", target.v);
SERIAL_CHAR(')');
#endif
#if HAS_W_AXIS
SERIAL_ECHOPGM_P(SP_W_LBL, abce.w);
SERIAL_ECHOPGM(" (", position.w, "->", target.w);
SERIAL_CHAR(')');
#endif
#if HAS_EXTRUDERS
SERIAL_ECHOPGM_P(SP_E_LBL, abce.e);
SERIAL_ECHOLNPGM(" (", position.e, "->", target.e, ")");
@ -2987,12 +3099,14 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, cons
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
cart.i - position_cart.i, cart.j - position_cart.j, cart.k - position_cart.k,
cart.u - position_cart.u, cart.v - position_cart.v, cart.w - position_cart.w
);
#else
const xyz_pos_t cart_dist_mm = LINEAR_AXIS_ARRAY(
const xyz_pos_t cart_dist_mm = NUM_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
cart.i - position_cart.i, cart.j - position_cart.j, cart.k - position_cart.k,
cart.u - position_cart.u, cart.v - position_cart.v, cart.w - position_cart.w
);
#endif
@ -3097,7 +3211,10 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) {
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])
LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS]),
LROUND(abce.u * settings.axis_steps_per_mm[U_AXIS]),
LROUND(abce.v * settings.axis_steps_per_mm[V_AXIS]),
LROUND(abce.w * settings.axis_steps_per_mm[W_AXIS])
)
);
@ -3109,7 +3226,7 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) {
else {
#if ENABLED(BACKLASH_COMPENSATION)
abce_long_t stepper_pos = position;
LOOP_LINEAR_AXES(axis) stepper_pos[axis] += backlash.get_applied_steps((AxisEnum)axis);
LOOP_NUM_AXES(axis) stepper_pos[axis] += backlash.get_applied_steps((AxisEnum)axis);
stepper.set_position(stepper_pos);
#else
stepper.set_position(position);

View File

@ -84,7 +84,8 @@
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,
_mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f);
_mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f,
_mf.u / 60.0f, _mf.v / 60.0f, _mf.w / 60.0f);
#endif
#if IS_KINEMATIC && HAS_JUNCTION_DEVIATION
@ -843,7 +844,8 @@ class Planner {
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(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS)
get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS),
get_axis_position_mm(U_AXIS), get_axis_position_mm(V_AXIS), get_axis_position_mm(W_AXIS)
);
return out;
}

View File

@ -188,7 +188,10 @@ void cubic_b_spline(
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.
interp(position.k, target.k, t), // FIXME. Wrong, since t is not linear in the distance.
interp(position.u, target.u, t), // FIXME. Wrong, since t is not linear in the distance.
interp(position.v, target.v, t), // FIXME. Wrong, since t is not linear in the distance.
interp(position.w, target.w, t) // FIXME. Wrong, since t is not linear in the distance.
);
apply_motion_limits(new_bez);
bez_target = new_bez;

View File

@ -809,9 +809,10 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
#endif
// On delta keep Z below clip height or do_blocking_move_to will abort
xyz_pos_t npos = LINEAR_AXIS_ARRAY(
xyz_pos_t npos = NUM_AXIS_ARRAY(
rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z),
current_position.i, current_position.j, current_position.k
current_position.i, current_position.j, current_position.k,
current_position.u, current_position.v, current_position.w
);
if (!can_reach(npos, probe_relative)) {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable");

View File

@ -146,7 +146,7 @@ public:
#else
static constexpr xyz_pos_t offset = xyz_pos_t(LINEAR_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767
static constexpr xyz_pos_t offset = xyz_pos_t(NUM_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767
static bool set_deployed(const bool) { return false; }

View File

@ -254,7 +254,7 @@ float segments_per_second = TERN(AXEL_TPARA, TPARA_SEGMENTS_PER_SECOND, SCARA_SE
// Do this here all at once for Delta, because
// XYZ isn't ABC. Applying this per-tower would
// give the impression that they are the same.
LOOP_LINEAR_AXES(i) set_axis_is_at_home((AxisEnum)i);
LOOP_NUM_AXES(i) set_axis_is_at_home((AxisEnum)i);
sync_plan_position();
}

View File

@ -180,10 +180,10 @@
#define _EN_ITEM(N) , E##N
#define _EN1_ITEM(N) , E##N:1
typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint16_t;
typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint32_t;
typedef struct { int16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4; } mot_stepper_int16_t;
typedef struct { bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1), X2:1, Y2:1, Z2:1, Z3:1, Z4:1 REPEAT(E_STEPPERS, _EN1_ITEM); } per_stepper_bool_t;
typedef struct { uint16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint16_t;
typedef struct { uint32_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } per_stepper_uint32_t;
typedef struct { int16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4; } mot_stepper_int16_t;
typedef struct { bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1), X2:1, Y2:1, Z2:1, Z3:1, Z4:1 REPEAT(E_STEPPERS, _EN1_ITEM); } per_stepper_bool_t;
#undef _EN_ITEM
@ -211,7 +211,7 @@ typedef struct SettingsDataStruct {
//
// DISTINCT_E_FACTORS
//
uint8_t e_factors; // DISTINCT_AXES - LINEAR_AXES
uint8_t e_factors; // DISTINCT_AXES - NUM_AXES
//
// Planner settings
@ -447,7 +447,7 @@ typedef struct SettingsDataStruct {
// HAS_MOTOR_CURRENT_PWM
//
#ifndef MOTOR_CURRENT_COUNT
#define MOTOR_CURRENT_COUNT LINEAR_AXES
#define MOTOR_CURRENT_COUNT NUM_AXES
#endif
uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // M907 X Z E ...
@ -600,7 +600,7 @@ void MarlinSettings::postprocess() {
#endif
// Software endstops depend on home_offset
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
update_workspace_offset((AxisEnum)i);
update_software_endstops((AxisEnum)i);
}
@ -750,7 +750,7 @@ void MarlinSettings::postprocess() {
working_crc = 0; // clear before first "real data"
const uint8_t e_factors = DISTINCT_AXES - (LINEAR_AXES);
const uint8_t e_factors = DISTINCT_AXES - (NUM_AXES);
_FIELD_TEST(e_factors);
EEPROM_WRITE(e_factors);
@ -767,7 +767,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, 0.4, 0.4, 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, 0.4, 0.4, 0.4);
EEPROM_WRITE(planner_max_jerk);
#endif
@ -1248,6 +1248,15 @@ void MarlinSettings::postprocess() {
#if AXIS_IS_TMC(K)
tmc_stepper_current.K = stepperK.getMilliamps();
#endif
#if AXIS_IS_TMC(U)
tmc_stepper_current.U = stepperU.getMilliamps();
#endif
#if AXIS_IS_TMC(V)
tmc_stepper_current.V = stepperV.getMilliamps();
#endif
#if AXIS_IS_TMC(W)
tmc_stepper_current.W = stepperW.getMilliamps();
#endif
#if AXIS_IS_TMC(X2)
tmc_stepper_current.X2 = stepperX2.getMilliamps();
#endif
@ -1305,6 +1314,9 @@ void MarlinSettings::postprocess() {
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_(U_HAS_STEALTHCHOP, tmc_hybrid_threshold.U = stepperU.get_pwm_thrs());
TERN_(V_HAS_STEALTHCHOP, tmc_hybrid_threshold.V = stepperV.get_pwm_thrs());
TERN_(W_HAS_STEALTHCHOP, tmc_hybrid_threshold.W = stepperW.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());
@ -1321,7 +1333,7 @@ void MarlinSettings::postprocess() {
#else
#define _EN_ITEM(N) , .E##N = 30
const per_stepper_uint32_t tmc_hybrid_threshold = {
LINEAR_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3),
NUM_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3, .U = 3, .V = 3, .W = 3),
.X2 = 100, .Y2 = 100, .Z2 = 3, .Z3 = 3, .Z4 = 3
REPEAT(E_STEPPERS, _EN_ITEM)
};
@ -1336,13 +1348,16 @@ void MarlinSettings::postprocess() {
{
mot_stepper_int16_t tmc_sgt{0};
#if USE_SENSORLESS
LINEAR_AXIS_CODE(
NUM_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_(K_SENSORLESS, tmc_sgt.K = stepperK.homing_threshold()),
TERN_(U_SENSORLESS, tmc_sgt.U = stepperU.homing_threshold()),
TERN_(V_SENSORLESS, tmc_sgt.V = stepperV.homing_threshold()),
TERN_(W_SENSORLESS, tmc_sgt.W = stepperW.homing_threshold())
);
TERN_(X2_SENSORLESS, tmc_sgt.X2 = stepperX2.homing_threshold());
TERN_(Y2_SENSORLESS, tmc_sgt.Y2 = stepperY2.homing_threshold());
@ -1366,6 +1381,9 @@ void MarlinSettings::postprocess() {
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_(U_HAS_STEALTHCHOP, tmc_stealth_enabled.U = stepperU.get_stored_stealthChop());
TERN_(V_HAS_STEALTHCHOP, tmc_stealth_enabled.V = stepperV.get_stored_stealthChop());
TERN_(W_HAS_STEALTHCHOP, tmc_stealth_enabled.W = stepperW.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());
@ -1455,7 +1473,7 @@ void MarlinSettings::postprocess() {
{
#if ENABLED(BACKLASH_GCODE)
xyz_float_t backlash_distance_mm;
LOOP_LINEAR_AXES(axis) backlash_distance_mm[axis] = backlash.get_distance_mm((AxisEnum)axis);
LOOP_NUM_AXES(axis) backlash_distance_mm[axis] = backlash.get_distance_mm((AxisEnum)axis);
const uint8_t backlash_correction = backlash.get_correction_uint8();
#else
const xyz_float_t backlash_distance_mm{0};
@ -1675,16 +1693,16 @@ void MarlinSettings::postprocess() {
{
// Get only the number of E stepper parameters previously stored
// Any steppers added later are set to their defaults
uint32_t tmp1[LINEAR_AXES + e_factors];
float tmp2[LINEAR_AXES + e_factors];
feedRate_t tmp3[LINEAR_AXES + e_factors];
uint32_t tmp1[NUM_AXES + e_factors];
float tmp2[NUM_AXES + e_factors];
feedRate_t tmp3[NUM_AXES + e_factors];
EEPROM_READ((uint8_t *)tmp1, sizeof(tmp1)); // max_acceleration_mm_per_s2
EEPROM_READ(planner.settings.min_segment_time_us);
EEPROM_READ((uint8_t *)tmp2, sizeof(tmp2)); // axis_steps_per_mm
EEPROM_READ((uint8_t *)tmp3, sizeof(tmp3)); // max_feedrate_mm_s
if (!validating) LOOP_DISTINCT_AXES(i) {
const bool in = (i < e_factors + LINEAR_AXES);
const bool in = (i < e_factors + NUM_AXES);
planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : pgm_read_dword(&_DMA[ALIM(i, _DMA)]);
planner.settings.axis_steps_per_mm[i] = in ? tmp2[i] : pgm_read_float(&_DASU[ALIM(i, _DASU)]);
planner.settings.max_feedrate_mm_s[i] = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]);
@ -2199,6 +2217,15 @@ void MarlinSettings::postprocess() {
#if AXIS_IS_TMC(K)
SET_CURR(K);
#endif
#if AXIS_IS_TMC(U)
SET_CURR(U);
#endif
#if AXIS_IS_TMC(V)
SET_CURR(V);
#endif
#if AXIS_IS_TMC(W)
SET_CURR(W);
#endif
#if AXIS_IS_TMC(E0)
SET_CURR(E0);
#endif
@ -2246,6 +2273,9 @@ void MarlinSettings::postprocess() {
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_(U_HAS_STEALTHCHOP, stepperU.set_pwm_thrs(tmc_hybrid_threshold.U));
TERN_(V_HAS_STEALTHCHOP, stepperV.set_pwm_thrs(tmc_hybrid_threshold.V));
TERN_(W_HAS_STEALTHCHOP, stepperW.set_pwm_thrs(tmc_hybrid_threshold.W));
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));
@ -2267,13 +2297,16 @@ void MarlinSettings::postprocess() {
EEPROM_READ(tmc_sgt);
#if USE_SENSORLESS
if (!validating) {
LINEAR_AXIS_CODE(
NUM_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_(K_SENSORLESS, stepperK.homing_threshold(tmc_sgt.K)),
TERN_(U_SENSORLESS, stepperU.homing_threshold(tmc_sgt.U)),
TERN_(V_SENSORLESS, stepperV.homing_threshold(tmc_sgt.V)),
TERN_(W_SENSORLESS, stepperW.homing_threshold(tmc_sgt.W))
);
TERN_(X2_SENSORLESS, stepperX2.homing_threshold(tmc_sgt.X2));
TERN_(Y2_SENSORLESS, stepperY2.homing_threshold(tmc_sgt.Y2));
@ -2301,6 +2334,9 @@ void MarlinSettings::postprocess() {
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_(U_HAS_STEALTHCHOP, SET_STEPPING_MODE(U));
TERN_(V_HAS_STEALTHCHOP, SET_STEPPING_MODE(V));
TERN_(W_HAS_STEALTHCHOP, SET_STEPPING_MODE(W));
TERN_(X2_HAS_STEALTHCHOP, SET_STEPPING_MODE(X2));
TERN_(Y2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Y2));
TERN_(Z2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Z2));
@ -2421,7 +2457,7 @@ void MarlinSettings::postprocess() {
EEPROM_READ(backlash_smoothing_mm);
#if ENABLED(BACKLASH_GCODE)
LOOP_LINEAR_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, backlash_distance_mm[axis]);
LOOP_NUM_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, backlash_distance_mm[axis]);
backlash.set_correction_uint8(backlash_correction);
#ifdef BACKLASH_SMOOTHING_MM
backlash.set_smoothing_mm(backlash_smoothing_mm);
@ -2807,8 +2843,17 @@ void MarlinSettings::reset() {
#if HAS_K_AXIS && !defined(DEFAULT_KJERK)
#define DEFAULT_KJERK 0
#endif
#if HAS_U_AXIS && !defined(DEFAULT_UJERK)
#define DEFAULT_UJERK 0
#endif
#if HAS_V_AXIS && !defined(DEFAULT_VJERK)
#define DEFAULT_VJERK 0
#endif
#if HAS_W_AXIS && !defined(DEFAULT_WJERK)
#define DEFAULT_WJERK 0
#endif
planner.max_jerk.set(
LINEAR_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_IJERK, DEFAULT_JJERK, DEFAULT_KJERK)
NUM_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_IJERK, DEFAULT_JJERK, DEFAULT_KJERK, DEFAULT_UJERK, DEFAULT_VJERK, DEFAULT_WJERK)
);
TERN_(HAS_CLASSIC_E_JERK, planner.max_jerk.e = DEFAULT_EJERK);
#endif
@ -2870,7 +2915,7 @@ void MarlinSettings::reset() {
#if ENABLED(BACKLASH_GCODE)
backlash.set_correction(BACKLASH_CORRECTION);
constexpr xyz_float_t tmp = BACKLASH_DISTANCE_MM;
LOOP_LINEAR_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, tmp[axis]);
LOOP_NUM_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, tmp[axis]);
#ifdef BACKLASH_SMOOTHING_MM
backlash.set_smoothing_mm(BACKLASH_SMOOTHING_MM);
#endif
@ -2916,11 +2961,11 @@ void MarlinSettings::reset() {
//
#if HAS_BED_PROBE
constexpr float dpo[] = NOZZLE_TO_PROBE_OFFSET;
static_assert(COUNT(dpo) == LINEAR_AXES, "NOZZLE_TO_PROBE_OFFSET must contain offsets for each linear axis X, Y, Z....");
static_assert(COUNT(dpo) == NUM_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];
LOOP_NUM_AXES(a) probe.offset[a] = dpo[a];
#else
probe.offset.set(LINEAR_AXIS_LIST(0, 0, dpo[Z_AXIS], 0, 0, 0));
probe.offset.set(NUM_AXIS_LIST(0, 0, dpo[Z_AXIS], 0, 0, 0, 0, 0, 0));
#endif
#endif

View File

@ -447,6 +447,18 @@ xyze_int8_t Stepper::count_direction{0};
#define K_APPLY_DIR(v,Q) K_DIR_WRITE(v)
#define K_APPLY_STEP(v,Q) K_STEP_WRITE(v)
#endif
#if HAS_U_AXIS
#define U_APPLY_DIR(v,Q) U_DIR_WRITE(v)
#define U_APPLY_STEP(v,Q) U_STEP_WRITE(v)
#endif
#if HAS_V_AXIS
#define V_APPLY_DIR(v,Q) V_DIR_WRITE(v)
#define V_APPLY_STEP(v,Q) V_STEP_WRITE(v)
#endif
#if HAS_W_AXIS
#define W_APPLY_DIR(v,Q) W_DIR_WRITE(v)
#define W_APPLY_STEP(v,Q) W_STEP_WRITE(v)
#endif
#if DISABLED(MIXING_EXTRUDER)
#define E_APPLY_STEP(v,Q) E_STEP_WRITE(stepper_extruder, v)
@ -486,9 +498,10 @@ xyze_int8_t Stepper::count_direction{0};
void Stepper::enable_axis(const AxisEnum axis) {
#define _CASE_ENABLE(N) case N##_AXIS: ENABLE_AXIS_##N(); break;
switch (axis) {
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
_CASE_ENABLE(X), _CASE_ENABLE(Y), _CASE_ENABLE(Z),
_CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K)
_CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K),
_CASE_ENABLE(U), _CASE_ENABLE(V), _CASE_ENABLE(W)
);
default: break;
}
@ -505,9 +518,10 @@ bool Stepper::disable_axis(const AxisEnum axis) {
if (can_disable) {
#define _CASE_DISABLE(N) case N##_AXIS: DISABLE_AXIS_##N(); break;
switch (axis) {
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
_CASE_DISABLE(X), _CASE_DISABLE(Y), _CASE_DISABLE(Z),
_CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K)
_CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K),
_CASE_DISABLE(U), _CASE_DISABLE(V), _CASE_DISABLE(W)
);
default: break;
}
@ -550,9 +564,10 @@ bool Stepper::disable_axis(const AxisEnum axis) {
void Stepper::enable_all_steppers() {
TERN_(AUTO_POWER_CONTROL, powerManager.power_on());
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS),
enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS)
enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS),
enable_axis(U_AXIS), enable_axis(V_AXIS), enable_axis(W_AXIS)
);
enable_e_steppers();
@ -560,9 +575,10 @@ void Stepper::enable_all_steppers() {
}
void Stepper::disable_all_steppers() {
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
disable_axis(X_AXIS), disable_axis(Y_AXIS), disable_axis(Z_AXIS),
disable_axis(I_AXIS), disable_axis(J_AXIS), disable_axis(K_AXIS)
disable_axis(I_AXIS), disable_axis(J_AXIS), disable_axis(K_AXIS),
disable_axis(U_AXIS), disable_axis(V_AXIS), disable_axis(W_AXIS)
);
disable_e_steppers();
@ -596,6 +612,9 @@ void Stepper::set_directions() {
TERN_(HAS_I_DIR, SET_STEP_DIR(I));
TERN_(HAS_J_DIR, SET_STEP_DIR(J));
TERN_(HAS_K_DIR, SET_STEP_DIR(K));
TERN_(HAS_U_DIR, SET_STEP_DIR(U));
TERN_(HAS_V_DIR, SET_STEP_DIR(V));
TERN_(HAS_W_DIR, SET_STEP_DIR(W));
#if DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
@ -1816,6 +1835,15 @@ void Stepper::pulse_phase_isr() {
#if HAS_K_STEP
PULSE_PREP(K);
#endif
#if HAS_U_STEP
PULSE_PREP(U);
#endif
#if HAS_V_STEP
PULSE_PREP(V);
#endif
#if HAS_W_STEP
PULSE_PREP(W);
#endif
#if EITHER(LIN_ADVANCE, MIXING_EXTRUDER)
delta_error.e += advance_dividend.e;
@ -1860,6 +1888,15 @@ void Stepper::pulse_phase_isr() {
#if HAS_K_STEP
PULSE_START(K);
#endif
#if HAS_U_STEP
PULSE_START(U);
#endif
#if HAS_V_STEP
PULSE_START(V);
#endif
#if HAS_W_STEP
PULSE_START(W);
#endif
#if DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
@ -1898,6 +1935,15 @@ void Stepper::pulse_phase_isr() {
#if HAS_K_STEP
PULSE_STOP(K);
#endif
#if HAS_U_STEP
PULSE_STOP(U);
#endif
#if HAS_V_STEP
PULSE_STOP(V);
#endif
#if HAS_W_STEP
PULSE_STOP(W);
#endif
#if DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
@ -2243,13 +2289,16 @@ uint32_t Stepper::block_phase_isr() {
#endif
axis_bits_t axis_bits = 0;
LINEAR_AXIS_CODE(
NUM_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 (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.k) SBI(axis_bits, K_AXIS),
if (current_block->steps.u) SBI(axis_bits, U_AXIS),
if (current_block->steps.v) SBI(axis_bits, V_AXIS),
if (current_block->steps.w) SBI(axis_bits, W_AXIS)
);
//if (current_block->steps.e) SBI(axis_bits, E_AXIS);
//if (current_block->steps.a) SBI(axis_bits, X_HEAD);
@ -2589,6 +2638,15 @@ void Stepper::init() {
#if HAS_K_DIR
K_DIR_INIT();
#endif
#if HAS_U_DIR
U_DIR_INIT();
#endif
#if HAS_V_DIR
V_DIR_INIT();
#endif
#if HAS_W_DIR
W_DIR_INIT();
#endif
#if HAS_E0_DIR
E0_DIR_INIT();
#endif
@ -2659,6 +2717,18 @@ void Stepper::init() {
K_ENABLE_INIT();
if (!K_ENABLE_ON) K_ENABLE_WRITE(HIGH);
#endif
#if HAS_U_ENABLE
U_ENABLE_INIT();
if (!U_ENABLE_ON) U_ENABLE_WRITE(HIGH);
#endif
#if HAS_V_ENABLE
V_ENABLE_INIT();
if (!V_ENABLE_ON) V_ENABLE_WRITE(HIGH);
#endif
#if HAS_W_ENABLE
W_ENABLE_INIT();
if (!W_ENABLE_ON) W_ENABLE_WRITE(HIGH);
#endif
#if HAS_E0_ENABLE
E0_ENABLE_INIT();
if (!E_ENABLE_ON) E0_ENABLE_WRITE(HIGH);
@ -2744,6 +2814,15 @@ void Stepper::init() {
#if HAS_K_STEP
AXIS_INIT(K, K);
#endif
#if HAS_U_STEP
AXIS_INIT(U, U);
#endif
#if HAS_V_STEP
AXIS_INIT(V, V);
#endif
#if HAS_W_STEP
AXIS_INIT(W, W);
#endif
#if E_STEPPERS && HAS_E0_STEP
E_AXIS_INIT(0);
@ -2778,13 +2857,16 @@ void Stepper::init() {
// Init direction bits for first moves
set_directions(0
LINEAR_AXIS_GANG(
NUM_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_I_DIR, _BV(I_AXIS)),
| TERN0(INVERT_J_DIR, _BV(J_AXIS)),
| TERN0(INVERT_K_DIR, _BV(K_AXIS))
| TERN0(INVERT_K_DIR, _BV(K_AXIS)),
| TERN0(INVERT_U_DIR, _BV(U_AXIS)),
| TERN0(INVERT_V_DIR, _BV(V_AXIS)),
| TERN0(INVERT_W_DIR, _BV(W_AXIS))
)
);
@ -2820,6 +2902,14 @@ void Stepper::_set_position(const abce_long_t &spos) {
#elif ENABLED(MARKFORGED_YX)
count_position.set(spos.a, spos.b - spos.a, spos.c);
#endif
SECONDARY_AXIS_CODE(
count_position.i = spos.i,
count_position.j = spos.j,
count_position.k = spos.k,
count_position.u = spos.u,
count_position.v = spos.v,
count_position.w = spos.w
);
TERN_(HAS_EXTRUDERS, count_position.e = spos.e);
#else
// default non-h-bot planning
@ -2934,13 +3024,16 @@ int32_t Stepper::triggered_position(const AxisEnum axis) {
void Stepper::report_a_position(const xyz_long_t &pos) {
SERIAL_ECHOLNPGM_P(
LIST_N(DOUBLE(LINEAR_AXES),
LIST_N(DOUBLE(NUM_AXES),
TERN(SAYS_A, PSTR(STR_COUNT_A), PSTR(STR_COUNT_X)), pos.x,
TERN(SAYS_B, PSTR("B:"), SP_Y_LBL), pos.y,
TERN(SAYS_C, PSTR("C:"), SP_Z_LBL), pos.z,
SP_I_LBL, pos.i,
SP_J_LBL, pos.j,
SP_K_LBL, pos.k
SP_K_LBL, pos.k,
SP_U_LBL, pos.u,
SP_V_LBL, pos.v,
SP_W_LBL, pos.w
)
);
}
@ -3096,16 +3189,18 @@ void Stepper::report_positions() {
const bool z_direction = direction ^ BABYSTEP_INVERT_Z;
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS),
enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS)
enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS),
enable_axis(U_AXIS), enable_axis(V_AXIS), enable_axis(W_AXIS)
);
DIR_WAIT_BEFORE();
const xyz_byte_t old_dir = LINEAR_AXIS_ARRAY(
const xyz_byte_t old_dir = NUM_AXIS_ARRAY(
X_DIR_READ(), Y_DIR_READ(), Z_DIR_READ(),
I_DIR_READ(), J_DIR_READ(), K_DIR_READ()
I_DIR_READ(), J_DIR_READ(), K_DIR_READ(),
U_DIR_READ(), V_DIR_READ(), W_DIR_READ()
);
X_DIR_WRITE(ENABLED(INVERT_X_DIR) ^ z_direction);
@ -3124,6 +3219,15 @@ void Stepper::report_positions() {
#ifdef K_DIR_WRITE
K_DIR_WRITE(ENABLED(INVERT_K_DIR) ^ z_direction);
#endif
#ifdef U_DIR_WRITE
U_DIR_WRITE(ENABLED(INVERT_U_DIR) ^ z_direction);
#endif
#ifdef V_DIR_WRITE
V_DIR_WRITE(ENABLED(INVERT_V_DIR) ^ z_direction);
#endif
#ifdef W_DIR_WRITE
W_DIR_WRITE(ENABLED(INVERT_W_DIR) ^ z_direction);
#endif
DIR_WAIT_AFTER();
@ -3145,6 +3249,15 @@ void Stepper::report_positions() {
#ifdef K_STEP_WRITE
K_STEP_WRITE(!INVERT_K_STEP_PIN);
#endif
#ifdef U_STEP_WRITE
U_STEP_WRITE(!INVERT_U_STEP_PIN);
#endif
#ifdef V_STEP_WRITE
V_STEP_WRITE(!INVERT_V_STEP_PIN);
#endif
#ifdef W_STEP_WRITE
W_STEP_WRITE(!INVERT_W_STEP_PIN);
#endif
_PULSE_WAIT();
@ -3164,6 +3277,15 @@ void Stepper::report_positions() {
#ifdef K_STEP_WRITE
K_STEP_WRITE(INVERT_K_STEP_PIN);
#endif
#ifdef U_STEP_WRITE
U_STEP_WRITE(INVERT_U_STEP_PIN);
#endif
#ifdef V_STEP_WRITE
V_STEP_WRITE(INVERT_V_STEP_PIN);
#endif
#ifdef W_STEP_WRITE
W_STEP_WRITE(INVERT_W_STEP_PIN);
#endif
// Restore direction bits
EXTRA_DIR_WAIT_BEFORE();
@ -3184,6 +3306,15 @@ void Stepper::report_positions() {
#ifdef K_DIR_WRITE
K_DIR_WRITE(old_dir.k);
#endif
#ifdef U_DIR_WRITE
U_DIR_WRITE(old_dir.u);
#endif
#ifdef V_DIR_WRITE
V_DIR_WRITE(old_dir.v);
#endif
#ifdef W_DIR_WRITE
W_DIR_WRITE(old_dir.w);
#endif
EXTRA_DIR_WAIT_AFTER();
@ -3200,6 +3331,15 @@ void Stepper::report_positions() {
#if HAS_K_AXIS
case K_AXIS: BABYSTEP_AXIS(K, 0, direction); break;
#endif
#if HAS_U_AXIS
case U_AXIS: BABYSTEP_AXIS(U, 0, direction); break;
#endif
#if HAS_V_AXIS
case V_AXIS: BABYSTEP_AXIS(V, 0, direction); break;
#endif
#if HAS_W_AXIS
case W_AXIS: BABYSTEP_AXIS(W, 0, direction); break;
#endif
default: break;
}
@ -3428,6 +3568,24 @@ void Stepper::report_positions() {
SET_OUTPUT(K_MS3_PIN);
#endif
#endif
#if HAS_U_MS_PINS
SET_OUTPUT(U_MS1_PIN); SET_OUTPUT(U_MS2_PIN);
#if PIN_EXISTS(U_MS3)
SET_OUTPUT(U_MS3_PIN);
#endif
#endif
#if HAS_V_MS_PINS
SET_OUTPUT(V_MS1_PIN); SET_OUTPUT(V_MS2_PIN);
#if PIN_EXISTS(V_MS3)
SET_OUTPUT(V_MS3_PIN);
#endif
#endif
#if HAS_W_MS_PINS
SET_OUTPUT(W_MS1_PIN); SET_OUTPUT(W_MS2_PIN);
#if PIN_EXISTS(W_MS3)
SET_OUTPUT(W_MS3_PIN);
#endif
#endif
#if HAS_E0_MS_PINS
SET_OUTPUT(E0_MS1_PIN); SET_OUTPUT(E0_MS2_PIN);
#if PIN_EXISTS(E0_MS3)
@ -3553,6 +3711,15 @@ void Stepper::report_positions() {
#if HAS_K_MS_PINS
case 13: WRITE(K_MS1_PIN, ms1); break
#endif
#if HAS_U_MS_PINS
case 14: WRITE(U_MS1_PIN, ms1); break
#endif
#if HAS_V_MS_PINS
case 15: WRITE(V_MS1_PIN, ms1); break
#endif
#if HAS_W_MS_PINS
case 16: WRITE(W_MS1_PIN, ms1); break
#endif
}
if (ms2 >= 0) switch (driver) {
#if HAS_X_MS_PINS || HAS_X2_MS_PINS
@ -3624,6 +3791,15 @@ void Stepper::report_positions() {
#if HAS_K_MS_PINS
case 13: WRITE(K_MS2_PIN, ms2); break
#endif
#if HAS_U_MS_PINS
case 14: WRITE(U_MS2_PIN, ms2); break
#endif
#if HAS_V_MS_PINS
case 15: WRITE(V_MS2_PIN, ms2); break
#endif
#if HAS_W_MS_PINS
case 16: WRITE(W_MS2_PIN, ms2); break
#endif
}
if (ms3 >= 0) switch (driver) {
#if HAS_X_MS_PINS || HAS_X2_MS_PINS
@ -3760,6 +3936,24 @@ void Stepper::report_positions() {
PIN_CHAR(K_MS3);
#endif
#endif
#if HAS_U_MS_PINS
MS_LINE(U);
#if PIN_EXISTS(U_MS3)
PIN_CHAR(U_MS3);
#endif
#endif
#if HAS_V_MS_PINS
MS_LINE(V);
#if PIN_EXISTS(V_MS3)
PIN_CHAR(V_MS3);
#endif
#endif
#if HAS_W_MS_PINS
MS_LINE(W);
#if PIN_EXISTS(W_MS3)
PIN_CHAR(W_MS3);
#endif
#endif
#if HAS_E0_MS_PINS
MS_LINE(E0);
#if PIN_EXISTS(E0_MS3)

View File

@ -159,12 +159,21 @@
#if HAS_K_STEP
#define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_U_STEP
#define ISR_U_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_V_STEP
#define ISR_V_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_W_STEP
#define ISR_W_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_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))
#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, + ISR_U_STEPPER_CYCLES, + ISR_V_STEPPER_CYCLES, + ISR_W_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))
@ -236,7 +245,7 @@
// Perhaps DISABLE_MULTI_STEPPING should be required with ADAPTIVE_STEP_SMOOTHING.
#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2)
#define ENABLE_COUNT (LINEAR_AXES + E_STEPPERS)
#define ENABLE_COUNT (NUM_AXES + E_STEPPERS)
typedef IF<(ENABLE_COUNT > 8), uint16_t, uint8_t>::type ena_mask_t;
// Axis flags type, for enabled state or other simple state
@ -244,25 +253,25 @@ typedef struct {
union {
ena_mask_t bits;
struct {
bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1);
bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1);
#if HAS_EXTRUDERS
bool LIST_N(EXTRUDERS, E0:1, E1:1, E2:1, E3:1, E4:1, E5:1, E6:1, E7:1);
#endif
};
};
constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; }
constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; }
constexpr ena_mask_t linear_bits() { return _BV(NUM_AXES) - 1; }
constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << NUM_AXES; }
} stepper_flags_t;
// All the stepper enable pins
constexpr pin_t ena_pins[] = {
LINEAR_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN),
NUM_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN, U_ENABLE_PIN, V_ENABLE_PIN, W_ENABLE_PIN),
LIST_N(E_STEPPERS, E0_ENABLE_PIN, E1_ENABLE_PIN, E2_ENABLE_PIN, E3_ENABLE_PIN, E4_ENABLE_PIN, E5_ENABLE_PIN, E6_ENABLE_PIN, E7_ENABLE_PIN)
};
// Index of the axis or extruder element in a combined array
constexpr uint8_t index_of_axis(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
return uint8_t(axis) + (E_TERN0(axis < LINEAR_AXES ? 0 : eindex));
return uint8_t(axis) + (E_TERN0(axis < NUM_AXES ? 0 : eindex));
}
//#define __IAX_N(N,V...) _IAX_##N(V)
//#define _IAX_N(N,V...) __IAX_N(N,V)
@ -292,7 +301,7 @@ constexpr bool any_enable_overlap(const uint8_t a=0) {
// (e.g., CoreXY, Dual XYZ, or E with multiple steppers, etc.).
constexpr ena_mask_t enable_overlap[] = {
#define _OVERLAP(N) ena_overlap(INDEX_OF_AXIS(AxisEnum(N))),
REPEAT(LINEAR_AXES, _OVERLAP)
REPEAT(NUM_AXES, _OVERLAP)
#if HAS_EXTRUDERS
#define _E_OVERLAP(N) ena_overlap(INDEX_OF_AXIS(E_AXIS, N)),
REPEAT(E_STEPPERS, _E_OVERLAP)
@ -320,7 +329,7 @@ class Stepper {
#ifndef MOTOR_CURRENT_PWM_FREQUENCY
#define MOTOR_CURRENT_PWM_FREQUENCY 31400
#endif
#define MOTOR_CURRENT_COUNT LINEAR_AXES
#define MOTOR_CURRENT_COUNT NUM_AXES
#elif HAS_MOTOR_CURRENT_SPI
static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
#define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count)

View File

@ -64,6 +64,15 @@
#if AXIS_IS_L64XX(K)
L64XX_CLASS(K) stepperK(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(U)
L64XX_CLASS(u) stepperU(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(V)
L64XX_CLASS(v) stepperV(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(W)
L64XX_CLASS(w) stepperW(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(E0)
L64XX_CLASS(E0) stepperE0(L6470_CHAIN_SS_PIN);
#endif
@ -217,6 +226,15 @@ void L64XX_Marlin::init_to_defaults() {
#if AXIS_IS_L64XX(K)
L6470_INIT_CHIP(K);
#endif
#if AXIS_IS_L64XX(U)
L6470_INIT_CHIP(U);
#endif
#if AXIS_IS_L64XX(V)
L6470_INIT_CHIP(V);
#endif
#if AXIS_IS_L64XX(W)
L6470_INIT_CHIP(W);
#endif
#if AXIS_IS_L64XX(E0)
L6470_INIT_CHIP(E0);
#endif

View File

@ -266,6 +266,72 @@
#endif
#endif
// U Stepper
#if HAS_U_AXIS
#if AXIS_IS_L64XX(U)
extern L64XX_CLASS(U) stepperU;
#define U_ENABLE_INIT() NOOP
#define U_ENABLE_WRITE(STATE) (STATE ? stepperU.hardStop() : stepperU.free())
#define U_ENABLE_READ() (stepperU.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_U(L6474)
#define U_DIR_INIT() SET_OUTPUT(U_DIR_PIN)
#define U_DIR_WRITE(STATE) L6474_DIR_WRITE(U, STATE)
#define U_DIR_READ() READ(U_DIR_PIN)
#else
#define U_DIR_INIT() NOOP
#define U_DIR_WRITE(STATE) L64XX_DIR_WRITE(U, STATE)
#define U_DIR_READ() (stepper##U.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_U(L6470)
#define DISABLE_STEPPER_U() stepperU.free()
#endif
#endif
#endif
#endif
// V Stepper
#if HAS_V_AXIS
#if AXIS_IS_L64XX(V)
extern L64XX_CLASS(V) stepperV;
#define V_ENABLE_INIT() NOOP
#define V_ENABLE_WRITE(STATE) (STATE ? stepperV.hardStop() : stepperV.free())
#define V_ENABLE_READ() (stepperV.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_V(L6474)
#define V_DIR_INIT() SET_OUTPUT(V_DIR_PIN)
#define V_DIR_WRITE(STATE) L6474_DIR_WRITE(V, STATE)
#define V_DIR_READ() READ(V_DIR_PIN)
#else
#define V_DIR_INIT() NOOP
#define V_DIR_WRITE(STATE) L64XX_DIR_WRITE(V, STATE)
#define V_DIR_READ() (stepper##V.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_V(L6470)
#define DISABLE_STEPPER_V() stepperV.free()
#endif
#endif
#endif
#endif
// W Stepper
#if HAS_W_AXIS
#if AXIS_IS_L64XX(W)
extern L64XX_CLASS(w) stepperW;
#define W_ENABLE_INIT() NOOP
#define W_ENABLE_WRITE(STATE) (STATE ? stepperW.hardStop() : stepperW.free())
#define W_ENABLE_READ() (stepperW.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_W(L6474)
#define W_DIR_INIT() SET_OUTPUT(W_DIR_PIN)
#define W_DIR_WRITE(STATE) L6474_DIR_WRITE(W, STATE)
#define W_DIR_READ() READ(W_DIR_PIN)
#else
#define W_DIR_INIT() NOOP
#define W_DIR_WRITE(STATE) L64XX_DIR_WRITE(W, STATE)
#define W_DIR_READ() (stepper##W.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_W(L6470)
#define DISABLE_STEPPER_W() stepperW.free()
#endif
#endif
#endif
#endif
// E0 Stepper
#if AXIS_IS_L64XX(E0)
extern L64XX_CLASS(E0) stepperE0;

View File

@ -69,6 +69,15 @@
#if AXIS_DRIVER_TYPE_K(TMC26X)
_TMC26X_DEFINE(K);
#endif
#if AXIS_DRIVER_TYPE_U(TMC26X)
_TMC26X_DEFINE(U);
#endif
#if AXIS_DRIVER_TYPE_V(TMC26X)
_TMC26X_DEFINE(V);
#endif
#if AXIS_DRIVER_TYPE_W(TMC26X)
_TMC26X_DEFINE(W);
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
_TMC26X_DEFINE(E0);
#endif
@ -133,6 +142,15 @@ void tmc26x_init_to_defaults() {
#if AXIS_DRIVER_TYPE_K(TMC26X)
_TMC26X_INIT(K);
#endif
#if AXIS_DRIVER_TYPE_U(TMC26X)
_TMC26X_INIT(U);
#endif
#if AXIS_DRIVER_TYPE_V(TMC26X)
_TMC26X_INIT(V);
#endif
#if AXIS_DRIVER_TYPE_W(TMC26X)
_TMC26X_INIT(W);
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
_TMC26X_INIT(E0);
#endif

View File

@ -123,6 +123,30 @@ void tmc26x_init_to_defaults();
#define K_ENABLE_READ() stepperK.isEnabled()
#endif
// U Stepper
#if HAS_U_ENABLE && AXIS_DRIVER_TYPE_U(TMC26X)
extern TMC26XStepper stepperU;
#define U_ENABLE_INIT() NOOP
#define U_ENABLE_WRITE(STATE) stepperU.setEnabled(STATE)
#define U_ENABLE_READ() stepperU.isEnabled()
#endif
// V Stepper
#if HAS_V_ENABLE && AXIS_DRIVER_TYPE_V(TMC26X)
extern TMC26XStepper stepperV;
#define V_ENABLE_INIT() NOOP
#define V_ENABLE_WRITE(STATE) stepperV.setEnabled(STATE)
#define V_ENABLE_READ() stepperV.isEnabled()
#endif
// W Stepper
#if HAS_W_ENABLE && AXIS_DRIVER_TYPE_W(TMC26X)
extern TMC26XStepper stepperW;
#define W_ENABLE_INIT() NOOP
#define W_ENABLE_WRITE(STATE) stepperW.setEnabled(STATE)
#define W_ENABLE_READ() stepperW.isEnabled()
#endif
// E0 Stepper
#if AXIS_DRIVER_TYPE_E0(TMC26X)
extern TMC26XStepper stepperE0;

View File

@ -262,6 +262,63 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define K_STEP_READ() bool(READ(K_STEP_PIN))
#endif
// U Stepper
#if HAS_U_AXIS
#ifndef U_ENABLE_INIT
#define U_ENABLE_INIT() SET_OUTPUT(U_ENABLE_PIN)
#define U_ENABLE_WRITE(STATE) WRITE(U_ENABLE_PIN,STATE)
#define U_ENABLE_READ() bool(READ(U_ENABLE_PIN))
#endif
#ifndef U_DIR_INIT
#define U_DIR_INIT() SET_OUTPUT(U_DIR_PIN)
#define U_DIR_WRITE(STATE) WRITE(U_DIR_PIN,STATE)
#define U_DIR_READ() bool(READ(U_DIR_PIN))
#endif
#define U_STEP_INIT() SET_OUTPUT(U_STEP_PIN)
#ifndef U_STEP_WRITE
#define U_STEP_WRITE(STATE) WRITE(U_STEP_PIN,STATE)
#endif
#define U_STEP_READ() bool(READ(U_STEP_PIN))
#endif
// V Stepper
#if HAS_V_AXIS
#ifndef V_ENABLE_INIT
#define V_ENABLE_INIT() SET_OUTPUT(V_ENABLE_PIN)
#define V_ENABLE_WRITE(STATE) WRITE(V_ENABLE_PIN,STATE)
#define V_ENABLE_READ() bool(READ(V_ENABLE_PIN))
#endif
#ifndef V_DIR_INIT
#define V_DIR_INIT() SET_OUTPUT(V_DIR_PIN)
#define V_DIR_WRITE(STATE) WRITE(V_DIR_PIN,STATE)
#define V_DIR_READ() bool(READ(V_DIR_PIN))
#endif
#define V_STEP_INIT() SET_OUTPUT(V_STEP_PIN)
#ifndef V_STEP_WRITE
#define V_STEP_WRITE(STATE) WRITE(V_STEP_PIN,STATE)
#endif
#define V_STEP_READ() bool(READ(V_STEP_PIN))
#endif
// W Stepper
#if HAS_W_AXIS
#ifndef W_ENABLE_INIT
#define W_ENABLE_INIT() SET_OUTPUT(W_ENABLE_PIN)
#define W_ENABLE_WRITE(STATE) WRITE(W_ENABLE_PIN,STATE)
#define W_ENABLE_READ() bool(READ(W_ENABLE_PIN))
#endif
#ifndef W_DIR_INIT
#define W_DIR_INIT() SET_OUTPUT(W_DIR_PIN)
#define W_DIR_WRITE(STATE) WRITE(W_DIR_PIN,STATE)
#define W_DIR_READ() bool(READ(W_DIR_PIN))
#endif
#define W_STEP_INIT() SET_OUTPUT(W_STEP_PIN)
#ifndef W_STEP_WRITE
#define W_STEP_WRITE(STATE) WRITE(W_STEP_PIN,STATE)
#endif
#define W_STEP_READ() bool(READ(W_STEP_PIN))
#endif
// E0 Stepper
#ifndef E0_ENABLE_INIT
#define E0_ENABLE_INIT() SET_OUTPUT(E0_ENABLE_PIN)
@ -743,6 +800,51 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define DISABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE(!K_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_U
#if HAS_U_ENABLE
#define ENABLE_STEPPER_U() U_ENABLE_WRITE( U_ENABLE_ON)
#else
#define ENABLE_STEPPER_U() NOOP
#endif
#endif
#ifndef DISABLE_STEPPER_U
#if HAS_U_ENABLE
#define DISABLE_STEPPER_U() U_ENABLE_WRITE(!U_ENABLE_ON)
#else
#define DISABLE_STEPPER_U() NOOP
#endif
#endif
#ifndef ENABLE_STEPPER_V
#if HAS_V_ENABLE
#define ENABLE_STEPPER_V() V_ENABLE_WRITE( V_ENABLE_ON)
#else
#define ENABLE_STEPPER_V() NOOP
#endif
#endif
#ifndef DISABLE_STEPPER_V
#if HAS_V_ENABLE
#define DISABLE_STEPPER_V() V_ENABLE_WRITE(!V_ENABLE_ON)
#else
#define DISABLE_STEPPER_V() NOOP
#endif
#endif
#ifndef ENABLE_STEPPER_W
#if HAS_W_ENABLE
#define ENABLE_STEPPER_W() W_ENABLE_WRITE( W_ENABLE_ON)
#else
#define ENABLE_STEPPER_W() NOOP
#endif
#endif
#ifndef DISABLE_STEPPER_W
#if HAS_W_ENABLE
#define DISABLE_STEPPER_W() W_ENABLE_WRITE(!W_ENABLE_ON)
#else
#define DISABLE_STEPPER_W() NOOP
#endif
#endif
#ifndef ENABLE_STEPPER_E0
#define ENABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE( E_ENABLE_ON), NOOP)
#endif
@ -917,6 +1019,28 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define DISABLE_AXIS_K() NOOP
#endif
#if HAS_U_AXIS
#define ENABLE_AXIS_U() if (SHOULD_ENABLE(u)) { ENABLE_STEPPER_U(); AFTER_CHANGE(u, true); }
#define DISABLE_AXIS_U() if (SHOULD_DISABLE(u)) { DISABLE_STEPPER_U(); AFTER_CHANGE(u, false); set_axis_untrusted(U_AXIS); }
#else
#define ENABLE_AXIS_U() NOOP
#define DISABLE_AXIS_U() NOOP
#endif
#if HAS_V_AXIS
#define ENABLE_AXIS_V() if (SHOULD_ENABLE(v)) { ENABLE_STEPPER_V(); AFTER_CHANGE(v, true); }
#define DISABLE_AXIS_V() if (SHOULD_DISABLE(v)) { DISABLE_STEPPER_V(); AFTER_CHANGE(v, false); set_axis_untrusted(V_AXIS); }
#else
#define ENABLE_AXIS_V() NOOP
#define DISABLE_AXIS_V() NOOP
#endif
#if HAS_W_AXIS
#define ENABLE_AXIS_W() if (SHOULD_ENABLE(w)) { ENABLE_STEPPER_W(); AFTER_CHANGE(w, true); }
#define DISABLE_AXIS_W() if (SHOULD_DISABLE(w)) { DISABLE_STEPPER_W(); AFTER_CHANGE(w, false); set_axis_untrusted(W_AXIS); }
#else
#define ENABLE_AXIS_W() NOOP
#define DISABLE_AXIS_W() 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, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K)
LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K, STEALTH_AXIS_U, STEALTH_AXIS_V, STEALTH_AXIS_W)
};
#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, ST##_HOLD_MULTIPLIER)
@ -106,6 +106,15 @@ enum StealthIndex : uint8_t {
#if AXIS_HAS_SPI(K)
TMC_SPI_DEFINE(K, K);
#endif
#if AXIS_HAS_SPI(U)
TMC_SPI_DEFINE(U, U);
#endif
#if AXIS_HAS_SPI(V)
TMC_SPI_DEFINE(V, V);
#endif
#if AXIS_HAS_SPI(W)
TMC_SPI_DEFINE(W, W);
#endif
#if AXIS_HAS_SPI(E0)
TMC_SPI_DEFINE_E(0);
#endif
@ -173,6 +182,15 @@ enum StealthIndex : uint8_t {
#ifndef TMC_K_BAUD_RATE
#define TMC_K_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_U_BAUD_RATE
#define TMC_U_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_V_BAUD_RATE
#define TMC_V_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_W_BAUD_RATE
#define TMC_W_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E0_BAUD_RATE
#define TMC_E0_BAUD_RATE TMC_BAUD_RATE
#endif
@ -374,6 +392,32 @@ enum StealthIndex : uint8_t {
#define K_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(U)
#ifdef U_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, U, U);
#define U_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, U, U);
#define U_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(V)
#ifdef V_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, V, V);
#else
TMC_UART_DEFINE(SW, V, V);
#define V_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(W)
#ifdef W_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, W, W);
#define W_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, W, W);
#define W_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E0)
#ifdef E0_HARDWARE_SERIAL
@ -449,7 +493,7 @@ enum StealthIndex : uint8_t {
#endif
#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 };
enum TMCAxis : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
#undef _EN_ITEM
void tmc_serial_begin() {
@ -543,6 +587,27 @@ enum StealthIndex : uint8_t {
stepperK.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(U)
#ifdef U_HARDWARE_SERIAL
HW_SERIAL_BEGIN(U);
#else
stepperU.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(V)
#ifdef V_HARDWARE_SERIAL
HW_SERIAL_BEGIN(V);
#else
stepperV.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(W)
#ifdef W_HARDWARE_SERIAL
HW_SERIAL_BEGIN(W);
#else
stepperW.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E0)
#ifdef E0_HARDWARE_SERIAL
HW_SERIAL_BEGIN(E0);
@ -814,6 +879,15 @@ void restore_trinamic_drivers() {
#if AXIS_IS_TMC(K)
stepperK.push();
#endif
#if AXIS_IS_TMC(U)
stepperU.push();
#endif
#if AXIS_IS_TMC(V)
stepperV.push();
#endif
#if AXIS_IS_TMC(W)
stepperW.push();
#endif
#if AXIS_IS_TMC(E0)
stepperE0.push();
#endif
@ -844,7 +918,8 @@ void reset_trinamic_drivers() {
static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY(
ENABLED(STEALTHCHOP_E),
ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z),
ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K)
ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K),
ENABLED(STEALTHCHOP_U), ENABLED(STEALTHCHOP_V), ENABLED(STEALTHCHOP_W)
);
#if AXIS_IS_TMC(X)
@ -880,6 +955,15 @@ void reset_trinamic_drivers() {
#if AXIS_IS_TMC(K)
TMC_INIT(K, STEALTH_AXIS_K);
#endif
#if AXIS_IS_TMC(U)
TMC_INIT(U, STEALTH_AXIS_U);
#endif
#if AXIS_IS_TMC(V)
TMC_INIT(V, STEALTH_AXIS_V);
#endif
#if AXIS_IS_TMC(W)
TMC_INIT(W, STEALTH_AXIS_W);
#endif
#if AXIS_IS_TMC(E0)
TMC_INIT(E0, STEALTH_AXIS_E);
#endif
@ -917,6 +1001,9 @@ void reset_trinamic_drivers() {
TERN_(I_SENSORLESS, stepperI.homing_threshold(I_STALL_SENSITIVITY));
TERN_(J_SENSORLESS, stepperJ.homing_threshold(J_STALL_SENSITIVITY));
TERN_(K_SENSORLESS, stepperK.homing_threshold(K_STALL_SENSITIVITY));
TERN_(U_SENSORLESS, stepperU.homing_threshold(U_STALL_SENSITIVITY));
TERN_(V_SENSORLESS, stepperV.homing_threshold(V_STALL_SENSITIVITY));
TERN_(W_SENSORLESS, stepperW.homing_threshold(W_STALL_SENSITIVITY));
#endif
#ifdef TMC_ADV
@ -946,7 +1033,7 @@ void reset_trinamic_drivers() {
TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2),
TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2),
TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4),
TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K),
TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K), TMC_HW_DETAIL(U), TMC_HW_DETAIL(V), TMC_HW_DETAIL(W),
TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7)
};
@ -969,7 +1056,7 @@ void reset_trinamic_drivers() {
SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2);
SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2);
SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4);
SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K);
SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K); SA_NO_TMC_HW_C(U); SA_NO_TMC_HW_C(V); SA_NO_TMC_HW_C(W);
SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7);
#endif
@ -981,7 +1068,7 @@ void reset_trinamic_drivers() {
TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2),
TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2),
TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4),
TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K),
TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K), TMC_SW_DETAIL(U), TMC_SW_DETAIL(V), TMC_SW_DETAIL(W),
TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7)
};
@ -999,7 +1086,7 @@ void reset_trinamic_drivers() {
SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2);
SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2);
SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4);
SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K);
SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K); SA_NO_TMC_SW_C(U); SA_NO_TMC_SW_C(V); SA_NO_TMC_SW_C(W);
SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7);
#endif

View File

@ -49,6 +49,9 @@
#define TMC_I_LABEL 'I', '0'
#define TMC_J_LABEL 'J', '0'
#define TMC_K_LABEL 'K', '0'
#define TMC_U_LABEL 'U', '0'
#define TMC_V_LABEL 'V', '0'
#define TMC_W_LABEL 'W', '0'
#define TMC_X2_LABEL 'X', '2'
#define TMC_Y2_LABEL 'Y', '2'
@ -92,6 +95,15 @@
#if HAS_K_AXIS && !defined(CHOPPER_TIMING_K)
#define CHOPPER_TIMING_K CHOPPER_TIMING
#endif
#if HAS_U_AXIS && !defined(CHOPPER_TIMING_U)
#define CHOPPER_TIMING_U CHOPPER_TIMING
#endif
#if HAS_V_AXIS && !defined(CHOPPER_TIMING_V)
#define CHOPPER_TIMING_V CHOPPER_TIMING
#endif
#if HAS_W_AXIS && !defined(CHOPPER_TIMING_W)
#define CHOPPER_TIMING_W CHOPPER_TIMING
#endif
#if HAS_EXTRUDERS && !defined(CHOPPER_TIMING_E)
#define CHOPPER_TIMING_E CHOPPER_TIMING
#endif
@ -274,6 +286,48 @@ void reset_trinamic_drivers();
#endif
#endif
// U Stepper
#if AXIS_IS_TMC(U)
extern TMC_CLASS(U, U) stepperU;
static constexpr chopper_timing_t chopper_timing_U = CHOPPER_TIMING_U;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define U_ENABLE_INIT() NOOP
#define U_ENABLE_WRITE(STATE) stepperU.toff((STATE)==U_ENABLE_ON ? chopper_timing_U.toff : 0)
#define U_ENABLE_READ() stepperU.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(U)
#define U_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(U_STEP_PIN); }while(0)
#endif
#endif
// V Stepper
#if AXIS_IS_TMC(V)
extern TMC_CLASS(V, V) stepperV;
static constexpr chopper_timing_t chopper_timing_V = CHOPPER_TIMING_V;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define V_ENABLE_INIT() NOOP
#define V_ENABLE_WRITE(STATE) stepperV.toff((STATE)==V_ENABLE_ON ? chopper_timing_V.toff : 0)
#define V_ENABLE_READ() stepperV.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(V)
#define V_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(V_STEP_PIN); }while(0)
#endif
#endif
// W Stepper
#if AXIS_IS_TMC(W)
extern TMC_CLASS(W, W) stepperW;
static constexpr chopper_timing_t chopper_timing_W = CHOPPER_TIMING_W;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define W_ENABLE_INIT() NOOP
#define W_ENABLE_WRITE(STATE) stepperW.toff((STATE)==W_ENABLE_ON ? chopper_timing_W.toff : 0)
#define W_ENABLE_READ() stepperW.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(W)
#define W_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(W_STEP_PIN); }while(0)
#endif
#endif
// E0 Stepper
#if AXIS_IS_TMC(E0)
extern TMC_CLASS_E(0) stepperE0;

View File

@ -1052,6 +1052,16 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0.
if (ok) {
IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x);
IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y);
#if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY)
SECONDARY_AXIS_CODE(
current_position.i = toolchange_settings.change_point.i,
current_position.j = toolchange_settings.change_point.j,
current_position.k = toolchange_settings.change_point.k,
current_position.u = toolchange_settings.change_point.u,
current_position.v = toolchange_settings.change_point.v,
current_position.w = toolchange_settings.change_point.w
);
#endif
planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), active_extruder);
planner.synchronize();
}
@ -1227,6 +1237,16 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
if (can_move_away && toolchange_settings.enable_park) {
IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x);
IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y);
#if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY)
SECONDARY_AXIS_CODE(
current_position.i = toolchange_settings.change_point.i,
current_position.j = toolchange_settings.change_point.j,
current_position.k = toolchange_settings.change_point.k,
current_position.u = toolchange_settings.change_point.u,
current_position.v = toolchange_settings.change_point.v,
current_position.w = toolchange_settings.change_point.w
);
#endif
planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), old_tool);
planner.synchronize();
}
@ -1281,7 +1301,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
sync_plan_position();
#if ENABLED(DELTA)
//LOOP_LINEAR_AXES(i) update_software_endstops(i); // or modify the constrain function
//LOOP_NUM_AXES(i) update_software_endstops(i); // or modify the constrain function
const bool safe_to_move = current_position.z < delta_clip_start_height - 1;
#else
constexpr bool safe_to_move = true;

View File

@ -40,7 +40,7 @@
#endif
#if ENABLED(TOOLCHANGE_PARK)
bool enable_park; // M217 W
xyz_pos_t change_point; // M217 X Y I J K
xyz_pos_t change_point; // M217 X Y I J K C H O
#endif
float z_raise; // M217 Z
} toolchange_settings_t;