diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 837f3885b949..96aa58c80716 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -366,17 +366,17 @@ #define STR_Z2 STR_C "2" #define STR_Z3 STR_C "3" #define STR_Z4 STR_C "4" -#if CORE_IS_XY || CORE_IS_XZ +#if ANY(HAS_REAL_X, IS_SCARA, DELTA) #define STEPPER_A_NAME 'A' #else #define STEPPER_A_NAME 'X' #endif -#if CORE_IS_XY || CORE_IS_YZ +#if ANY(HAS_REAL_Y, IS_SCARA, DELTA, POLAR) #define STEPPER_B_NAME 'B' #else #define STEPPER_B_NAME 'Y' #endif -#if CORE_IS_XZ || CORE_IS_YZ +#if ANY(HAS_REAL_Z, DELTA) #define STEPPER_C_NAME 'C' #else #define STEPPER_C_NAME 'Z' diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 96ce9716d255..02ee0d9dd165 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -352,7 +352,7 @@ typedef struct { // // - X_AXIS, Y_AXIS, and Z_AXIS should be used for axes in Cartesian space // - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians -// - X_HEAD, Y_HEAD, and Z_HEAD should be used for axes on Core kinematics +// - X_REAL, Y_REAL, and Z_REAL should be used for axes on Core kinematics // enum AxisEnum : uint8_t { @@ -364,8 +364,14 @@ enum AxisEnum : uint8_t { #undef _EN_ITEM // Core also keeps toolhead directions - #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) - X_HEAD, Y_HEAD, Z_HEAD, + #if HAS_REAL_X + X_REAL, + #endif + #if HAS_REAL_Y + Y_REAL, + #endif + #if HAS_REAL_Z + Z_REAL, #endif // Distinct axes, including all E and Core @@ -374,6 +380,10 @@ enum AxisEnum : uint8_t { // Most of the time we refer only to the single E_AXIS #if HAS_EXTRUDERS E_AXIS = E0_AXIS, + E_REAL = E_AXIS, + #define _EN_REAL(N) E##N##_REAL = E##N##_AXIS, + REPEAT(EXTRUDERS, _EN_REAL) + #undef _EN_REAL #endif // A, B, and C are for DELTA, SCARA, etc. @@ -387,6 +397,35 @@ enum AxisEnum : uint8_t { C_AXIS = Z_AXIS, #endif + // Aliases to distinguish tool axes from stepper indexes + #if HAS_X_AXIS && !HAS_REAL_X + X_REAL = X_AXIS, + #endif + #if HAS_Y_AXIS && !HAS_REAL_Y + Y_REAL = Y_AXIS, + #endif + #if HAS_Z_AXIS && !HAS_REAL_Z + Z_REAL = Z_AXIS, + #endif + #if HAS_I_AXIS + I_REAL = I_AXIS, + #endif + #if HAS_J_AXIS + J_REAL = J_AXIS, + #endif + #if HAS_K_AXIS + K_REAL = K_AXIS, + #endif + #if HAS_U_AXIS + U_REAL = U_AXIS, + #endif + #if HAS_V_AXIS + V_REAL = V_AXIS, + #endif + #if HAS_W_AXIS + W_REAL = W_AXIS, + #endif + // To refer to all or none ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF }; @@ -1153,8 +1192,14 @@ class AxisBits { #define _EN_ITEM(N) bool e##N:1; REPEAT(EXTRUDERS,_EN_ITEM) #undef _EN_ITEM - #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) - bool rx:1, ry:1, rz:1; + #if HAS_REAL_X + bool rx:1; + #endif + #if HAS_REAL_Y + bool ry:1; + #endif + #if HAS_REAL_Z + bool rz:1; #endif }; // Axes X, Y, Z ... E0, E1, E2 ... RX, RY, RZ @@ -1165,8 +1210,14 @@ class AxisBits { #define _EN_ITEM(N) bool E##N:1; REPEAT(EXTRUDERS,_EN_ITEM) #undef _EN_ITEM - #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) - bool RX:1, RY:1, RZ:1; + #if HAS_REAL_X + bool RX:1; + #endif + #if HAS_REAL_Y + bool RY:1; + #endif + #if HAS_REAL_Z + bool RZ:1; #endif }; // a, b, c, e ... ra, rb, rc @@ -1177,8 +1228,14 @@ class AxisBits { REPEAT_S(1,EXTRUDERS,_EN_ITEM) #undef _EN_ITEM #endif - #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) - bool ra:1, rb:1, rc:1; + #if HAS_REAL_X + bool ra:1; + #endif + #if HAS_REAL_Y + bool rb:1; + #endif + #if HAS_REAL_Z + bool rc:1; #endif }; // A, B, C, E ... RA, RB, RC @@ -1189,8 +1246,14 @@ class AxisBits { REPEAT_S(1,EXTRUDERS,_EN_ITEM) #undef _EN_ITEM #endif - #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) - bool RA:1, RB:1, RC:1; + #if HAS_REAL_X + bool RA:1; + #endif + #if HAS_REAL_Y + bool RB:1; + #endif + #if HAS_REAL_Z + bool RC:1; #endif }; }; diff --git a/Marlin/src/inc/Conditionals-3-etc.h b/Marlin/src/inc/Conditionals-3-etc.h index 2b6500910bbd..68f34a7fd61c 100644 --- a/Marlin/src/inc/Conditionals-3-etc.h +++ b/Marlin/src/inc/Conditionals-3-etc.h @@ -584,6 +584,15 @@ #if ANY(COREYZ, COREZY) #define CORE_IS_YZ 1 #endif +#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY) + #define HAS_REAL_X 1 +#endif +#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_YX) + #define HAS_REAL_Y 1 +#endif +#if CORE_IS_XZ || CORE_IS_YZ + #define HAS_REAL_Z 1 +#endif #if CORE_IS_XY || CORE_IS_XZ || CORE_IS_YZ #define IS_CORE 1 #if CORE_IS_XY diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 761125d790d9..6be3b167db85 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -1943,7 +1943,7 @@ static_assert(NUM_SERVOS <= NUM_SERVO_PLUGS, "NUM_SERVOS (or some servo index) i #if ENABLED(DUAL_X_CARRIAGE) #if EXTRUDERS < 2 #error "DUAL_X_CARRIAGE requires 2 (or more) extruders." - #elif ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX) + #elif HAS_REAL_X #error "DUAL_X_CARRIAGE cannot be used with COREXY, COREYX, COREXZ, COREZX, MARKFORGED_YX, or MARKFORGED_XY." #elif !GOOD_AXIS_PINS(X2) #error "DUAL_X_CARRIAGE requires X2 stepper pins to be defined." diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index 59172a478740..814f195bd825 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -556,7 +556,7 @@ void menu_move() { editable.state = c.axis_sync_enabled; EDIT_ITEM(bool, MSG_FTM_AXIS_SYNC, &editable.state, []{ - queue.inject(TS(F("M493"), IAXIS_CHAR(MenuItemBase::itemIndex), 'T', int(editable.state))); + queue.inject(TS(F("M493"), IAXIS_CHAR(MenuItemBase::itemIndex), 'H', int(editable.state))); }); #if ENABLED(FTM_RESONANCE_TEST) diff --git a/Marlin/src/module/endstops.cpp b/Marlin/src/module/endstops.cpp index 323a31e32000..5269d942adc1 100644 --- a/Marlin/src/module/endstops.cpp +++ b/Marlin/src/module/endstops.cpp @@ -462,30 +462,6 @@ void Endstops::update() { #define X_MIN_TEST() TERN1(DUAL_X_CARRIAGE, stepper.last_moved_extruder == 0) // Check min for the left carriage #define X_MAX_TEST() TERN1(DUAL_X_CARRIAGE, stepper.last_moved_extruder != 0) // Check max for the right carriage - // Use HEAD for core axes, AXIS for others - #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX) - #define X_AXIS_HEAD X_HEAD - #else - #define X_AXIS_HEAD X_AXIS - #endif - #if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX) - #define Y_AXIS_HEAD Y_HEAD - #else - #define Y_AXIS_HEAD Y_AXIS - #endif - #if CORE_IS_XZ || CORE_IS_YZ - #define Z_AXIS_HEAD Z_HEAD - #else - #define Z_AXIS_HEAD Z_AXIS - #endif - - #define I_AXIS_HEAD I_AXIS - #define J_AXIS_HEAD J_AXIS - #define K_AXIS_HEAD K_AXIS - #define U_AXIS_HEAD U_AXIS - #define V_AXIS_HEAD V_AXIS - #define W_AXIS_HEAD W_AXIS - /** * Check and update endstops */ @@ -680,8 +656,8 @@ void Endstops::update() { #define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX) #endif - #define AXIS_IS_MOVING(A) TERN(FT_MOTION, ftMotion, stepper).axis_is_moving(_AXIS(A)) - #define AXIS_DIR_REV(A) !TERN(FT_MOTION, ftMotion, stepper).motor_direction(A) + #define AXIS_IS_MOVING(A) TERN(FT_MOTION, ftMotion, stepper).axis_is_moving(A##_REAL) + #define AXIS_DIR_REV(A) !TERN(FT_MOTION, ftMotion, stepper).axis_direction(A##_REAL) #if ENABLED(G38_PROBE_TARGET) // For G38 moves check the probe's pin for ALL movement @@ -704,8 +680,7 @@ void Endstops::update() { #if HAS_X_AXIS if (AXIS_IS_MOVING(X)) { - const AxisEnum x_head = TERN0(FT_MOTION, ftMotion.cfg.active) ? X_AXIS : X_AXIS_HEAD; - if (AXIS_DIR_REV(x_head)) { + if (AXIS_DIR_REV(X)) { #if HAS_X_MIN_STATE PROCESS_ENDSTOP_X(MIN); #if CORE_DIAG(XY, Y, MIN) @@ -738,8 +713,7 @@ void Endstops::update() { #if HAS_Y_AXIS if (AXIS_IS_MOVING(Y)) { - const AxisEnum y_head = TERN0(FT_MOTION, ftMotion.cfg.active) ? Y_AXIS : Y_AXIS_HEAD; - if (AXIS_DIR_REV(y_head)) { + if (AXIS_DIR_REV(Y)) { #if HAS_Y_MIN_STATE PROCESS_ENDSTOP_Y(MIN); #if CORE_DIAG(XY, X, MIN) @@ -772,8 +746,7 @@ void Endstops::update() { #if HAS_Z_AXIS if (AXIS_IS_MOVING(Z)) { - const AxisEnum z_head = TERN0(FT_MOTION, ftMotion.cfg.active) ? Z_AXIS : Z_AXIS_HEAD; - if (AXIS_DIR_REV(z_head)) { + if (AXIS_DIR_REV(Z)) { // Z- : Gantry down, bed up #if HAS_Z_MIN_STATE // If the Z_MIN_PIN is being used for the probe there's no @@ -820,7 +793,7 @@ void Endstops::update() { #if HAS_I_AXIS && HAS_I_STATE if (AXIS_IS_MOVING(I)) { - if (AXIS_DIR_REV(I_AXIS_HEAD)) { + if (AXIS_DIR_REV(I)) { #if HAS_I_MIN_STATE PROCESS_ENDSTOP(I, MIN); #endif @@ -835,7 +808,7 @@ void Endstops::update() { #if HAS_J_AXIS && HAS_J_STATE if (AXIS_IS_MOVING(J)) { - if (AXIS_DIR_REV(J_AXIS_HEAD)) { + if (AXIS_DIR_REV(J)) { #if HAS_J_MIN_STATE PROCESS_ENDSTOP(J, MIN); #endif @@ -850,7 +823,7 @@ void Endstops::update() { #if HAS_K_AXIS && HAS_K_STATE if (AXIS_IS_MOVING(K)) { - if (AXIS_DIR_REV(K_AXIS_HEAD)) { + if (AXIS_DIR_REV(K)) { #if HAS_K_MIN_STATE PROCESS_ENDSTOP(K, MIN); #endif @@ -865,7 +838,7 @@ void Endstops::update() { #if HAS_U_AXIS && HAS_U_STATE if (AXIS_IS_MOVING(U)) { - if (AXIS_DIR_REV(U_AXIS_HEAD)) { + if (AXIS_DIR_REV(U)) { #if HAS_U_MIN_STATE PROCESS_ENDSTOP(U, MIN); #endif @@ -880,7 +853,7 @@ void Endstops::update() { #if HAS_V_AXIS && HAS_V_STATE if (AXIS_IS_MOVING(V)) { - if (AXIS_DIR_REV(V_AXIS_HEAD)) { + if (AXIS_DIR_REV(V)) { #if HAS_V_MIN_STATE PROCESS_ENDSTOP(V, MIN); #endif @@ -895,7 +868,7 @@ void Endstops::update() { #if HAS_W_AXIS && HAS_W_STATE if (AXIS_IS_MOVING(W)) { - if (AXIS_DIR_REV(W_AXIS_HEAD)) { + if (AXIS_DIR_REV(W)) { #if HAS_W_MIN_STATE PROCESS_ENDSTOP(W, MIN); #endif diff --git a/Marlin/src/module/ft_motion.cpp b/Marlin/src/module/ft_motion.cpp index 3e8895ad0530..01cb0827cf37 100644 --- a/Marlin/src/module/ft_motion.cpp +++ b/Marlin/src/module/ft_motion.cpp @@ -389,16 +389,10 @@ bool FTMotion::plan_next_block() { recovery.info.current_position = current_block->start_position; #endif - // Some kinematics track axis motion in RX, RY, RZ - #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX) - stepper.last_direction_bits.rx = current_block->direction_bits.rx; - #endif - #if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX) - stepper.last_direction_bits.ry = current_block->direction_bits.ry; - #endif - #if ANY(CORE_IS_XZ, CORE_IS_YZ) - stepper.last_direction_bits.rz = current_block->direction_bits.rz; - #endif + // Some kinematics track axis motion in HX, HY, HZ + TERN_(HAS_REAL_X, stepper.last_direction_bits.rx = current_block->direction_bits.rx); + TERN_(HAS_REAL_Y, stepper.last_direction_bits.ry = current_block->direction_bits.ry); + TERN_(HAS_REAL_Z, stepper.last_direction_bits.rz = current_block->direction_bits.rz); // Cache the extruder index / axis for this block #if ANY(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER) @@ -411,7 +405,7 @@ bool FTMotion::plan_next_block() { const float totalLength = current_block->millimeters; startPos = endPos_prevBlock; - const xyze_pos_t &moveDist = current_block->distance_mm; + const ext_distance_t &moveDist = current_block->ext_distance_mm; ratio = moveDist / totalLength; // Plan the trajectory using the trajectory generator @@ -422,9 +416,15 @@ bool FTMotion::plan_next_block() { TERN_(FTM_HAS_LIN_ADVANCE, use_advance_lead = current_block->use_advance_lead); axis_move_dir = current_block->direction_bits; - #define _SET_MOVE_END(A) moving_axis_flags.A = bool(moveDist.A); + // Set moving flags for axes that have movement in this block + // For CORE kinematics: moveDist.x/.y/.z contain motor distances (a/b/c) + // HEAD movement flags need to be inferred: if either motor moves, the head moves + #define _SET_MOVE_END(A) moving_axis_flags.A = bool(moveDist.A); LOGICAL_AXIS_MAP(_SET_MOVE_END); + TERN_(HAS_REAL_X, moving_axis_flags.rx = bool(moveDist.real.x)); + TERN_(HAS_REAL_Y, moving_axis_flags.ry = bool(moveDist.real.y)); + TERN_(HAS_REAL_Z, moving_axis_flags.rz = bool(moveDist.real.z)); // If the endstop is already pressed, endstop interrupts won't invoke // endstop_triggered and the move will grind. So check here for a diff --git a/Marlin/src/module/ft_motion.h b/Marlin/src/module/ft_motion.h index 15be0154ae46..ec6699af0cff 100644 --- a/Marlin/src/module/ft_motion.h +++ b/Marlin/src/module/ft_motion.h @@ -300,11 +300,11 @@ class FTMotion { static TrajectoryType getTrajectoryType() { return TERN(FTM_POLYS, trajectoryType, TrajectoryType::TRAPEZOIDAL); } static FSTR_P getTrajectoryName(); - FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { - return cfg.active ? moving_axis_flags[axis] : TERN0(HAS_STANDARD_MOTION, stepper.axis_is_moving(axis)); + FORCE_INLINE static bool axis_is_moving(const AxisEnum real) { + return cfg.active ? moving_axis_flags[real] : TERN0(HAS_STANDARD_MOTION, stepper.axis_is_moving(real)); } - FORCE_INLINE static bool motor_direction(const AxisEnum axis) { - return cfg.active ? axis_move_dir[axis] : stepper.last_direction_bits[axis]; + FORCE_INLINE static bool axis_direction(const AxisEnum real) { + return cfg.active ? axis_move_dir[real] : stepper.last_direction_bits[real]; } // A frame of the stepping plan diff --git a/Marlin/src/module/ft_motion/shaping.cpp b/Marlin/src/module/ft_motion/shaping.cpp index bfefe77ae719..d6763a0015e2 100644 --- a/Marlin/src/module/ft_motion/shaping.cpp +++ b/Marlin/src/module/ft_motion/shaping.cpp @@ -33,10 +33,16 @@ void AxisShaping::set_axis_shaping_A( OPTARG(HAS_FTM_EI_SHAPING, const float vtol) ) { - const float K = exp(-zeta * M_PI / sqrt(1.f - sq(zeta))), - K2 = sq(K), - K3 = K2 * K, - K4 = K3 * K; + const float K = exp(-zeta * M_PI / sqrt(1.f - sq(zeta))); + #if ANY(FTM_SHAPER_ZVD, FTM_SHAPER_ZVDD, FTM_SHAPER_ZVDDD, FTM_SHAPER_EI, FTM_SHAPER_2HEI, FTM_SHAPER_3HEI, FTM_SHAPER_MZV) + const float K2 = sq(K); + #endif + #if ANY(FTM_SHAPER_ZVDD, FTM_SHAPER_ZVDDD, FTM_SHAPER_2HEI, FTM_SHAPER_3HEI) + const float K3 = K2 * K; + #endif + #if ANY(FTM_SHAPER_ZVDDD, FTM_SHAPER_3HEI) + const float K4 = K3 * K; + #endif switch (shaper) { diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 59879d6bc64e..89f34e5e1b33 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -1854,42 +1854,36 @@ bool Planner::_populate_block( #endif // PREVENT_COLD_EXTRUSION || PREVENT_LENGTHY_EXTRUDE // Compute direction bit-mask for this block + // In this context Core kinematics "real" bits pertain to Cartesian + // directions and others pertain directly to stepper directions. AxisBits dm; - #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX) - dm.rx = (steps_dist.a > 0); // True direction in X - #endif - #if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX) - dm.ry = (steps_dist.b > 0); // True direction in Y - #endif - #if ANY(CORE_IS_XZ, CORE_IS_YZ) - dm.rz = (steps_dist.c > 0); // True direction in Z - #endif + TERN_(HAS_REAL_X, dm.rx = (steps_dist.x > 0)); // True direction in X + TERN_(HAS_REAL_Y, dm.ry = (steps_dist.y > 0)); // True direction in Y + TERN_(HAS_REAL_Z, dm.rz = (steps_dist.z > 0)); // True direction in Z #if CORE_IS_XY - dm.a = (steps_dist.a + steps_dist.b > 0); // Motor A direction - dm.b = (CORESIGN(steps_dist.a - steps_dist.b) > 0); // Motor B direction - TERN_(HAS_Z_AXIS, dm.z = (steps_dist.c > 0)); // Axis Z direction + XYZ_CODE( + dm.a = (steps_dist.x + steps_dist.y) > 0, // Motor A direction + dm.b = CORESIGN(steps_dist.x - steps_dist.y) > 0, // Motor B direction + dm.z = (steps_dist.z > 0) // Axis Z direction + ); #elif CORE_IS_XZ - dm.a = (steps_dist.a + steps_dist.c > 0); // Motor A direction - dm.y = (steps_dist.b > 0); // Axis Y direction - dm.c = (CORESIGN(steps_dist.a - steps_dist.c) > 0); // Motor C direction + dm.a = (steps_dist.x + steps_dist.z) > 0; // Motor A direction + dm.y = (steps_dist.y > 0); // Axis Y direction + dm.c = (CORESIGN(steps_dist.x - steps_dist.z) > 0); // Motor C direction #elif CORE_IS_YZ - dm.x = (steps_dist.a > 0); // Axis X direction - dm.b = (steps_dist.b + steps_dist.c > 0); // Motor B direction - dm.c = (CORESIGN(steps_dist.b - steps_dist.c) > 0); // Motor C direction + dm.x = (steps_dist.x > 0); // Axis X direction + dm.b = (steps_dist.y + steps_dist.z > 0); // Motor B direction + dm.c = (CORESIGN(steps_dist.y - steps_dist.z) > 0); // Motor C direction #elif ENABLED(MARKFORGED_XY) - dm.a = (steps_dist.a TERN(MARKFORGED_INVERSE, -, +) steps_dist.b > 0); // Motor A direction - dm.b = (steps_dist.b > 0); // Motor B direction - TERN_(HAS_Z_AXIS, dm.z = (steps_dist.c > 0)); // Axis Z direction + dm.a = (steps_dist.x TERN(MARKFORGED_INVERSE, -, +) steps_dist.y > 0); // Motor A direction + dm.b = (steps_dist.y > 0); // Motor B direction + TERN_(HAS_Z_AXIS, dm.z = (steps_dist.z > 0)); // Axis Z direction #elif ENABLED(MARKFORGED_YX) - dm.a = (steps_dist.a > 0); // Motor A direction - dm.b = (steps_dist.b TERN(MARKFORGED_INVERSE, -, +) steps_dist.a > 0); // Motor B direction - TERN_(HAS_Z_AXIS, dm.z = (steps_dist.c > 0)); // Axis Z direction + dm.a = (steps_dist.x > 0); // Motor A direction + dm.b = (steps_dist.y TERN(MARKFORGED_INVERSE, -, +) steps_dist.x > 0); // Motor B direction + TERN_(HAS_Z_AXIS, dm.z = (steps_dist.z > 0)); // Axis Z direction #else - XYZ_CODE( - dm.x = (steps_dist.a > 0), - dm.y = (steps_dist.b > 0), - dm.z = (steps_dist.c > 0) - ); + XYZ_CODE(dm.x = (steps_dist.x > 0), dm.y = (steps_dist.y > 0), dm.z = (steps_dist.z > 0)); #endif SECONDARY_AXIS_CODE( @@ -1965,82 +1959,86 @@ bool Planner::_populate_block( /** * This part of the code calculates the total length of the movement. * For Cartesian bots, the distance in XY axes equals the X_AXIS/Y_AXIS joint displacement. - * But for geometries like CORE_XY that is not true. For these machines we need to create 2 additional variables, named X_HEAD and Y_HEAD, to store the displacent of the head along the X and Y axes in a cartesian coordinate system. - * The displacement of the head along the axes of the cartesian coordinate system has to be calculated from "X_AXIS" and "Y_AXIS" (should be renamed to A_JOINT and B_JOINT) + * For Core/H-bot geometries we use X_REAL and Y_REAL to store the real XY displacement of the head in Cartesian coordinates. + * The Cartesian head displacement is calculated from a combined ABC stepper positions. * For the joint displacements use forward kinematics (A=X+Y and B=X-Y in the case of CORE_XY). * Next we can calculate the total movement length and apply the desired speed. */ - struct DistanceMM : abce_float_t { - #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) - struct { float x, y, z; } head; - #endif - } dist_mm; + ext_distance_t dist_mm; - #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - dist_mm.head.x = steps_dist.a * mm_per_step[A_AXIS]; - dist_mm.head.y = steps_dist.b * mm_per_step[B_AXIS]; - TERN_(HAS_Z_AXIS, dist_mm.z = steps_dist.c * mm_per_step[Z_AXIS]); + #if HAS_X_AXIS + const float dx = steps_dist.x * mm_per_step[X_AXIS]; // Axis X or Tower A Steps + #endif + #if HAS_Y_AXIS + const float dy = steps_dist.y * mm_per_step[Y_AXIS]; // Axis Y or Tower B Steps + #endif + #if HAS_Z_AXIS + const float dz = steps_dist.z * mm_per_step[Z_AXIS]; // Axis Z or Tower C Steps #endif #if CORE_IS_XY - dist_mm.a = (steps_dist.a + steps_dist.b) * mm_per_step[A_AXIS]; - dist_mm.b = CORESIGN(steps_dist.a - steps_dist.b) * mm_per_step[B_AXIS]; + XYZ_CODE( + dist_mm.a = dx + dy, + dist_mm.b = CORESIGN(dx - dy), + dist_mm.z = dz + ); #elif CORE_IS_XZ - dist_mm.head.x = steps_dist.a * mm_per_step[A_AXIS]; - dist_mm.y = steps_dist.b * mm_per_step[Y_AXIS]; - dist_mm.head.z = steps_dist.c * mm_per_step[C_AXIS]; - dist_mm.a = (steps_dist.a + steps_dist.c) * mm_per_step[A_AXIS]; - dist_mm.c = CORESIGN(steps_dist.a - steps_dist.c) * mm_per_step[C_AXIS]; + dist_mm.a = dx + dz, + dist_mm.y = dy, + dist_mm.c = CORESIGN(dx - dz) #elif CORE_IS_YZ - dist_mm.x = steps_dist.a * mm_per_step[X_AXIS]; - dist_mm.head.y = steps_dist.b * mm_per_step[B_AXIS]; - dist_mm.head.z = steps_dist.c * mm_per_step[C_AXIS]; - dist_mm.b = (steps_dist.b + steps_dist.c) * mm_per_step[B_AXIS]; - dist_mm.c = CORESIGN(steps_dist.b - steps_dist.c) * mm_per_step[C_AXIS]; + dist_mm.x = dx; + dist_mm.b = dy + dz; + dist_mm.c = CORESIGN(dy - dz); #elif ENABLED(MARKFORGED_XY) - dist_mm.a = (steps_dist.a TERN(MARKFORGED_INVERSE, +, -) steps_dist.b) * mm_per_step[A_AXIS]; - dist_mm.b = steps_dist.b * mm_per_step[B_AXIS]; + XYZ_CODE( + dist_mm.a = dx TERN(MARKFORGED_INVERSE, +, -) dy, + dist_mm.b = dy, + dist_mm.z = dz + ); #elif ENABLED(MARKFORGED_YX) - dist_mm.a = steps_dist.a * mm_per_step[A_AXIS]; - dist_mm.b = (steps_dist.b TERN(MARKFORGED_INVERSE, +, -) steps_dist.a) * mm_per_step[B_AXIS]; - #else XYZ_CODE( - dist_mm.a = steps_dist.a * mm_per_step[A_AXIS], - dist_mm.b = steps_dist.b * mm_per_step[B_AXIS], - dist_mm.c = steps_dist.c * mm_per_step[C_AXIS] + dist_mm.a = dx, + dist_mm.b = dy TERN(MARKFORGED_INVERSE, +, -) dx, + dist_mm.z = dz ); + #else + // Cartesian, Delta, SCARA, etc. + XYZ_CODE(dist_mm.a = dx, dist_mm.b = dy, dist_mm.c = dz); #endif SECONDARY_AXIS_CODE( - dist_mm.i = steps_dist.i * mm_per_step[I_AXIS], dist_mm.j = steps_dist.j * mm_per_step[J_AXIS], dist_mm.k = steps_dist.k * mm_per_step[K_AXIS], - dist_mm.u = steps_dist.u * mm_per_step[U_AXIS], dist_mm.v = steps_dist.v * mm_per_step[V_AXIS], dist_mm.w = steps_dist.w * mm_per_step[W_AXIS] + dist_mm.i = steps_dist.i * mm_per_step[I_AXIS], dist_mm.j = steps_dist.j * mm_per_step[J_AXIS], + dist_mm.k = steps_dist.k * mm_per_step[K_AXIS], dist_mm.u = steps_dist.u * mm_per_step[U_AXIS], + dist_mm.v = steps_dist.v * mm_per_step[V_AXIS], dist_mm.w = steps_dist.w * mm_per_step[W_AXIS] ); - TERN_(HAS_EXTRUDERS, dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]); + TERN_(HAS_REAL_X, dist_mm.real.x = dx); + TERN_(HAS_REAL_Y, dist_mm.real.y = dy); + TERN_(HAS_REAL_Z, dist_mm.real.z = dz); + TERN_(HAS_EXTRUDERS, dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]); TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += dist_mm.e); + TERN_(FT_MOTION, block->ext_distance_mm = dist_mm); // Store the distance for all axes in mm for this block + #if HAS_ROTATIONAL_AXES bool cartesian_move = hints.cartesian_move; #endif + // Determine linear distance for block->millimeters + if (!XYZ_HAS_ENOUGH_STEPS(block)) { block->millimeters = TERN0(HAS_EXTRUDERS, ABS(dist_mm.e)); } else { - if (hints.millimeters) + // Use a provided move length (e.g., always provided by Kinematic robots) + if (/* ANY(DELTA, IS_SCARA, TPARA) || */ hints.millimeters) block->millimeters = hints.millimeters; else { + // Calculate move length from axis positions const xyze_pos_t displacement = LOGICAL_AXIS_ARRAY( dist_mm.e, - #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - dist_mm.head.x, dist_mm.head.y, dist_mm.z, - #elif CORE_IS_XZ - dist_mm.head.x, dist_mm.y, dist_mm.head.z, - #elif CORE_IS_YZ - dist_mm.x, dist_mm.head.y, dist_mm.head.z, - #else - dist_mm.x, dist_mm.y, dist_mm.z, - #endif + dx, dy, dz, dist_mm.i, dist_mm.j, dist_mm.k, dist_mm.u, dist_mm.v, dist_mm.w ); @@ -2051,19 +2049,19 @@ bool Planner::_populate_block( /** * At this point at least one of the axes has more steps than * MIN_STEPS_PER_SEGMENT, ensuring the segment won't get dropped as - * zero-length. It's important to not apply corrections - * to blocks that would get dropped! + * zero-length. It's important to not apply corrections to blocks + * that would get dropped! * - * A correction function is permitted to add steps to an axis, it - * should *never* remove steps! + * A correction function is permitted to add steps to an axis, but + * it should *never* remove steps! */ TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(steps_dist, dm, block)); } - TERN_(FT_MOTION, block->distance_mm = dist_mm); // Store the distance for all axes in mm for this block - TERN_(HAS_EXTRUDERS, block->steps.e = esteps); + // Set the block's Step Event Count based from the axis with the most steps + block->step_event_count = ( #if NUM_AXES _MAX(LOGICAL_AXIS_LIST(esteps, @@ -2076,9 +2074,11 @@ bool Planner::_populate_block( #endif ); - // Bail if this is a zero-length block + // Bail if this is a "zero-length" block if (block->step_event_count < MIN_STEPS_PER_SEGMENT) return false; + E_TERN_(block->extruder = extruder); + TERN_(MIXING_EXTRUDER, mixer.populate_block(block->b_color)); #if HAS_FAN @@ -2090,8 +2090,6 @@ bool Planner::_populate_block( block->e_to_p_pressure = baricuda_e_to_p_pressure; #endif - E_TERN_(block->extruder = extruder); - #if ENABLED(AUTO_POWER_CONTROL) if (XYZ_HAS_STEPS(block)) powerManager.power_on(); #endif @@ -2983,6 +2981,7 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const feedRate_t fr_mm_s // Cartesian XYZ to kinematic ABC, stored in global 'delta' inverse_kinematics(machine); + // Provide known Cartesian length in the hints structure PlannerHints ph = hints; if (!hints.millimeters) ph.millimeters = get_move_distance(xyze_pos_t(cart_dist_mm) OPTARG(HAS_ROTATIONAL_AXES, ph.cartesian_move)); diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 02150451b687..46def8542789 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -190,6 +190,52 @@ typedef struct { #endif +typedef struct DistanceMM : abce_float_t { + #if ANY(HAS_REAL_X, HAS_REAL_Y, HAS_REAL_Z) + struct { + #if HAS_REAL_X + float x; + #endif + #if HAS_REAL_Y + float y; + #endif + #if HAS_REAL_Z + float z; + #endif + } real; + #endif + const float& operator[](const int n) const { + switch (n) { + #if HAS_REAL_X + case X_REAL: return real.x; + #endif + #if HAS_REAL_Y + case Y_REAL: return real.y; + #endif + #if HAS_REAL_Z + case Z_REAL: return real.z; + #endif + default: break; + } + return pos[n]; + } + float& operator[](const int n) { + switch (n) { + #if HAS_REAL_X + case X_REAL: return real.x; + #endif + #if HAS_REAL_Y + case Y_REAL: return real.y; + #endif + #if HAS_REAL_Z + case Z_REAL: return real.z; + #endif + default: break; + } + return pos[n]; + } +} ext_distance_t; + /** * struct block_t * @@ -262,7 +308,7 @@ typedef struct PlannerBlock { AxisBits direction_bits; // Direction bits set for this block, where 1 is negative motion #if ENABLED(FT_MOTION) - xyze_pos_t distance_mm; // The distance traveled in mm along each axis + ext_distance_t ext_distance_mm; // The distance traveled in mm along each axis #endif #if ANY(SMOOTH_LIN_ADVANCE, FTM_HAS_LIN_ADVANCE) diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index cb339830d3e5..bc049a3492eb 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -682,7 +682,7 @@ void Stepper::disable_all_steppers() { // Set a single axis direction based on the last set flags. // A direction bit of "1" indicates forward or positive motion. #define SET_STEP_DIR(A) do{ \ - const bool fwd = motor_direction(_AXIS(A)); \ + const bool fwd = axis_direction(_AXIS(A)); \ A##_APPLY_DIR(fwd, false); \ count_direction[_AXIS(A)] = fwd ? 1 : -1; \ }while(0) @@ -2389,19 +2389,12 @@ void Stepper::isr() { #endif // Set flags for all axes that move in this block - // These are set per-axis, not per-stepper AxisBits didmove; - NUM_AXIS_CODE( - if (X_MOVE_TEST) didmove.a = true, // Cartesian X or Kinematic A - if (Y_MOVE_TEST) didmove.b = true, // Cartesian Y or Kinematic B - if (Z_MOVE_TEST) didmove.c = true, // Cartesian Z or Kinematic C - if (!!current_block->steps.i) didmove.i = true, - if (!!current_block->steps.j) didmove.j = true, - if (!!current_block->steps.k) didmove.k = true, - if (!!current_block->steps.u) didmove.u = true, - if (!!current_block->steps.v) didmove.v = true, - if (!!current_block->steps.w) didmove.w = true - ); + #define _DID_MOVE(A) didmove.A = bool(current_block->steps.A); + MAIN_AXIS_MAP(_DID_MOVE); + TERN_(HAS_REAL_X, didmove.rx = X_MOVE_TEST); // Cartesian X + TERN_(HAS_REAL_Y, didmove.ry = Y_MOVE_TEST); // ... Y + TERN_(HAS_REAL_Z, didmove.rz = Z_MOVE_TEST); // ... Z axis_did_move = didmove; } @@ -2563,7 +2556,7 @@ void Stepper::isr() { const bool forward_e = la_step_rate < step_rate; la_interval = calc_timer_interval((forward_e ? step_rate - la_step_rate : la_step_rate - step_rate) >> current_block->la_scaling); - if (forward_e != motor_direction(E_AXIS)) { + if (forward_e != axis_direction(E_AXIS)) { last_direction_bits.toggle(E_AXIS); count_direction.e *= -1; @@ -3009,7 +3002,7 @@ void Stepper::isr() { #endif la_interval = calc_timer_interval(uint32_t(ABS(step_rate))); - if (forward_e != motor_direction(E_AXIS)) { + if (forward_e != axis_direction(E_AXIS)) { last_direction_bits.toggle(E_AXIS); count_direction.e *= -1; DIR_WAIT_BEFORE(); @@ -3595,13 +3588,13 @@ int32_t Stepper::triggered_position(const AxisEnum axis) { * Reporting */ -#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA) +#if ANY(HAS_REAL_X, IS_SCARA, DELTA) #define SAYS_A 1 #endif -#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA, POLAR) +#if ANY(HAS_REAL_Y, IS_SCARA, DELTA, POLAR) #define SAYS_B 1 #endif -#if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA) +#if ANY(HAS_REAL_Z, DELTA) #define SAYS_C 1 #endif diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index 3d9820a4969a..18ab27ab3af7 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -657,18 +657,18 @@ class Stepper { // Quickly stop all steppers FORCE_INLINE static void quick_stop() { abort_current_block = true; } - // The direction of a single motor. A true result indicates forward or positive motion. - FORCE_INLINE static bool motor_direction(const AxisEnum axis) { return last_direction_bits[axis]; } + // The direction of a single motor and/or real axis. A true result indicates forward or positive motion. + FORCE_INLINE static bool axis_direction(const AxisEnum real) { return last_direction_bits[real]; } #if HAS_STANDARD_MOTION - // The last movement direction was not null on the specified axis. Note that motor direction is not necessarily the same. - FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { return axis_did_move[axis]; } + // The last segment moved on the specified motor and/or real axis. + FORCE_INLINE static bool axis_is_moving(const AxisEnum real) { return axis_did_move[real]; } #endif // Handle a triggered endstop static void endstop_triggered(const AxisEnum axis); - // Triggered position of an axis in steps + // Triggered position of an axis in steps, converted as needed from Core kinematics static int32_t triggered_position(const AxisEnum axis); #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index f0ca49ef6612..a4744c2badaf 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -1938,7 +1938,8 @@ void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_T #endif temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_hotend_preheating(e)) - && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0; + && (temp_hotend[e].celsius < temp_range[e].maxtemp) + ? (int)get_pid_output_hotend(e) >> 1 : 0; #if WATCH_HOTENDS // Make sure temperature is increasing