diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 75c4efa743..036e426de6 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -359,6 +359,34 @@ #if ANY(FTM_SHAPER_EI, FTM_SHAPER_2HEI, FTM_SHAPER_3HEI) #define HAS_FTM_EI_SHAPING 1 #endif + + /** + * TMC2208 Direction-Flip Delay + * + * Some TMC2208 / TMC2208_STANDALONE drivers may require a short delay after a DIR change + * to prevent a standstill error, especially when using stealthChop (the standalone default). + * + * When enabled for an axis, FT Motion will hold that axis for > 750µs after a DIR change + * by holding its trajectory coordinate constant for a multiple of FTM_TS frames. For the + * default FTM_FS = 1000, it is a single 1ms frame. + * + * Other axes keep moving normally, and the wait is canceled if the axis flips again. + */ + #if AXIS_DRIVER_TYPE_X(TMC2208) || AXIS_DRIVER_TYPE_X(TMC2208_STANDALONE) + #define FTM_DIR_CHANGE_HOLD_X 1 + #endif + #if AXIS_DRIVER_TYPE_Y(TMC2208) || AXIS_DRIVER_TYPE_Y(TMC2208_STANDALONE) + #define FTM_DIR_CHANGE_HOLD_Y 1 + #endif + #if AXIS_DRIVER_TYPE_Z(TMC2208) || AXIS_DRIVER_TYPE_Z(TMC2208_STANDALONE) + #define FTM_DIR_CHANGE_HOLD_Z 1 + #endif + #if HAS_E_DRIVER(TMC2208) || HAS_E_DRIVER(TMC2208_STANDALONE) + #define FTM_DIR_CHANGE_HOLD_E 1 + #endif + #if ANY(FTM_DIR_CHANGE_HOLD_X, FTM_DIR_CHANGE_HOLD_Y, FTM_DIR_CHANGE_HOLD_Z, FTM_DIR_CHANGE_HOLD_E) + #define HAS_FTM_DIR_CHANGE_HOLD 1 + #endif #endif // Standard Motion diff --git a/Marlin/src/module/ft_motion.cpp b/Marlin/src/module/ft_motion.cpp index f9b7c86998..093fa3b12e 100644 --- a/Marlin/src/module/ft_motion.cpp +++ b/Marlin/src/module/ft_motion.cpp @@ -75,6 +75,10 @@ xyze_pos_t FTMotion::startPos, // (mm) Start position of bl xyze_float_t FTMotion::ratio; // (ratio) Axis move ratio of block float FTMotion::tau = 0.0f; // (s) Time since start of block bool FTMotion::fastForwardUntilMotion = false; // Fast forward time if there is no motion +#if HAS_FTM_DIR_CHANGE_HOLD + xyze_uint_t FTMotion::hold_frames; // Briefly hold motion after direction changes to fix TMC2208 bug + AxisBits FTMotion::last_traj_dir; // Direction of the last trajectory point after shaping, smoothing, ... +#endif // Trajectory generators TrapezoidalTrajectoryGenerator FTMotion::trapezoidalGenerator; @@ -245,7 +249,11 @@ void FTMotion::reset() { TERN_(DISTINCT_E_FACTORS, block_extruder_axis = E_AXIS); moving_axis_flags.reset(); - + last_target_traj.reset(); + #if HAS_FTM_DIR_CHANGE_HOLD + last_traj_dir.reset(); + hold_frames.reset(); + #endif if (did_suspend) stepper.wake_up(); } @@ -412,7 +420,7 @@ 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 = moveDist.A ? true : false; + #define _SET_MOVE_END(A) moving_axis_flags.A = bool(moveDist.A); LOGICAL_AXIS_MAP(_SET_MOVE_END); @@ -612,7 +620,38 @@ void FTMotion::fill_stepper_plan_buffer() { // It eliminates idle time when changing smoothing time or shapers and speeds up homing and bed leveling. } else { + + #if HAS_FTM_DIR_CHANGE_HOLD + + // When a flip is detected (and the axis is in stealthChop or is standalone), + // hold that axis' trajectory coordinate constant for at least 750µs. + + #define DIR_FLIP_HOLD_S 0.000'750f + static constexpr uint32_t dir_flip_hold_frames = DIR_FLIP_HOLD_S / (FTM_TS + 1); + + auto start_hold_if_dir_flip = [&](const AxisEnum a) { + const bool dir = traj_coords[a] > last_target_traj[a], + moved = traj_coords[a] != last_target_traj[a], + flipped = moved && (dir != last_traj_dir[a]), + hold = !moved || (flipped && hold_frames[a] > 0); + if (hold) { + if (hold_frames[a]) hold_frames[a]--; + traj_coords[a] = last_target_traj[a]; + } + else { + last_traj_dir[a] = dir; + hold_frames[a] = dir_flip_hold_frames; + } + }; + + #define START_HOLD_IF_DIR_FLIP(A) TERN_(FTM_DIR_CHANGE_HOLD_##A, start_hold_if_dir_flip(_AXIS(A))); + + LOGICAL_AXIS_MAP(START_HOLD_IF_DIR_FLIP); + + #endif // HAS_FTM_DIR_CHANGE_HOLD + fastForwardUntilMotion = false; + // Calculate and store stepper plan in buffer stepping_enqueue(traj_coords); } diff --git a/Marlin/src/module/ft_motion.h b/Marlin/src/module/ft_motion.h index 1d2849f289..ff7e118d1e 100644 --- a/Marlin/src/module/ft_motion.h +++ b/Marlin/src/module/ft_motion.h @@ -332,6 +332,11 @@ class FTMotion { static float tau; // (s) Time since start of block static bool fastForwardUntilMotion; // Fast forward time if there is no motion + #if HAS_FTM_DIR_CHANGE_HOLD + static xyze_uint_t hold_frames; // Briefly hold motion after direction changes to fix TMC2208 bug + static AxisBits last_traj_dir; // Direction of the last trajectory point after shaping, smoothing, ... + #endif + // Trajectory generators static TrapezoidalTrajectoryGenerator trapezoidalGenerator; #if ENABLED(FTM_POLYS) diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 2a10c83800..84924b6f65 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -3376,6 +3376,10 @@ void Stepper::init() { #endif // HAS_ZV_SHAPING +/** + * Position + */ + /** * Set the stepper positions directly in steps * @@ -3502,20 +3506,11 @@ void Stepper::set_axis_position(const AxisEnum a, const int32_t &v) { AVR_ATOMIC_SECTION_END(); } -#endif // HAS_EXTRUDERS +#endif -#if ENABLED(FT_MOTION) - - void Stepper::ftMotion_syncPosition() { - planner.synchronize(); - - // Update stepper positions from the planner - AVR_ATOMIC_SECTION_START(); - count_position = planner.position; - AVR_ATOMIC_SECTION_END(); - } - -#endif // FT_MOTION +/** + * Endstops + */ /** * Record stepper positions and discard the rest of the current block @@ -3561,6 +3556,10 @@ int32_t Stepper::triggered_position(const AxisEnum axis) { return v; } +/** + * Reporting + */ + #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA) #define SAYS_A 1 #endif @@ -3592,6 +3591,15 @@ void Stepper::report_positions() { #if ENABLED(FT_MOTION) + void Stepper::ftMotion_syncPosition() { + planner.synchronize(); + + // Update stepper positions from the planner + AVR_ATOMIC_SECTION_START(); + count_position = planner.position; + AVR_ATOMIC_SECTION_END(); + } + /** * Run stepping for FT Motion from the Stepper ISR at regular short intervals. * @@ -3686,6 +3694,10 @@ void Stepper::report_positions() { #endif // FT_MOTION +/** + * Babystepping + */ + #if ENABLED(BABYSTEPPING) #define _ENABLE_AXIS(A) enable_axis(_AXIS(A)) diff --git a/buildroot/tests/STM32F103RC_btt b/buildroot/tests/STM32F103RC_btt index 7a03dd64fa..9e6019bb91 100755 --- a/buildroot/tests/STM32F103RC_btt +++ b/buildroot/tests/STM32F103RC_btt @@ -11,11 +11,13 @@ set -e # restore_configs opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \ - X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2209 Z_DRIVER_TYPE TMC2209 E0_DRIVER_TYPE TMC2209 \ + X_DRIVER_TYPE TMC2208 Y_DRIVER_TYPE TMC2208 Z_DRIVER_TYPE TMC2208 E0_DRIVER_TYPE TMC2208 \ X_CURRENT_HOME X_CURRENT/2 Y_CURRENT_HOME Y_CURRENT/2 Z_CURRENT_HOME Y_CURRENT/2 -opt_enable CR10_STOCKDISPLAY PINS_DEBUGGING Z_IDLE_HEIGHT EDITABLE_HOMING_CURRENT \ - INPUT_SHAPING_X INPUT_SHAPING_Y FT_MOTION FT_MOTION_MENU FTM_RESONANCE_TEST EMERGENCY_PARSER \ +opt_enable CR10_STOCKDISPLAY EMERGENCY_PARSER Z_IDLE_HEIGHT EDITABLE_HOMING_CURRENT \ + INPUT_SHAPING_X INPUT_SHAPING_Y \ + FT_MOTION FT_MOTION_MENU FTM_RESONANCE_TEST \ BIQU_MICROPROBE_V1 PROBE_ENABLE_DISABLE Z_SAFE_HOMING AUTO_BED_LEVELING_BILINEAR \ - ADAPTIVE_STEP_SMOOTHING LIN_ADVANCE SMOOTH_LIN_ADVANCE NONLINEAR_EXTRUSION + ADAPTIVE_STEP_SMOOTHING LIN_ADVANCE SMOOTH_LIN_ADVANCE NONLINEAR_EXTRUSION \ + PINS_DEBUGGING opt_disable FTM_POLYS -exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - TMC2209 HW Serial, FT_MOTION w/out FTM_POLYS" "$3" +exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - TMC2208 HW Serial, FT_MOTION w/out FTM_POLYS" "$3"