mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2026-01-03 21:30:31 -07:00
FTM, fix TMC2208 bug on E axis
This commit is contained in:
parent
c45354a38c
commit
e63e7ef4c7
2 changed files with 82 additions and 21 deletions
|
|
@ -671,6 +671,7 @@ void Stepper::disable_all_steppers() {
|
|||
#if ENABLED(FT_MOTION)
|
||||
// We'll compare the updated DIR bits to the last set state
|
||||
static AxisBits last_set_direction;
|
||||
xyze_int_t Stepper::pending_hysteresis_steps ={0}; // Accumulated steps offset due to hysteresis delays
|
||||
#endif
|
||||
|
||||
// Set a single axis direction based on the last set flags.
|
||||
|
|
@ -1809,6 +1810,48 @@ void Stepper::isr() {
|
|||
#define ISR_MULTI_STEPS 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ========================================
|
||||
* Hysteresis Macros for TMC Driver Safety
|
||||
* ========================================
|
||||
* When input shaping is active, direction changes can occur rapidly.
|
||||
* This hysteresis prevents TMC2208/TMC2225/TMC5160 shutdown bugs (#16076)
|
||||
* by increasing the step detection threshold, giving the driver time to
|
||||
* stabilize phase currents.
|
||||
*/
|
||||
|
||||
// Define hysteresis values based on driver type (64 units = ~0.5 step)
|
||||
#if AXIS_DRIVER_TYPE_X(TMC2208) || AXIS_DRIVER_TYPE_X(TMC2208_STANDALONE) || \
|
||||
AXIS_DRIVER_TYPE_X(TMC5160) || AXIS_DRIVER_TYPE_X(TMC5160_STANDALONE)
|
||||
#define HYSTERESIS_X 64
|
||||
#else
|
||||
#define HYSTERESIS_X 0
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Y(TMC2208) || AXIS_DRIVER_TYPE_Y(TMC2208_STANDALONE) || \
|
||||
AXIS_DRIVER_TYPE_Y(TMC5160) || AXIS_DRIVER_TYPE_Y(TMC5160_STANDALONE)
|
||||
#define HYSTERESIS_Y 64
|
||||
#else
|
||||
#define HYSTERESIS_Y 0
|
||||
#endif
|
||||
|
||||
#if AXIS_DRIVER_TYPE_Z(TMC2208) || AXIS_DRIVER_TYPE_Z(TMC2208_STANDALONE) || \
|
||||
AXIS_DRIVER_TYPE_Z(TMC5160) || AXIS_DRIVER_TYPE_Z(TMC5160_STANDALONE)
|
||||
#define HYSTERESIS_Z 64
|
||||
#else
|
||||
#define HYSTERESIS_Z 0
|
||||
#endif
|
||||
|
||||
#if HAS_E_DRIVER(TMC2208) || HAS_E_DRIVER(TMC2208_STANDALONE) || \
|
||||
HAS_E_DRIVER(TMC5160) || HAS_E_DRIVER(TMC5160_STANDALONE)
|
||||
#define HYSTERESIS_E 64
|
||||
#else
|
||||
#define HYSTERESIS_E 0
|
||||
#endif
|
||||
|
||||
#define _HYSTERESIS(AXIS) HYSTERESIS_##AXIS
|
||||
#define HYSTERESIS(AXIS) _HYSTERESIS(AXIS)
|
||||
|
||||
#if HAS_STANDARD_MOTION
|
||||
/**
|
||||
* This phase of the ISR should ONLY create the pulses for the steppers.
|
||||
|
|
@ -1883,27 +1926,7 @@ void Stepper::isr() {
|
|||
// the TMC2208 / TMC2225 shutdown bug (#16076), add a half step hysteresis
|
||||
// in each direction. This results in the position being off by half an
|
||||
// average half step during travel but correct at the end of each segment.
|
||||
#if AXIS_DRIVER_TYPE_X(TMC2208) || AXIS_DRIVER_TYPE_X(TMC2208_STANDALONE) || \
|
||||
AXIS_DRIVER_TYPE_X(TMC5160) || AXIS_DRIVER_TYPE_X(TMC5160_STANDALONE)
|
||||
#define HYSTERESIS_X 64
|
||||
#else
|
||||
#define HYSTERESIS_X 0
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Y(TMC2208) || AXIS_DRIVER_TYPE_Y(TMC2208_STANDALONE) || \
|
||||
AXIS_DRIVER_TYPE_Y(TMC5160) || AXIS_DRIVER_TYPE_Y(TMC5160_STANDALONE)
|
||||
#define HYSTERESIS_Y 64
|
||||
#else
|
||||
#define HYSTERESIS_Y 0
|
||||
#endif
|
||||
#if AXIS_DRIVER_TYPE_Z(TMC2208) || AXIS_DRIVER_TYPE_Z(TMC2208_STANDALONE) || \
|
||||
AXIS_DRIVER_TYPE_Z(TMC5160) || AXIS_DRIVER_TYPE_Z(TMC5160_STANDALONE)
|
||||
#define HYSTERESIS_Z 64
|
||||
#else
|
||||
#define HYSTERESIS_Z 0
|
||||
#endif
|
||||
#define _HYSTERESIS(AXIS) HYSTERESIS_##AXIS
|
||||
#define HYSTERESIS(AXIS) _HYSTERESIS(AXIS)
|
||||
|
||||
|
||||
#define PULSE_PREP_SHAPING(AXIS, DELTA_ERROR, DIVIDEND) do{ \
|
||||
int16_t de = DELTA_ERROR + (DIVIDEND); \
|
||||
const bool step_fwd = de >= (64 + HYSTERESIS(AXIS)), \
|
||||
|
|
@ -3603,6 +3626,38 @@ void Stepper::report_positions() {
|
|||
AxisBits &step_bits = ftMotion.stepping.step_bits; // Aliases for prettier code
|
||||
AxisBits &dir_bits = ftMotion.stepping.dir_bits;
|
||||
|
||||
/**
|
||||
* For axes with TMC drivers vulnerable to shutdown (TMC2208/2225/5160),
|
||||
* apply hysteresis to direction changes, just like PULSE_PREP_SHAPING
|
||||
* in the standard motion system.
|
||||
*/
|
||||
|
||||
#if (HYSTERESIS_E > 0)
|
||||
/**
|
||||
* When a direction change is detected on E axis:
|
||||
* 1. Update last_direction_bits
|
||||
* 2. Accumulate step counter for the new direction
|
||||
* 3. Apply WAIT_BEFORE only when accumulated steps >= HYSTERESIS threshold
|
||||
* 4. Single-direction blocks pass through without suppression
|
||||
*/
|
||||
|
||||
if (step_bits.E && (last_direction_bits.E != dir_bits.E)) {
|
||||
// Direction change detected - UPDATE immediately to avoid re-accumulation
|
||||
last_direction_bits.E = dir_bits.E;
|
||||
|
||||
if (++pending_hysteresis_steps.E >= HYSTERESIS_E) {
|
||||
// Threshold reached - apply direction change with TMC protection
|
||||
{ USING_TIMED_PULSE(); START_TIMED_PULSE(); AWAIT_LOW_PULSE(); }
|
||||
DIR_WAIT_BEFORE();
|
||||
pending_hysteresis_steps.E = 0;
|
||||
} else {
|
||||
step_bits.E = 0;
|
||||
}
|
||||
} else {
|
||||
pending_hysteresis_steps.E = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
USING_TIMED_PULSE();
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -406,6 +406,12 @@ class Stepper {
|
|||
static AxisBits axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
|
||||
#endif
|
||||
|
||||
// FT_MOTION Hysteresis tracking for direction changes
|
||||
#if ENABLED(FT_MOTION) && (HAS_E_DRIVER(TMC2208) || HAS_E_DRIVER(TMC2208_STANDALONE) || \
|
||||
HAS_E_DRIVER(TMC5160) || HAS_E_DRIVER(TMC5160_STANDALONE))
|
||||
static xyze_int_t pending_hysteresis_steps; // Accumulated steps offset due to hysteresis delays
|
||||
#endif
|
||||
|
||||
static bool abort_current_block; // Signals to the stepper that current block should be aborted
|
||||
|
||||
// Motor locking for independent movement of multi-stepper axes
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue