mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2026-01-04 21:57:44 -07:00
🐛 Limit FTM reset-on-threshold E pos to maintain precision (#28192)
This commit is contained in:
parent
a889336b25
commit
9eb82d8894
3 changed files with 37 additions and 0 deletions
|
|
@ -349,6 +349,7 @@ bool FTMotion::plan_next_block() {
|
|||
if (current_block->is_sync_pos()) stepper._set_position(current_block->position);
|
||||
continue;
|
||||
}
|
||||
ensure_float_precision();
|
||||
|
||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||
recovery.info.sdpos = current_block->sdpos;
|
||||
|
|
@ -400,6 +401,39 @@ bool FTMotion::plan_next_block() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure extruder position stays within floating point precision bounds.
|
||||
* Float32 numbers have 23 bits of precision, so the minimum increment ("resolution") around a value x is:
|
||||
* resolution = 2^(floor(log2(|x|)) - 23)
|
||||
* By resetting at ±1'000mm (1 meter), we get a minimum resolution of ~ 0.00006mm, enough for smoothing to work well.
|
||||
*/
|
||||
void FTMotion::ensure_float_precision() {
|
||||
constexpr float FTM_POSITION_WRAP_THRESHOLD = 1'000.0f; // (mm) Reset when position exceeds this to prevent floating point precision loss
|
||||
#if HAS_EXTRUDERS
|
||||
if (fabs(endPos_prevBlock.E) >= FTM_POSITION_WRAP_THRESHOLD) {
|
||||
const float offset = -endPos_prevBlock.E;
|
||||
endPos_prevBlock.E += offset;
|
||||
|
||||
// Offset extruder shaping buffer
|
||||
#if ALL(HAS_FTM_SHAPING, FTM_SHAPER_E)
|
||||
for (uint32_t i = 0; i < FTM_ZMAX; ++i) shaping.E.d_zi[i] += offset;
|
||||
#endif
|
||||
|
||||
// Offset extruder smoothing buffer
|
||||
#if ENABLED(FTM_SMOOTHING)
|
||||
for (uint8_t i = 0; i < FTM_SMOOTHING_ORDER; ++i) smoothing.E.smoothing_pass[i] += offset;
|
||||
#endif
|
||||
|
||||
// Offset linear advance previous position
|
||||
prev_traj_e += offset;
|
||||
|
||||
// Offset stepper current position
|
||||
const int64_t delta_steps_q48_16 = offset * planner.settings.axis_steps_per_mm[block_extruder_axis] * (1ULL << 16);
|
||||
stepping.curr_steps_q48_16.E += delta_steps_q48_16;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
xyze_float_t FTMotion::calc_traj_point(const float dist) {
|
||||
xyze_float_t traj_coords;
|
||||
#define _SET_TRAJ(q) traj_coords.q = startPos.q + ratio.q * dist;
|
||||
|
|
|
|||
|
|
@ -280,6 +280,7 @@ class FTMotion {
|
|||
static void fill_stepper_plan_buffer();
|
||||
static xyze_float_t calc_traj_point(const float dist);
|
||||
static bool plan_next_block();
|
||||
static void ensure_float_precision();
|
||||
|
||||
}; // class FTMotion
|
||||
|
||||
|
|
|
|||
|
|
@ -233,9 +233,11 @@ typedef struct Stepping {
|
|||
FORCE_INLINE bool is_busy() {
|
||||
return !(is_empty() && ticks_left_in_frame_fp == 0);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool is_empty() {
|
||||
return stepper_plan_head == stepper_plan_tail;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool is_full() {
|
||||
return ((stepper_plan_head + 1) & FTM_BUFFER_MASK) == stepper_plan_tail;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue