diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 0091563463..e59c4e0f9d 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1230,9 +1230,10 @@ #define FTM_POLY6_ACCELERATION_OVERSHOOT 1.875f // Max acceleration overshoot factor for POLY6 (1.25 to 1.875) #endif - #define FTM_CONSTANT_JERK // Enable constant-jerk (7-phase S-curve) trajectory with block merging + #define FTM_CONSTANT_JERK // Enable constant-jerk (7-phase S-curve) trajectory #if ENABLED(FTM_CONSTANT_JERK) - #define FTM_DEFAULT_JERK_MAX 30000.0f // (mm/s³) Default maximum jerk for constant-jerk trajectory + #define FTM_DEFAULT_JERK_MAX 500'000.0f // (mm/s³) Default maximum jerk for constant-jerk trajectory + // Higher prints faster at the cost of increased resonance and extruder stress #endif /** diff --git a/Marlin/src/gcode/feature/ft_motion/M494.cpp b/Marlin/src/gcode/feature/ft_motion/M494.cpp index 6f3b436282..90b8c43c8c 100644 --- a/Marlin/src/gcode/feature/ft_motion/M494.cpp +++ b/Marlin/src/gcode/feature/ft_motion/M494.cpp @@ -130,15 +130,8 @@ void GcodeSuite::M494() { // Parse jerk max parameter. if (parser.seenval('J')) { - const float val = parser.value_float(); - if (val > 0.0f) { - ftMotion.cfg.jerk_max = val; - ftMotion.cjPlanner.setJerkMax(val); - ftMotion.constantJerkGenerator.setJerkMax(val); - report = true; - } - else - SERIAL_ECHOLN(F("?Invalid (J)erk value. Must be positive.")); + ftMotion.cfg.set_jerkMax(parser.value_float()); + report = true; } #endif // FTM_CONSTANT_JERK diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 729be45fb3..4a6b463ad4 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -836,8 +836,8 @@ namespace LanguageNarrow_en { LSTR MSG_FTM_TRAPEZOIDAL = _UxGT("Trapezoidal"); LSTR MSG_FTM_POLY5 = _UxGT("5th Order"); LSTR MSG_FTM_POLY6 = _UxGT("6th Order"); - LSTR MSG_FTM_CONSTANT_JERK = _UxGT("Constant Jerk"); - LSTR MSG_FTM_JERK_MAX = _UxGT("@ Jerk Max"); + LSTR MSG_FTM_CONSTANT_JERK = _UxGT("Constant Jerk"); + LSTR MSG_FTM_JERK_MAX = _UxGT("Jerk (m/s3)"); LSTR MSG_FTM_TRAJECTORY = _UxGT("Trajectory: $"); LSTR MSG_FILAMENT_EN = _UxGT("Filament *"); LSTR MSG_SEGMENTS_PER_SECOND = _UxGT("Segments/Sec"); diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index 36f4b4a630..4ec7975b34 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -561,9 +561,9 @@ void menu_move() { #endif #if ENABLED(FTM_CONSTANT_JERK) if (ftMotion.getTrajectoryType() == TrajectoryType::CONSTANT_JERK) { - editable.decimal = c.jerk_max; - EDIT_ITEM(float62, MSG_FTM_JERK_MAX, &editable.decimal, 100.0f, 200000.0f, []{ - queue.inject(TS(F("M494"), 'J', editable.decimal)); + editable.decimal = c.jerk_max / 1000; + EDIT_ITEM(float4, MSG_FTM_JERK_MAX, &editable.decimal, 1.0f, 9999.0f, []{ + queue.inject(TS(F("M494"), 'J', editable.decimal * 1000)); }); } #endif @@ -628,9 +628,9 @@ void menu_move() { #endif #if ENABLED(FTM_CONSTANT_JERK) if (ftMotion.getTrajectoryType() == TrajectoryType::CONSTANT_JERK) { - editable.decimal = ftMotion.cfg.jerk_max; - EDIT_ITEM(float62, MSG_FTM_JERK_MAX, &editable.decimal, 100.0f, 200000.0f, []{ - queue.inject(TS(F("M494"), 'J', editable.decimal)); + editable.decimal = ftMotion.cfg.jerk_max / 1000; + EDIT_ITEM(float4, MSG_FTM_JERK_MAX, &editable.decimal, 1.0f, 9999.0f, []{ + queue.inject(TS(F("M494"), 'J', editable.decimal * 1000)); }); } #endif diff --git a/Marlin/src/module/ft_motion.cpp b/Marlin/src/module/ft_motion.cpp index 01c5c3c45c..c9e4540e25 100644 --- a/Marlin/src/module/ft_motion.cpp +++ b/Marlin/src/module/ft_motion.cpp @@ -87,7 +87,6 @@ TrapezoidalTrajectoryGenerator FTMotion::trapezoidalGenerator; Poly6TrajectoryGenerator FTMotion::poly6Generator; #endif #if ENABLED(FTM_CONSTANT_JERK) - ConstantJerkTrajectoryGenerator FTMotion::constantJerkGenerator; ConstantJerkBlockPlanner FTMotion::cjPlanner; #endif #if HAS_FTM_TRAJECTORY_SELECTION @@ -330,8 +329,7 @@ void FTMotion::init() { #endif #if ENABLED(FTM_CONSTANT_JERK) case TrajectoryType::CONSTANT_JERK: - constantJerkGenerator.setJerkMax(cfg.jerk_max); - currentGenerator = &constantJerkGenerator; + // CJ planner sets currentGenerator per-block in plan_next_block() break; #endif } @@ -436,7 +434,7 @@ bool FTMotion::plan_next_block() { if (trajectoryType == TrajectoryType::CONSTANT_JERK) { // CJ planner runs its own jerk-aware reverse/forward pass on all // visible blocks, then plans a single or merged S-curve trajectory. - cjPlanner.planNext(current_block); + cjPlanner.planNext(current_block, cfg.jerk_max); currentGenerator = &cjPlanner.trajectory(); endPos_prevBlock += moveDist; } diff --git a/Marlin/src/module/ft_motion.h b/Marlin/src/module/ft_motion.h index 6d8fa88204..6d99436fa3 100644 --- a/Marlin/src/module/ft_motion.h +++ b/Marlin/src/module/ft_motion.h @@ -105,6 +105,12 @@ typedef struct FTConfig { #endif #if ENABLED(FTM_CONSTANT_JERK) float jerk_max = FTM_DEFAULT_JERK_MAX; // (mm/s³) Maximum jerk for constant-jerk trajectory + + void set_jerkMax(float j) { + NOLESS(j, 1000.0f); + prep_for_shaper_change(); + jerk_max = j; + } #endif static void prep_for_shaper_change(); @@ -259,7 +265,6 @@ class FTMotion { static bool busy; #if ENABLED(FTM_CONSTANT_JERK) - static ConstantJerkTrajectoryGenerator constantJerkGenerator; static ConstantJerkBlockPlanner cjPlanner; #endif diff --git a/Marlin/src/module/ft_motion/constant_jerk_planner.h b/Marlin/src/module/ft_motion/constant_jerk_planner.h index c47b1db44c..a80eea7914 100644 --- a/Marlin/src/module/ft_motion/constant_jerk_planner.h +++ b/Marlin/src/module/ft_motion/constant_jerk_planner.h @@ -50,9 +50,6 @@ class ConstantJerkBlockPlanner { public: - void setJerkMax(float j) { jerk_max = j; } - float getJerkMax() const { return jerk_max; } - void reset() { has_plan = false; orig_block_index = 0; @@ -73,7 +70,7 @@ public: * * Returns true if a trajectory is ready for execution. */ - bool planNext(const block_t* current_block) { + bool planNext(const block_t* current_block, const float jerk_max) { has_plan = false; if (!current_block) return false; @@ -398,8 +395,6 @@ private: return v; } - float jerk_max = 30000.0f; - ConstantJerkTrajectoryGenerator traj; uint8_t group_block_count = 0; uint8_t orig_block_index = 0; diff --git a/Marlin/src/module/ft_motion/trajectory_constant_jerk.h b/Marlin/src/module/ft_motion/trajectory_constant_jerk.h index 3ef945fe59..e9966df536 100644 --- a/Marlin/src/module/ft_motion/trajectory_constant_jerk.h +++ b/Marlin/src/module/ft_motion/trajectory_constant_jerk.h @@ -86,19 +86,12 @@ class ConstantJerkTrajectoryGenerator : public TrajectoryGenerator { public: ConstantJerkTrajectoryGenerator() = default; - void setJerkMax(float j) { jerk_max = j; } - float getJerkMax() const { return jerk_max; } + // plan() override is unused — the CJ block planner calls plan_full() directly. + // Kept to satisfy the pure virtual interface. + void plan(const float, const float, const float, const float, const float) override {} - void plan(const float initial_speed_in, const float final_speed_in, - const float acceleration_in, const float nominal_speed_in, - const float distance_in) override { - // acceleration_in is from Marlin's planner (trapezoidal accel limit). - // We use it as a_max for the S-curve. - plan_internal(initial_speed_in, final_speed_in, acceleration_in, - jerk_max, distance_in, nominal_speed_in); - } - - // Full plan with explicit jerk and a_max (used by the block merging planner) + // Plan with explicit jerk and a_max (used by the block merging planner). + // Jerk comes from cfg.jerk_max, passed through by the caller. void plan_full(float initial_speed_in, float final_speed_in, float accel_max_in, float jerk_in, float distance_in, float nominal_in) { @@ -235,7 +228,6 @@ private: } } - float jerk_max = 30000.0f; float v0 = 0, v1 = 0; float a_max = 0, j = 0, distance = 0; float total_duration = 0;