️ Fix K, improve FTMotion linear advance (#28058)

This commit is contained in:
David Buezas 2025-09-22 00:21:53 +02:00 committed by GitHub
parent d0dc3b619f
commit 5917aa73b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 42 additions and 32 deletions

View file

@ -249,7 +249,7 @@ void GcodeSuite::M493() {
// Pressure control (linear advance) gain parameter.
if (parser.seenval('K')) {
const float val = parser.value_float();
if (val >= 0.0f) {
if (WITHIN(val, 0.0f, 10.0f)) {
ftMotion.cfg.linearAdvK = val;
flag.report = true;
}

View file

@ -348,6 +348,10 @@
#define HAS_ROUGH_LIN_ADVANCE 1
#endif
#if ALL(FT_MOTION, HAS_EXTRUDERS)
#define HAS_FTM_LIN_ADVANCE 1
#endif
// Some displays can toggle Adaptive Step Smoothing.
// The state is saved to EEPROM.
// In future this may be added to a G-code such as M205 A.

View file

@ -490,7 +490,7 @@ void menu_move() {
#if HAS_EXTRUDERS
EDIT_ITEM(bool, MSG_LINEAR_ADVANCE, &c.linearAdvEna);
if (c.linearAdvEna || ENABLED(FT_MOTION_NO_MENU_TOGGLE))
EDIT_ITEM(float62, MSG_ADVANCE_K, &c.linearAdvK, 0.0f, 1000.0f);
EDIT_ITEM(float42_52, MSG_ADVANCE_K, &c.linearAdvK, 0.0f, 10.0f);
#endif
}
END_MENU();
@ -547,7 +547,7 @@ void menu_move() {
#if HAS_EXTRUDERS
EDIT_ITEM(bool, MSG_LINEAR_ADVANCE, &c.linearAdvEna);
if (c.linearAdvEna || ENABLED(FT_MOTION_NO_MENU_TOGGLE))
EDIT_ITEM(float62, MSG_ADVANCE_K, &c.linearAdvK, 0.0f, 1000.0f);
EDIT_ITEM(float42_52, MSG_ADVANCE_K, &c.linearAdvK, 0.0f, 10.0f);
#endif
END_MENU();

View file

@ -93,6 +93,7 @@ uint32_t FTMotion::interpIdx = 0; // Index of current data point b
uint8_t FTMotion::block_extruder_axis; // Cached E Axis from last-fetched block
#elif HAS_EXTRUDERS
constexpr uint8_t FTMotion::block_extruder_axis;
bool FTMotion::use_advance_lead;
#endif
// Shaping variables.
@ -103,15 +104,14 @@ uint32_t FTMotion::interpIdx = 0; // Index of current data point b
, x:{ false, { 0.0f }, { 0.0f }, { 0 }, 0 } // ena, d_zi[], Ai[], Ni[], max_i
#endif
#if HAS_Y_AXIS
, y:{ false, { 0.0f }, { 0.0f }, { 0 }, 0 } // ena, d_zi[], Ai[], Ni[], max_i
, y:{ false, { 0.0f }, { 0.0f }, { 0 }, 0 }
#endif
};
#endif
#if HAS_EXTRUDERS
// Linear advance variables.
float FTMotion::e_raw_z1 = 0.0f; // (ms) Unit delay of raw extruder position.
float FTMotion::e_advanced_z1 = 0.0f; // (ms) Unit delay of advanced extruder position.
float FTMotion::prev_traj_e = 0.0f; // (ms) Unit delay of raw extruder position.
#endif
constexpr uint32_t BATCH_SIDX_IN_WINDOW = (FTM_WINDOW_SIZE) - (FTM_BATCH_SIZE); // Batch start index in window.
@ -388,7 +388,7 @@ void FTMotion::reset() {
shaping.zi_idx = 0;
#endif
TERN_(HAS_EXTRUDERS, e_raw_z1 = e_advanced_z1 = 0.0f); // Reset linear advance variables.
TERN_(HAS_EXTRUDERS, prev_traj_e = 0.0f); // Reset linear advance variables.
TERN_(DISTINCT_E_FACTORS, block_extruder_axis = E_AXIS);
axis_move_end_ti.reset();
@ -539,6 +539,8 @@ void FTMotion::loadBlockData(block_t * const current_block) {
endPos_prevBlock += moveDist;
TERN_(FTM_HAS_LIN_ADVANCE, use_advance_lead = current_block->use_advance_lead);
// Watch endstops until the move ends
const millis_t move_end_ti = millis() + SEC_TO_MS((FTM_TS) * float(max_intervals + num_samples_shaper_settle() + ((PROP_BATCHES) + 1) * (FTM_BATCH_SIZE)) + (float(FTM_STEPPERCMD_BUFF_SIZE) / float(FTM_STEPPER_FS)));
@ -557,14 +559,10 @@ void FTMotion::generateTrajectoryPointsFromBlock() {
do {
float tau = (traj_idx_get + 1) * (FTM_TS); // (s) Time since start of block
float dist = 0.0f; // (mm) Distance traveled
#if HAS_EXTRUDERS
float accel_k = 0.0f; // (mm/s^2) Acceleration K factor
#endif
if (traj_idx_get < N1) {
// Acceleration phase
dist = (f_s * tau) + (0.5f * accel_P * sq(tau)); // (mm) Distance traveled for acceleration phase since start of block
TERN_(HAS_EXTRUDERS, accel_k = accel_P); // (mm/s^2) Acceleration K factor from Accel phase
}
else if (traj_idx_get < (N1 + N2)) {
// Coasting phase
@ -575,20 +573,20 @@ void FTMotion::generateTrajectoryPointsFromBlock() {
// Deceleration phase
tau -= (N1 + N2) * (FTM_TS); // (s) Time since start of decel phase
dist = s_2e + F_P * tau + 0.5f * decel_P * sq(tau); // (mm) Distance traveled for deceleration phase since start of block
TERN_(HAS_EXTRUDERS, accel_k = decel_P); // (mm/s^2) Acceleration K factor from Decel phase
}
#define _SET_TRAJ(q) traj.q[traj_idx_set] = startPos.q + ratio.q * dist;
LOGICAL_AXIS_MAP_LC(_SET_TRAJ);
#if HAS_EXTRUDERS
#if FTM_HAS_LIN_ADVANCE
if (cfg.linearAdvEna) {
float dedt_adj = (traj.e[traj_idx_set] - e_raw_z1) * (FTM_FS);
if (ratio.e > 0.0f) dedt_adj += accel_k * cfg.linearAdvK * 0.0001f;
e_raw_z1 = traj.e[traj_idx_set];
e_advanced_z1 += dedt_adj * (FTM_TS);
traj.e[traj_idx_set] = e_advanced_z1;
float traj_e = traj.e[traj_idx_set];
if (use_advance_lead) {
// Don't apply LA to retract/unretract blocks
float e_rate = (traj_e - prev_traj_e) * (FTM_FS);
traj.e[traj_idx_set] += e_rate * cfg.linearAdvK;
}
prev_traj_e = traj_e;
}
#endif

View file

@ -176,6 +176,7 @@ class FTMotion {
static uint8_t block_extruder_axis; // Cached extruder axis index
#elif HAS_EXTRUDERS
static constexpr uint8_t block_extruder_axis = E_AXIS;
static bool use_advance_lead;
#endif
// Shaping variables.
@ -209,7 +210,7 @@ class FTMotion {
// Linear advance variables.
#if HAS_EXTRUDERS
static float e_raw_z1, e_advanced_z1;
static float prev_traj_e;
#endif
// Private methods

View file

@ -2379,7 +2379,7 @@ bool Planner::_populate_block(
const float steps_per_mm = block->step_event_count * inverse_millimeters;
block->steps_per_mm = steps_per_mm;
uint32_t accel;
#if ENABLED(LIN_ADVANCE)
#if ANY(LIN_ADVANCE, FTM_HAS_LIN_ADVANCE)
bool use_advance_lead = false;
#endif
if (!ANY_AXIS_MOVES(block)) { // Is this a retract / recover move?
@ -2403,7 +2403,7 @@ bool Planner::_populate_block(
// Start with print or travel acceleration
accel = CEIL((esteps ? settings.acceleration : settings.travel_acceleration) * steps_per_mm);
#if ENABLED(LIN_ADVANCE)
#if ANY(LIN_ADVANCE, FTM_HAS_LIN_ADVANCE)
// Linear advance is currently not ready for HAS_I_AXIS
#define MAX_E_JERK(N) TERN(HAS_LINEAR_E_JERK, max_e_jerk[E_INDEX_N(N)], max_jerk.e)
@ -2432,16 +2432,22 @@ bool Planner::_populate_block(
use_advance_lead = false;
else {
#if HAS_ROUGH_LIN_ADVANCE
// Scale E acceleration so that it will be possible to jump to the advance speed.
const uint32_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[E_INDEX_N(extruder)] * e_D_ratio) * steps_per_mm;
if (accel > max_accel_steps_per_s2) {
accel = max_accel_steps_per_s2;
if (TERN0(LA_DEBUG, DEBUGGING(INFO))) SERIAL_ECHOLNPGM("Acceleration limited.");
const bool limit_accel = TERN1(HAS_FTM_LIN_ADVANCE, !ftMotion.cfg.active);
if (limit_accel) {
// Scale E acceleration so that it will be possible to jump to the advance speed.
const uint32_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[E_INDEX_N(extruder)] * e_D_ratio) * steps_per_mm;
if (accel > max_accel_steps_per_s2) {
accel = max_accel_steps_per_s2;
if (TERN0(LA_DEBUG, DEBUGGING(INFO))) SERIAL_ECHOLNPGM("Acceleration limited.");
}
}
#endif
}
#if ANY(SMOOTH_LIN_ADVANCE, FTM_HAS_LIN_ADVANCE)
block->use_advance_lead = use_advance_lead;
#endif
}
#endif // LIN_ADVANCE
#endif // LIN_ADVANCE || FTM_HAS_LIN_ADVANCE
// Limit acceleration per axis
if (block->step_event_count <= acceleration_long_cutoff) {
@ -2484,7 +2490,6 @@ bool Planner::_populate_block(
SERIAL_ECHOLNPGM("eISR running at > 10kHz: ", block->la_advance_rate);
}
#elif ENABLED(SMOOTH_LIN_ADVANCE)
block->use_advance_lead = use_advance_lead;
const uint32_t ratio = (uint64_t(block->steps.e) * _BV32(30)) / block->step_event_count;
block->e_step_ratio_q30 = block->direction_bits.e ? ratio : -ratio;

View file

@ -271,10 +271,12 @@ typedef struct PlannerBlock {
#endif
// Advance extrusion
#if ANY(SMOOTH_LIN_ADVANCE, FTM_HAS_LIN_ADVANCE)
bool use_advance_lead;
#endif
#if ENABLED(LIN_ADVANCE)
#if ENABLED(SMOOTH_LIN_ADVANCE)
bool use_advance_lead;
#else
#if HAS_ROUGH_LIN_ADVANCE
uint32_t la_advance_rate; // The rate at which steps are added whilst accelerating
uint8_t la_scaling; // Scale ISR frequency down and step frequency up by 2 ^ la_scaling
uint16_t max_adv_steps, // Max advance steps to get cruising speed pressure