From 5917aa73b51e77b28748cf7a73bd892775fc2128 Mon Sep 17 00:00:00 2001 From: David Buezas Date: Mon, 22 Sep 2025 00:21:53 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Fix=20K,=20improve=20FTMot?= =?UTF-8?q?ion=20linear=20advance=20(#28058)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Marlin/src/gcode/feature/ft_motion/M493.cpp | 2 +- Marlin/src/inc/Conditionals-4-adv.h | 4 +++ Marlin/src/lcd/menu/menu_motion.cpp | 4 +-- Marlin/src/module/ft_motion.cpp | 30 ++++++++++----------- Marlin/src/module/ft_motion.h | 3 ++- Marlin/src/module/planner.cpp | 23 +++++++++------- Marlin/src/module/planner.h | 8 +++--- 7 files changed, 42 insertions(+), 32 deletions(-) diff --git a/Marlin/src/gcode/feature/ft_motion/M493.cpp b/Marlin/src/gcode/feature/ft_motion/M493.cpp index fe57de6ac8..606d23179d 100644 --- a/Marlin/src/gcode/feature/ft_motion/M493.cpp +++ b/Marlin/src/gcode/feature/ft_motion/M493.cpp @@ -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; } diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 0967f994ce..0ed5ae27ca 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -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. diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index 3aded6ed72..23c0a5b7e0 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -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(); diff --git a/Marlin/src/module/ft_motion.cpp b/Marlin/src/module/ft_motion.cpp index e819a0cdfc..51c04c8a89 100644 --- a/Marlin/src/module/ft_motion.cpp +++ b/Marlin/src/module/ft_motion.cpp @@ -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 diff --git a/Marlin/src/module/ft_motion.h b/Marlin/src/module/ft_motion.h index d438b3a8c5..5e7635a3aa 100644 --- a/Marlin/src/module/ft_motion.h +++ b/Marlin/src/module/ft_motion.h @@ -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 diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 2918f14bd2..9c6c0e378a 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -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; diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 2695c1768e..40333beffe 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -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