From e434fd0aefa87e1027d40019b6a71d19b68d132b Mon Sep 17 00:00:00 2001 From: Harald Wagener Date: Fri, 12 Dec 2025 03:50:13 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20FTM=5FSHAPER=5F*=20options=20(#2821?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Scott Lahteine --- Marlin/Configuration_adv.h | 10 ++ Marlin/src/gcode/feature/ft_motion/M493.cpp | 95 ++++++----- Marlin/src/gcode/feature/ft_motion/M494.cpp | 7 +- Marlin/src/inc/Conditionals-4-adv.h | 3 + Marlin/src/inc/Conditionals-5-post.h | 17 +- Marlin/src/inc/SanityCheck.h | 5 +- Marlin/src/lcd/menu/menu_motion.cpp | 15 +- Marlin/src/module/ft_motion.cpp | 2 +- Marlin/src/module/ft_motion.h | 9 +- Marlin/src/module/ft_motion/shaping.cpp | 166 +++++++++++--------- Marlin/src/module/ft_motion/shaping.h | 10 +- Marlin/src/module/stepper.cpp | 14 +- buildroot/tests/rambo | 1 + 13 files changed, 211 insertions(+), 143 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index f217923520..b8d7ed694d 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1171,6 +1171,16 @@ #define FTM_DEFAULT_DYNFREQ_MODE dynFreqMode_DISABLED // Default mode of dynamic frequency calculation. (DISABLED, Z_BASED, MASS_BASED) #endif + // Disable unused shapers if you need more free space + #define FTM_SHAPER_ZV + #define FTM_SHAPER_ZVD + #define FTM_SHAPER_ZVDD + #define FTM_SHAPER_ZVDDD + #define FTM_SHAPER_EI + #define FTM_SHAPER_2HEI + #define FTM_SHAPER_3HEI + #define FTM_SHAPER_MZV + #define FTM_DEFAULT_SHAPER_X ftMotionShaper_NONE // Default shaper mode on X axis (NONE, ZV, ZVD, ZVDD, ZVDDD, EI, 2HEI, 3HEI, MZV) #define FTM_SHAPING_DEFAULT_FREQ_X 37.0f // (Hz) Default peak frequency used by input shapers #define FTM_SHAPING_ZETA_X 0.1f // Zeta used by input shapers for X axis diff --git a/Marlin/src/gcode/feature/ft_motion/M493.cpp b/Marlin/src/gcode/feature/ft_motion/M493.cpp index 905bddf124..85e2fc9d3b 100644 --- a/Marlin/src/gcode/feature/ft_motion/M493.cpp +++ b/Marlin/src/gcode/feature/ft_motion/M493.cpp @@ -136,13 +136,18 @@ void GcodeSuite::M493_report(const bool forReplay/*=true*/) { #else #define F_REPORT(A) #endif + #if HAS_FTM_EI_SHAPING + #define Q_REPORT(A) , F(" Q"), c.vtol.A + #else + #define Q_REPORT(A) + #endif #define _REPORT_M493_AXIS(A) \ SERIAL_ECHOLN(F(" M493 "), C(AXIS_CHAR(_AXIS(A))) \ , F(" C"), c.shaper.A \ , F(" A"), c.baseFreq.A \ F_REPORT(A) \ , F(" I"), c.zeta.A \ - , F(" Q"), c.vtol.A \ + Q_REPORT(A) \ ); // Shaper type for each axis SHAPED_MAP(_REPORT_M493_AXIS); @@ -293,12 +298,14 @@ void GcodeSuite::M493() { if (seenI && !goodZeta) SERIAL_ECHOLN(F("?Invalid "), F("(I) Zeta value. (0.01-1.0)")); // Zeta out of range - // Vibration Tolerance parameter - const bool seenQ = parser.seenval('Q'); - const float vtolVal = seenQ ? parser.value_float() : 0.0f; - const bool goodVtol = seenQ && c.goodVtol(vtolVal); - if (seenQ && !goodVtol) - SERIAL_ECHOLN(F("?Invalid "), F("(Q) Vibration Tolerance value. (0.0-1.0)")); // VTol out of range + #if HAS_FTM_EI_SHAPING + // Vibration Tolerance parameter + const bool seenQ = parser.seenval('Q'); + const float vtolVal = seenQ ? parser.value_float() : 0.0f; + const bool goodVtol = seenQ && c.goodVtol(vtolVal); + if (seenQ && !goodVtol) + SERIAL_ECHOLN(F("?Invalid "), F("(Q) Vibration Tolerance value. (0.0-1.0)")); // VTol out of range + #endif const bool apply_xy = !parser.seen("XYZE"); @@ -339,17 +346,19 @@ void GcodeSuite::M493() { SERIAL_ECHOLNPGM("?Wrong mode for ", C(STEPPER_A_NAME), " (I) zeta parameter."); } - // Parse X vtol parameter - if (seenQ) { - if (AXIS_IS_EISHAPING(X)) { - if (goodVtol) { - c.vtol.x = vtolVal; - flag.update = true; + #if HAS_FTM_EI_SHAPING + // Parse X vtol parameter + if (seenQ) { + if (AXIS_IS_EISHAPING(X)) { + if (goodVtol) { + c.vtol.x = vtolVal; + flag.update = true; + } } + else + SERIAL_ECHOLNPGM("?Wrong mode for ", C(STEPPER_A_NAME), " (Q) vtol parameter."); } - else - SERIAL_ECHOLNPGM("?Wrong mode for ", C(STEPPER_A_NAME), " (Q) vtol parameter."); - } + #endif } #endif // HAS_X_AXIS @@ -391,16 +400,18 @@ void GcodeSuite::M493() { } // Parse Y vtol parameter - if (seenQ) { - if (AXIS_IS_EISHAPING(Y)) { - if (goodVtol) { - c.vtol.y = vtolVal; - flag.update = true; + #if HAS_FTM_EI_SHAPING + if (seenQ) { + if (AXIS_IS_EISHAPING(Y)) { + if (goodVtol) { + c.vtol.y = vtolVal; + flag.update = true; + } } + else + SERIAL_ECHOLNPGM("?Wrong mode for ", C(STEPPER_B_NAME), " (Q) vtol parameter."); } - else - SERIAL_ECHOLNPGM("?Wrong mode for ", C(STEPPER_B_NAME), " (Q) vtol parameter."); - } + #endif } #endif // HAS_Y_AXIS @@ -442,16 +453,18 @@ void GcodeSuite::M493() { } // Parse Z vtol parameter - if (seenQ) { - if (AXIS_IS_EISHAPING(Z)) { - if (goodVtol) { - c.vtol.z = vtolVal; - flag.update = true; + #if HAS_FTM_EI_SHAPING + if (seenQ) { + if (AXIS_IS_EISHAPING(Z)) { + if (goodVtol) { + c.vtol.z = vtolVal; + flag.update = true; + } } + else + SERIAL_ECHOLNPGM("?Wrong mode for ", C(STEPPER_C_NAME), " (Q) vtol parameter."); } - else - SERIAL_ECHOLNPGM("?Wrong mode for ", C(STEPPER_C_NAME), " (Q) vtol parameter."); - } + #endif } #endif // FTM_SHAPER_Z @@ -493,16 +506,18 @@ void GcodeSuite::M493() { } // Parse E vtol parameter - if (seenQ) { - if (AXIS_IS_EISHAPING(E)) { - if (goodVtol) { - c.vtol.e = vtolVal; - flag.update = true; + #if HAS_FTM_EI_SHAPING + if (seenQ) { + if (AXIS_IS_EISHAPING(E)) { + if (goodVtol) { + c.vtol.e = vtolVal; + flag.update = true; + } } + else + SERIAL_ECHOLNPGM("?Wrong mode for ", C('E'), " (Q) vtol parameter."); } - else - SERIAL_ECHOLNPGM("?Wrong mode for ", C('E'), " (Q) vtol parameter."); - } + #endif } #endif // FTM_SHAPER_E diff --git a/Marlin/src/gcode/feature/ft_motion/M494.cpp b/Marlin/src/gcode/feature/ft_motion/M494.cpp index 6f90badb49..212a69c0a2 100644 --- a/Marlin/src/gcode/feature/ft_motion/M494.cpp +++ b/Marlin/src/gcode/feature/ft_motion/M494.cpp @@ -29,13 +29,12 @@ #include "../../../module/planner.h" void say_ftm_settings() { - #if ENABLED(FTM_POLYS) - SERIAL_ECHOLN(F(" Trajectory: "), ftMotion.getTrajectoryName(), C('('), (uint8_t)ftMotion.getTrajectoryType(), C(')')); + #if ANY(FTM_POLYS, FTM_SMOOTHING) + const ft_config_t &c = ftMotion.cfg; #endif - const ft_config_t &c = ftMotion.cfg; - #if ENABLED(FTM_POLYS) + SERIAL_ECHOLN(F(" Trajectory: "), ftMotion.getTrajectoryName(), C('('), (uint8_t)ftMotion.getTrajectoryType(), C(')')); if (ftMotion.getTrajectoryType() == TrajectoryType::POLY6) SERIAL_ECHOLNPGM(" Poly6 Overshoot: ", p_float_t(c.poly6_acceleration_overshoot, 3)); #endif diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index f92ba2c079..b363ccde11 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -375,6 +375,9 @@ #undef MULTISTEPPING_LIMIT #define MULTISTEPPING_LIMIT 1 #endif + #if ANY(FTM_SHAPER_EI, FTM_SHAPER_2HEI, FTM_SHAPER_3HEI) + #define HAS_FTM_EI_SHAPING 1 + #endif #endif #if DISABLED(NO_STANDARD_MOTION) #define HAS_STANDARD_MOTION 1 diff --git a/Marlin/src/inc/Conditionals-5-post.h b/Marlin/src/inc/Conditionals-5-post.h index e2d2952e1b..0fa53dbf3e 100644 --- a/Marlin/src/inc/Conditionals-5-post.h +++ b/Marlin/src/inc/Conditionals-5-post.h @@ -3690,13 +3690,16 @@ #define FTM_TS (1.0f / FTM_FS) // (s) Time step for trajectory generation. (Reciprocal of FTM_FS) #define FTM_RATIO (FTM_FS / FTM_MIN_SHAPE_FREQ) // Factor for use in FTM_ZMAX. DON'T CHANGE. #define FTM_SMOOTH_MAX_I uint32_t(TERN0(FTM_SMOOTHING, CEIL(FTM_FS * FTM_MAX_SMOOTHING_TIME))) // Max delays for smoothing - #define FTM_ZMAX (FTM_RATIO * 2 + FTM_SMOOTH_MAX_I) // Maximum delays for shaping functions (even numbers only!) - // Calculate as: - // ZV : FTM_RATIO / 2 - // ZVD, MZV : FTM_RATIO - // 2HEI : FTM_RATIO * 3 / 2 - // 3HEI : FTM_RATIO * 2 - #define FTM_SMOOTHING_ORDER 5 // 3 to 5 is closest to gaussian + + // Maximum delays for shaping functions (even numbers only!) + #define FTM_ZMAX (TERN(HAS_FTM_EI_SHAPING, 2, 1) * FTM_RATIO + FTM_SMOOTH_MAX_I) + + #define FTM_SMOOTHING_ORDER 5 // 3 to 5 is closest to Gaussian + // Calculate as: + // ZV : FTM_RATIO / 2 + // ZVD, MZV : FTM_RATIO + // 2HEI : FTM_RATIO * 3 / 2 + // 3HEI : FTM_RATIO * 2 #ifndef FTM_BUFFER_SIZE #define FTM_BUFFER_SIZE 128 #endif diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 5a55671fc1..694f88f3ee 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -4519,7 +4519,10 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive." #error "Z_LATE_ENABLE is not yet available in FT_MOTION. Disable NO_STANDARD_MOTION if you require it." #endif #endif -#endif + #if HAS_FTM_SHAPING && NONE(FTM_SHAPER_ZV, FTM_SHAPER_ZVD, FTM_SHAPER_ZVDD, FTM_SHAPER_ZVDDD, FTM_SHAPER_EI, FTM_SHAPER_2HEI, FTM_SHAPER_3HEI, FTM_SHAPER_MZV) + #error "For FT_MOTION at least one FTM_SHAPER_* type must be enabled." + #endif +#endif // FT_MOTION // Multi-Stepping Limit static_assert(WITHIN(MULTISTEPPING_LIMIT, 1, 128) && IS_POWER_OF_2(MULTISTEPPING_LIMIT), "MULTISTEPPING_LIMIT must be 1, 2, 4, 8, 16, 32, 64, or 128."); diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index 5b3d72a6ee..106646430c 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -444,13 +444,20 @@ void menu_move() { START_MENU(); BACK_ITEM(MSG_FIXED_TIME_MOTION); - if (axis == X_AXIS || axis == Y_AXIS || TERN0(FTM_SHAPER_Z, axis == Z_AXIS) || TERN0(FTM_SHAPER_E, axis == E_AXIS)) { + #if HAS_FTM_EI_SHAPING + #define EISHAPER_MENU_ITEM(A) \ + if (AXIS_IS_EISHAPING(A)) \ + EDIT_ITEM_FAST_N(float42_52, axis, MSG_FTM_VTOL_N, &c.vtol[axis], 0.0f, 1.0f, ftMotion.update_shaping_params); + #else + #define EISHAPER_MENU_ITEM(A) NOOP + #endif + + if (false SHAPED_GANG(|| axis == X_AXIS, || axis == Y_AXIS, || axis == Z_AXIS, || axis == E_AXIS)) { SUBMENU_N_S(axis, get_shaper_name(axis), MSG_FTM_CMPN_MODE, menu_ftm_shaper); - if (IS_SHAPING(c.shaper[axis])) { + if (AXIS_IS_SHAPING(axis)) { EDIT_ITEM_FAST_N(float42_52, axis, MSG_FTM_BASE_FREQ_N, &c.baseFreq[axis], FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2, ftMotion.update_shaping_params); EDIT_ITEM_FAST_N(float42_52, axis, MSG_FTM_ZETA_N, &c.zeta[axis], 0.0f, 1.0f, ftMotion.update_shaping_params); - if (IS_EISHAPING(c.shaper[axis])) - EDIT_ITEM_FAST_N(float42_52, axis, MSG_FTM_VTOL_N, &c.vtol[axis], 0.0f, 1.0f, ftMotion.update_shaping_params); + EISHAPER_MENU_ITEM(axis); } } diff --git a/Marlin/src/module/ft_motion.cpp b/Marlin/src/module/ft_motion.cpp index e35ccba95e..c4c2e5f302 100644 --- a/Marlin/src/module/ft_motion.cpp +++ b/Marlin/src/module/ft_motion.cpp @@ -193,7 +193,7 @@ void FTMotion::loop() { void FTMotion::update_shaping_params() { #define UPDATE_SHAPER(A) \ shaping.A.ena = IS_SHAPING(ftMotion.cfg.shaper.A); \ - shaping.A.set_axis_shaping_A(cfg.shaper.A, cfg.zeta.A, cfg.vtol.A); \ + shaping.A.set_axis_shaping_A(cfg.shaper.A, cfg.zeta.A OPTARG(HAS_FTM_EI_SHAPING, cfg.vtol.A)); \ shaping.A.set_axis_shaping_N(cfg.shaper.A, cfg.baseFreq.A, cfg.zeta.A); SHAPED_MAP(UPDATE_SHAPER); diff --git a/Marlin/src/module/ft_motion.h b/Marlin/src/module/ft_motion.h index 79dce3c8e1..bf6a38a88f 100644 --- a/Marlin/src/module/ft_motion.h +++ b/Marlin/src/module/ft_motion.h @@ -72,8 +72,11 @@ typedef struct FTConfig { SHAPED_ARRAY(FTM_SHAPING_DEFAULT_FREQ_X, FTM_SHAPING_DEFAULT_FREQ_Y, FTM_SHAPING_DEFAULT_FREQ_Z, FTM_SHAPING_DEFAULT_FREQ_E); ft_shaped_float_t zeta = // Damping factor SHAPED_ARRAY(FTM_SHAPING_ZETA_X, FTM_SHAPING_ZETA_Y, FTM_SHAPING_ZETA_Z, FTM_SHAPING_ZETA_E); - ft_shaped_float_t vtol = // Vibration Level - SHAPED_ARRAY(FTM_SHAPING_V_TOL_X, FTM_SHAPING_V_TOL_Y, FTM_SHAPING_V_TOL_Z, FTM_SHAPING_V_TOL_E); + + #if HAS_FTM_EI_SHAPING + ft_shaped_float_t vtol = // Vibration Level + SHAPED_ARRAY(FTM_SHAPING_V_TOL_X, FTM_SHAPING_V_TOL_Y, FTM_SHAPING_V_TOL_Z, FTM_SHAPING_V_TOL_E); + #endif #if HAS_DYNAMIC_FREQ dynFreqMode_t dynFreqMode = FTM_DEFAULT_DYNFREQ_MODE; // Dynamic frequency mode configuration. @@ -147,7 +150,7 @@ typedef struct FTConfig { shaper.A = FTM_DEFAULT_SHAPER_##A; \ baseFreq.A = FTM_SHAPING_DEFAULT_FREQ_##A; \ zeta.A = FTM_SHAPING_ZETA_##A; \ - vtol.A = FTM_SHAPING_V_TOL_##A; \ + TERN_(HAS_FTM_EI_SHAPING, vtol.A = FTM_SHAPING_V_TOL_##A); \ }while(0); SHAPED_MAP(_SET_CFG_DEFAULTS); diff --git a/Marlin/src/module/ft_motion/shaping.cpp b/Marlin/src/module/ft_motion/shaping.cpp index a077ce99b8..f4f00a8589 100644 --- a/Marlin/src/module/ft_motion/shaping.cpp +++ b/Marlin/src/module/ft_motion/shaping.cpp @@ -27,7 +27,11 @@ #include "shaping.h" // Refresh the gains used by shaping functions. -void AxisShaping::set_axis_shaping_A(const ftMotionShaper_t shaper, const float zeta, const float vtol) { +void AxisShaping::set_axis_shaping_A( + const ftMotionShaper_t shaper, + const float zeta + OPTARG(HAS_FTM_EI_SHAPING, const float vtol) +) { const float K = exp(-zeta * M_PI / sqrt(1.f - sq(zeta))), K2 = sq(K), @@ -36,79 +40,95 @@ void AxisShaping::set_axis_shaping_A(const ftMotionShaper_t shaper, const float switch (shaper) { - case ftMotionShaper_ZV: - max_i = 1U; - Ai[0] = 1.0f / (1.0f + K); - Ai[1] = Ai[0] * K; + #if ENABLED(FTM_SHAPER_ZV) + case ftMotionShaper_ZV: + max_i = 1U; + Ai[0] = 1.0f / (1.0f + K); + Ai[1] = Ai[0] * K; + break; + #endif + + #if ENABLED(FTM_SHAPER_ZVD) + case ftMotionShaper_ZVD: + max_i = 2U; + Ai[0] = 1.0f / (1.0f + 2.0f * K + K2); + Ai[1] = Ai[0] * 2.0f * K; + Ai[2] = Ai[0] * K2; + break; + #endif + + #if ENABLED(FTM_SHAPER_ZVDD) + case ftMotionShaper_ZVDD: + max_i = 3U; + Ai[0] = 1.0f / (1.0f + 3.0f * K + 3.0f * K2 + K3); + Ai[1] = Ai[0] * 3.0f * K; + Ai[2] = Ai[0] * 3.0f * K2; + Ai[3] = Ai[0] * K3; + break; + #endif + + #if ENABLED(FTM_SHAPER_ZVDDD) + case ftMotionShaper_ZVDDD: + max_i = 4U; + Ai[0] = 1.0f / (1.0f + 4.0f * K + 6.0f * K2 + 4.0f * K3 + K4); + Ai[1] = Ai[0] * 4.0f * K; + Ai[2] = Ai[0] * 6.0f * K2; + Ai[3] = Ai[0] * 4.0f * K3; + Ai[4] = Ai[0] * K4; + break; + #endif + + #if ENABLED(FTM_SHAPER_EI) + case ftMotionShaper_EI: { + max_i = 2U; + Ai[0] = 0.25f * (1.0f + vtol); + Ai[1] = 0.50f * (1.0f - vtol) * K; + Ai[2] = Ai[0] * K2; + + const float adj = 1.0f / (Ai[0] + Ai[1] + Ai[2]); + for (uint32_t i = 0; i < 3U; i++) Ai[i] *= adj; + } break; + #endif + + #if ENABLED(FTM_SHAPER_H2EI) + case ftMotionShaper_2HEI: { + max_i = 3U; + const float vtolx2 = sq(vtol); + const float X = POW(vtolx2 * (sqrt(1.0f - vtolx2) + 1.0f), 1.0f / 3.0f); + Ai[0] = (3.0f * sq(X) + 2.0f * X + 3.0f * vtolx2) / (16.0f * X); + Ai[1] = (0.5f - Ai[0]) * K; + Ai[2] = Ai[1] * K; + Ai[3] = Ai[0] * K3; + + const float adj = 1.0f / (Ai[0] + Ai[1] + Ai[2] + Ai[3]); + for (uint32_t i = 0; i < 4U; i++) Ai[i] *= adj; + } break; + #endif + + #if ENABLED(FTM_SHAPER_3HEI) + case ftMotionShaper_3HEI: { + max_i = 4U; + Ai[0] = 0.0625f * ( 1.0f + 3.0f * vtol + 2.0f * sqrt( 2.0f * ( vtol + 1.0f ) * vtol ) ); + Ai[1] = 0.25f * ( 1.0f - vtol ) * K; + Ai[2] = ( 0.5f * ( 1.0f + vtol ) - 2.0f * Ai[0] ) * K2; + Ai[3] = Ai[1] * K2; + Ai[4] = Ai[0] * K4; + + const float adj = 1.0f / (Ai[0] + Ai[1] + Ai[2] + Ai[3] + Ai[4]); + for (uint32_t i = 0; i < 5U; i++) Ai[i] *= adj; + } break; + #endif + + #if ENABLED(FTM_SHAPER_MZV) + case ftMotionShaper_MZV: { + max_i = 2U; + const float Bx = 1.4142135623730950488016887242097f * K; + Ai[0] = 1.0f / (1.0f + Bx + K2); + Ai[1] = Ai[0] * Bx; + Ai[2] = Ai[0] * K2; + } break; - - case ftMotionShaper_ZVD: - max_i = 2U; - Ai[0] = 1.0f / (1.0f + 2.0f * K + K2); - Ai[1] = Ai[0] * 2.0f * K; - Ai[2] = Ai[0] * K2; - break; - - case ftMotionShaper_ZVDD: - max_i = 3U; - Ai[0] = 1.0f / (1.0f + 3.0f * K + 3.0f * K2 + K3); - Ai[1] = Ai[0] * 3.0f * K; - Ai[2] = Ai[0] * 3.0f * K2; - Ai[3] = Ai[0] * K3; - break; - - case ftMotionShaper_ZVDDD: - max_i = 4U; - Ai[0] = 1.0f / (1.0f + 4.0f * K + 6.0f * K2 + 4.0f * K3 + K4); - Ai[1] = Ai[0] * 4.0f * K; - Ai[2] = Ai[0] * 6.0f * K2; - Ai[3] = Ai[0] * 4.0f * K3; - Ai[4] = Ai[0] * K4; - break; - - case ftMotionShaper_EI: { - max_i = 2U; - Ai[0] = 0.25f * (1.0f + vtol); - Ai[1] = 0.50f * (1.0f - vtol) * K; - Ai[2] = Ai[0] * K2; - - const float adj = 1.0f / (Ai[0] + Ai[1] + Ai[2]); - for (uint32_t i = 0; i < 3U; i++) Ai[i] *= adj; - } break; - - case ftMotionShaper_2HEI: { - max_i = 3U; - const float vtolx2 = sq(vtol); - const float X = POW(vtolx2 * (sqrt(1.0f - vtolx2) + 1.0f), 1.0f / 3.0f); - Ai[0] = (3.0f * sq(X) + 2.0f * X + 3.0f * vtolx2) / (16.0f * X); - Ai[1] = (0.5f - Ai[0]) * K; - Ai[2] = Ai[1] * K; - Ai[3] = Ai[0] * K3; - - const float adj = 1.0f / (Ai[0] + Ai[1] + Ai[2] + Ai[3]); - for (uint32_t i = 0; i < 4U; i++) Ai[i] *= adj; - } break; - - case ftMotionShaper_3HEI: { - max_i = 4U; - Ai[0] = 0.0625f * ( 1.0f + 3.0f * vtol + 2.0f * sqrt( 2.0f * ( vtol + 1.0f ) * vtol ) ); - Ai[1] = 0.25f * ( 1.0f - vtol ) * K; - Ai[2] = ( 0.5f * ( 1.0f + vtol ) - 2.0f * Ai[0] ) * K2; - Ai[3] = Ai[1] * K2; - Ai[4] = Ai[0] * K4; - - const float adj = 1.0f / (Ai[0] + Ai[1] + Ai[2] + Ai[3] + Ai[4]); - for (uint32_t i = 0; i < 5U; i++) Ai[i] *= adj; - } break; - - case ftMotionShaper_MZV: { - max_i = 2U; - const float Bx = 1.4142135623730950488016887242097f * K; - Ai[0] = 1.0f / (1.0f + Bx + K2); - Ai[1] = Ai[0] * Bx; - Ai[2] = Ai[0] * K2; - } - break; + #endif case ftMotionShaper_NONE: max_i = 0; diff --git a/Marlin/src/module/ft_motion/shaping.h b/Marlin/src/module/ft_motion/shaping.h index 671bdeea88..f207b3d2b7 100644 --- a/Marlin/src/module/ft_motion/shaping.h +++ b/Marlin/src/module/ft_motion/shaping.h @@ -41,8 +41,8 @@ enum dynFreqMode_t : uint8_t { dynFreqMode_MASS_BASED = 2 }; -#define IS_SHAPING(S) (S != ftMotionShaper_NONE) -#define IS_EISHAPING(S) WITHIN(S, ftMotionShaper_EI, ftMotionShaper_3HEI) +#define IS_SHAPING(S) ((S) != ftMotionShaper_NONE) +#define IS_EISHAPING(S) TERN0(HAS_FTM_EI_SHAPING, WITHIN(S, ftMotionShaper_EI, ftMotionShaper_3HEI)) #define AXIS_IS_SHAPING(A) TERN0(FTM_SHAPER_##A, IS_SHAPING(ftMotion.cfg.shaper.A)) #define AXIS_IS_EISHAPING(A) TERN0(FTM_SHAPER_##A, IS_EISHAPING(ftMotion.cfg.shaper.A)) @@ -104,7 +104,11 @@ typedef struct AxisShaping { void set_axis_shaping_N(const ftMotionShaper_t shaper, const float f, const float zeta); // Set the indices (per pulse delays) used by shaping functions - void set_axis_shaping_A(const ftMotionShaper_t shaper, const float zeta, const float vtol); + void set_axis_shaping_A( + const ftMotionShaper_t shaper, + const float zeta + OPTARG(HAS_FTM_EI_SHAPING, const float vtol) + ); } axis_shaping_t; diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 947a74f96a..86ad562e8c 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -1569,10 +1569,14 @@ HAL_STEP_TIMER_ISR() { void Stepper::isr() { - static hal_timer_t nextMainISR = 0; // Interval until the next main Stepper Pulse phase (0 = Now) - + #if HAS_STANDARD_MOTION + static hal_timer_t nextMainISR = 0; // Interval until the next main Stepper Pulse phase (0 = Now) + #endif #if ENABLED(SMOOTH_LIN_ADVANCE) - static hal_timer_t smoothLinAdvISR = 0; + static hal_timer_t smoothLinAdvISR = 0; // Interval until the next Smooth Linear Advance phase (0 = Now) + #endif + #if ENABLED(FT_MOTION) + static uint32_t ftMotion_nextStepperISR = 0; // Interval until the next FT Motion phase (0 = Now) #endif // Program timer compare for the maximum period, so it does NOT @@ -1586,10 +1590,6 @@ void Stepper::isr() { // Limit the amount of iterations uint8_t max_loops = 10; - #if ENABLED(FT_MOTION) - static uint32_t ftMotion_nextStepperISR = 0U; // Storage for the next ISR for stepping. - #endif - // FT Motion can be toggled if Standard Motion is also active const bool using_ftMotion = ENABLED(NO_STANDARD_MOTION) || TERN0(FT_MOTION, ftMotion.cfg.active); diff --git a/buildroot/tests/rambo b/buildroot/tests/rambo index fcbe648b1d..2730f9f8f8 100755 --- a/buildroot/tests/rambo +++ b/buildroot/tests/rambo @@ -75,6 +75,7 @@ opt_set MOTHERBOARD BOARD_RAMBO EXTRUDERS 0 TEMP_SENSOR_BED 1 TEMP_SENSOR_PROBE AXIS_RELATIVE_MODES '{ false, false, false }' opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER FIX_MOUNTED_PROBE Z_SAFE_HOMING \ FT_MOTION FTM_SMOOTHING FTM_HOME_AND_PROBE NO_STANDARD_MOTION +opt_disable FTM_SHAPER_EI FTM_SHAPER_2HEI FTM_SHAPER_3HEI exec_test $1 $2 "Rambo with ZERO EXTRUDERS, heated bed, FT_MOTION" "$3" #