From 1cdcc6adfacf93166a6e35a55a83935760323f4f Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 9 Jun 2018 23:26:34 -0500 Subject: [PATCH] Adaptive multiaxis step smoothing - Stepper bugs fixed - Support MIXING_EXTRUDER with Linear Advance - Miscellaneous cleanup Co-Authored-By: ejtagle --- Marlin/Conditionals_post.h | 114 ++- Marlin/Configuration_adv.h | 8 + .../AlephObjects/TAZ4/Configuration_adv.h | 8 + .../Anet/A6/Configuration_adv.h | 8 + .../Anet/A8/Configuration_adv.h | 8 + .../BIBO/TouchX/Cyclops/Configuration_adv.h | 8 + .../BIBO/TouchX/default/Configuration_adv.h | 8 + .../BQ/Hephestos/Configuration_adv.h | 8 + .../BQ/Hephestos_2/Configuration_adv.h | 8 + .../BQ/WITBOX/Configuration_adv.h | 8 + .../Cartesio/Configuration_adv.h | 8 + .../Creality/CR-10/Configuration_adv.h | 8 + .../Creality/CR-10S/Configuration_adv.h | 8 + .../Creality/CR-10mini/Configuration_adv.h | 8 + .../Creality/CR-8/Configuration_adv.h | 8 + .../Creality/Ender-2/Configuration_adv.h | 8 + .../Creality/Ender-3/Configuration_adv.h | 8 + .../Creality/Ender-4/Configuration_adv.h | 8 + .../Felix/Configuration_adv.h | 8 + .../FolgerTech/i3-2020/Configuration_adv.h | 8 + .../Prusa i3 Pro C/Configuration_adv.h | 8 + .../Prusa i3 Pro W/Configuration_adv.h | 8 + .../Infitary/i3-M508/Configuration_adv.h | 8 + .../JGAurora/A5/Configuration_adv.h | 8 + .../Malyan/M150/Configuration_adv.h | 8 + .../Micromake/C1/enhanced/Configuration_adv.h | 8 + .../RigidBot/Configuration_adv.h | 8 + .../SCARA/Configuration_adv.h | 8 + .../Sanguinololu/Configuration_adv.h | 8 + .../TinyBoy2/Configuration_adv.h | 8 + .../Velleman/K8200/Configuration_adv.h | 8 + .../Velleman/K8400/Configuration_adv.h | 8 + .../Wanhao/Duplicator 6/Configuration_adv.h | 8 + .../FLSUN/auto_calibrate/Configuration_adv.h | 8 + .../delta/FLSUN/kossel/Configuration_adv.h | 8 + .../FLSUN/kossel_mini/Configuration_adv.h | 8 + .../delta/generic/Configuration_adv.h | 8 + .../delta/kossel_mini/Configuration_adv.h | 8 + .../delta/kossel_pro/Configuration_adv.h | 8 + .../delta/kossel_xl/Configuration_adv.h | 8 + .../gCreate/gMax1.5+/Configuration_adv.h | 8 + .../makibox/Configuration_adv.h | 8 + .../tvrrug/Round2/Configuration_adv.h | 8 + .../wt150/Configuration_adv.h | 8 + Marlin/planner.cpp | 10 +- Marlin/planner.h | 4 +- Marlin/stepper.cpp | 780 +++++++++--------- Marlin/stepper.h | 134 +-- 48 files changed, 928 insertions(+), 458 deletions(-) diff --git a/Marlin/Conditionals_post.h b/Marlin/Conditionals_post.h index 2e91e44097..df44597d9c 100644 --- a/Marlin/Conditionals_post.h +++ b/Marlin/Conditionals_post.h @@ -205,15 +205,6 @@ #define MAX_AUTORETRACT 99 #endif -/** - * MAX_STEP_FREQUENCY differs for TOSHIBA - */ -#if ENABLED(CONFIG_STEPPERS_TOSHIBA) - #define MAX_STEP_FREQUENCY 10000 // Max step frequency for Toshiba Stepper Controllers -#else - #define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) -#endif - // MS1 MS2 Stepper Driver Microstepping mode table #define MICROSTEP1 LOW,LOW #if ENABLED(HEROIC_STEPPER_DRIVERS) @@ -1320,4 +1311,109 @@ #define HAS_FOLDER_SORTING (FOLDER_SORTING || ENABLED(SDSORT_GCODE)) #endif +// Calculate a default maximum stepper rate, if not supplied +#ifndef MAXIMUM_STEPPER_RATE + #define MAXIMUM_STEPPER_RATE (1000000UL / (2UL * (MINIMUM_STEPPER_PULSE))) +#endif + +// +// Estimate the amount of time the ISR will take to execute +// + +// The base ISR takes 752 cycles +#define ISR_BASE_CYCLES 752UL + +// Linear advance base time is 32 cycles +#if ENABLED(LIN_ADVANCE) + #define ISR_LA_BASE_CYCLES 32UL +#else + #define ISR_LA_BASE_CYCLES 0UL +#endif + +// S curve interpolation adds 160 cycles +#if ENABLED(S_CURVE_ACCELERATION) + #define ISR_S_CURVE_CYCLES 160UL +#else + #define ISR_S_CURVE_CYCLES 0UL +#endif + +// Stepper Loop base cycles +#define ISR_LOOP_BASE_CYCLES 32UL + +// And each stepper takes 88 cycles +#define ISR_STEPPER_CYCLES 88UL + +// For each stepper, we add its time +#ifdef HAS_X_STEP + #define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES +#else + #define ISR_X_STEPPER_CYCLES 0UL +#endif + +// For each stepper, we add its time +#ifdef HAS_Y_STEP + #define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES +#else + #define ISR_Y_STEPPER_CYCLES 0UL +#endif + +// For each stepper, we add its time +#ifdef HAS_Z_STEP + #define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES +#else + #define ISR_Z_STEPPER_CYCLES 0UL +#endif + +// E is always interpolated, even for mixing extruders +#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES + +// If linear advance is disabled, then the loop also handles them +#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER) + #define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * ISR_STEPPER_CYCLES) +#else + #define ISR_MIXING_STEPPER_CYCLES 0UL +#endif + +// And the total minimum loop time is, without including the base +#define MIN_ISR_LOOP_CYCLES (ISR_X_STEPPER_CYCLES + ISR_Y_STEPPER_CYCLES + ISR_Z_STEPPER_CYCLES + ISR_E_STEPPER_CYCLES + ISR_MIXING_STEPPER_CYCLES) + +// But the user could be enforcing a minimum time, so the loop time is +#define ISR_LOOP_CYCLES (ISR_LOOP_BASE_CYCLES + MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES)) + +// If linear advance is enabled, then it is handled separately +#if ENABLED(LIN_ADVANCE) + + // Estimate the minimum LA loop time + #if ENABLED(MIXING_EXTRUDER) + #define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES)) + #else + #define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES + #endif + + // And the real loop time + #define ISR_LA_LOOP_CYCLES MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LA_LOOP_CYCLES) + +#else + #define ISR_LA_LOOP_CYCLES 0UL +#endif + +// Now estimate the total ISR execution time in cycles given a step per ISR multiplier +#define ISR_EXECUTION_CYCLES(rate) (((ISR_BASE_CYCLES + (ISR_LOOP_CYCLES * rate) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / rate) + +// The maximum allowable stepping frequency when doing x128-x1 stepping (in Hz) +#define MAX_128X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(128)) +#define MAX_64X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(64)) +#define MAX_32X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(32)) +#define MAX_16X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(16)) +#define MAX_8X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(8)) +#define MAX_4X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(4)) +#define MAX_2X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(2)) +#define MAX_1X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(1)) + +// The minimum allowable frequency for step smoothing will be 1/10 of the maximum nominal frequency (in Hz) +#define MIN_STEP_ISR_FREQUENCY MAX_1X_STEP_ISR_FREQUENCY + +// Disable multiple steps per ISR +//#define DISABLE_MULTI_STEPPING + #endif // CONDITIONALS_POST_H diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 3d1e8f7abe..42f2ecad61 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/AlephObjects/TAZ4/Configuration_adv.h b/Marlin/example_configurations/AlephObjects/TAZ4/Configuration_adv.h index baaa5b6c2d..9bee6cc96c 100644 --- a/Marlin/example_configurations/AlephObjects/TAZ4/Configuration_adv.h +++ b/Marlin/example_configurations/AlephObjects/TAZ4/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 4, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Anet/A6/Configuration_adv.h b/Marlin/example_configurations/Anet/A6/Configuration_adv.h index 253719fcf5..d3e34e3dac 100644 --- a/Marlin/example_configurations/Anet/A6/Configuration_adv.h +++ b/Marlin/example_configurations/Anet/A6/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Anet/A8/Configuration_adv.h b/Marlin/example_configurations/Anet/A8/Configuration_adv.h index b6c8cec826..0a1951a18d 100644 --- a/Marlin/example_configurations/Anet/A8/Configuration_adv.h +++ b/Marlin/example_configurations/Anet/A8/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/BIBO/TouchX/Cyclops/Configuration_adv.h b/Marlin/example_configurations/BIBO/TouchX/Cyclops/Configuration_adv.h index 2b8304d4bc..4e60da6922 100644 --- a/Marlin/example_configurations/BIBO/TouchX/Cyclops/Configuration_adv.h +++ b/Marlin/example_configurations/BIBO/TouchX/Cyclops/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/BIBO/TouchX/default/Configuration_adv.h b/Marlin/example_configurations/BIBO/TouchX/default/Configuration_adv.h index 3d1e8f7abe..42f2ecad61 100644 --- a/Marlin/example_configurations/BIBO/TouchX/default/Configuration_adv.h +++ b/Marlin/example_configurations/BIBO/TouchX/default/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/BQ/Hephestos/Configuration_adv.h b/Marlin/example_configurations/BQ/Hephestos/Configuration_adv.h index fde9398cd1..167242dfe5 100644 --- a/Marlin/example_configurations/BQ/Hephestos/Configuration_adv.h +++ b/Marlin/example_configurations/BQ/Hephestos/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/BQ/Hephestos_2/Configuration_adv.h b/Marlin/example_configurations/BQ/Hephestos_2/Configuration_adv.h index 33ef19c2d4..e4fe7d2d8f 100644 --- a/Marlin/example_configurations/BQ/Hephestos_2/Configuration_adv.h +++ b/Marlin/example_configurations/BQ/Hephestos_2/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/BQ/WITBOX/Configuration_adv.h b/Marlin/example_configurations/BQ/WITBOX/Configuration_adv.h index fde9398cd1..167242dfe5 100644 --- a/Marlin/example_configurations/BQ/WITBOX/Configuration_adv.h +++ b/Marlin/example_configurations/BQ/WITBOX/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Cartesio/Configuration_adv.h b/Marlin/example_configurations/Cartesio/Configuration_adv.h index c6c80f2382..ecfe86cd82 100644 --- a/Marlin/example_configurations/Cartesio/Configuration_adv.h +++ b/Marlin/example_configurations/Cartesio/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Creality/CR-10/Configuration_adv.h b/Marlin/example_configurations/Creality/CR-10/Configuration_adv.h index bc3a2df062..e6b6ca2139 100755 --- a/Marlin/example_configurations/Creality/CR-10/Configuration_adv.h +++ b/Marlin/example_configurations/Creality/CR-10/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Creality/CR-10S/Configuration_adv.h b/Marlin/example_configurations/Creality/CR-10S/Configuration_adv.h index 3b23e04959..08bce22e41 100644 --- a/Marlin/example_configurations/Creality/CR-10S/Configuration_adv.h +++ b/Marlin/example_configurations/Creality/CR-10S/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Creality/CR-10mini/Configuration_adv.h b/Marlin/example_configurations/Creality/CR-10mini/Configuration_adv.h index 8aba468534..ca2f939f7b 100644 --- a/Marlin/example_configurations/Creality/CR-10mini/Configuration_adv.h +++ b/Marlin/example_configurations/Creality/CR-10mini/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Creality/CR-8/Configuration_adv.h b/Marlin/example_configurations/Creality/CR-8/Configuration_adv.h index 8cd45a5743..8c4812bfc1 100644 --- a/Marlin/example_configurations/Creality/CR-8/Configuration_adv.h +++ b/Marlin/example_configurations/Creality/CR-8/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Creality/Ender-2/Configuration_adv.h b/Marlin/example_configurations/Creality/Ender-2/Configuration_adv.h index f44ce42af4..23785efb73 100644 --- a/Marlin/example_configurations/Creality/Ender-2/Configuration_adv.h +++ b/Marlin/example_configurations/Creality/Ender-2/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Creality/Ender-3/Configuration_adv.h b/Marlin/example_configurations/Creality/Ender-3/Configuration_adv.h index 9dae46b7ff..af8105c227 100644 --- a/Marlin/example_configurations/Creality/Ender-3/Configuration_adv.h +++ b/Marlin/example_configurations/Creality/Ender-3/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Creality/Ender-4/Configuration_adv.h b/Marlin/example_configurations/Creality/Ender-4/Configuration_adv.h index 8cd45a5743..8c4812bfc1 100644 --- a/Marlin/example_configurations/Creality/Ender-4/Configuration_adv.h +++ b/Marlin/example_configurations/Creality/Ender-4/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Felix/Configuration_adv.h b/Marlin/example_configurations/Felix/Configuration_adv.h index c7f19baab0..b1cf98f0fc 100644 --- a/Marlin/example_configurations/Felix/Configuration_adv.h +++ b/Marlin/example_configurations/Felix/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/FolgerTech/i3-2020/Configuration_adv.h b/Marlin/example_configurations/FolgerTech/i3-2020/Configuration_adv.h index dfcb684d7d..9568464fbd 100644 --- a/Marlin/example_configurations/FolgerTech/i3-2020/Configuration_adv.h +++ b/Marlin/example_configurations/FolgerTech/i3-2020/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Geeetech/Prusa i3 Pro C/Configuration_adv.h b/Marlin/example_configurations/Geeetech/Prusa i3 Pro C/Configuration_adv.h index 927e4fa9ae..ccb7abd49f 100644 --- a/Marlin/example_configurations/Geeetech/Prusa i3 Pro C/Configuration_adv.h +++ b/Marlin/example_configurations/Geeetech/Prusa i3 Pro C/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Geeetech/Prusa i3 Pro W/Configuration_adv.h b/Marlin/example_configurations/Geeetech/Prusa i3 Pro W/Configuration_adv.h index 927e4fa9ae..ccb7abd49f 100644 --- a/Marlin/example_configurations/Geeetech/Prusa i3 Pro W/Configuration_adv.h +++ b/Marlin/example_configurations/Geeetech/Prusa i3 Pro W/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Infitary/i3-M508/Configuration_adv.h b/Marlin/example_configurations/Infitary/i3-M508/Configuration_adv.h index b0f3c760d3..928b038bc4 100644 --- a/Marlin/example_configurations/Infitary/i3-M508/Configuration_adv.h +++ b/Marlin/example_configurations/Infitary/i3-M508/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/JGAurora/A5/Configuration_adv.h b/Marlin/example_configurations/JGAurora/A5/Configuration_adv.h index ca4af07dd4..b005ea0bce 100644 --- a/Marlin/example_configurations/JGAurora/A5/Configuration_adv.h +++ b/Marlin/example_configurations/JGAurora/A5/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Malyan/M150/Configuration_adv.h b/Marlin/example_configurations/Malyan/M150/Configuration_adv.h index 1b7ea9f73c..686ec8d590 100644 --- a/Marlin/example_configurations/Malyan/M150/Configuration_adv.h +++ b/Marlin/example_configurations/Malyan/M150/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Micromake/C1/enhanced/Configuration_adv.h b/Marlin/example_configurations/Micromake/C1/enhanced/Configuration_adv.h index 5a3ecda182..1861129d37 100644 --- a/Marlin/example_configurations/Micromake/C1/enhanced/Configuration_adv.h +++ b/Marlin/example_configurations/Micromake/C1/enhanced/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/RigidBot/Configuration_adv.h b/Marlin/example_configurations/RigidBot/Configuration_adv.h index 5205cf7d88..3954bbf90a 100644 --- a/Marlin/example_configurations/RigidBot/Configuration_adv.h +++ b/Marlin/example_configurations/RigidBot/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/SCARA/Configuration_adv.h b/Marlin/example_configurations/SCARA/Configuration_adv.h index 5b23a377d8..a12357e0b9 100644 --- a/Marlin/example_configurations/SCARA/Configuration_adv.h +++ b/Marlin/example_configurations/SCARA/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Sanguinololu/Configuration_adv.h b/Marlin/example_configurations/Sanguinololu/Configuration_adv.h index bcfb204cc5..3cdd081712 100644 --- a/Marlin/example_configurations/Sanguinololu/Configuration_adv.h +++ b/Marlin/example_configurations/Sanguinololu/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/TinyBoy2/Configuration_adv.h b/Marlin/example_configurations/TinyBoy2/Configuration_adv.h index d04bb4c591..a185144536 100644 --- a/Marlin/example_configurations/TinyBoy2/Configuration_adv.h +++ b/Marlin/example_configurations/TinyBoy2/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Velleman/K8200/Configuration_adv.h b/Marlin/example_configurations/Velleman/K8200/Configuration_adv.h index e8081987a6..1fd114fda6 100644 --- a/Marlin/example_configurations/Velleman/K8200/Configuration_adv.h +++ b/Marlin/example_configurations/Velleman/K8200/Configuration_adv.h @@ -453,6 +453,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Velleman/K8400/Configuration_adv.h b/Marlin/example_configurations/Velleman/K8400/Configuration_adv.h index 388ce8273b..9b7cb314e5 100644 --- a/Marlin/example_configurations/Velleman/K8400/Configuration_adv.h +++ b/Marlin/example_configurations/Velleman/K8400/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/Wanhao/Duplicator 6/Configuration_adv.h b/Marlin/example_configurations/Wanhao/Duplicator 6/Configuration_adv.h index 9bccf30421..dbe4532666 100644 --- a/Marlin/example_configurations/Wanhao/Duplicator 6/Configuration_adv.h +++ b/Marlin/example_configurations/Wanhao/Duplicator 6/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h b/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h index afd5093117..778080e5b3 100644 --- a/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h +++ b/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h @@ -452,6 +452,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/delta/FLSUN/kossel/Configuration_adv.h b/Marlin/example_configurations/delta/FLSUN/kossel/Configuration_adv.h index 9f66c1e75f..f86c8226b7 100644 --- a/Marlin/example_configurations/delta/FLSUN/kossel/Configuration_adv.h +++ b/Marlin/example_configurations/delta/FLSUN/kossel/Configuration_adv.h @@ -452,6 +452,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h b/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h index 76fc35948d..b87c917ca8 100644 --- a/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h +++ b/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h @@ -452,6 +452,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/delta/generic/Configuration_adv.h b/Marlin/example_configurations/delta/generic/Configuration_adv.h index 76fc35948d..b87c917ca8 100644 --- a/Marlin/example_configurations/delta/generic/Configuration_adv.h +++ b/Marlin/example_configurations/delta/generic/Configuration_adv.h @@ -452,6 +452,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h index 76fc35948d..b87c917ca8 100644 --- a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h +++ b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h @@ -452,6 +452,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h index b3e7295ac1..0a6616807b 100644 --- a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h +++ b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h @@ -457,6 +457,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h index ad8dc82860..a70affd960 100644 --- a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h +++ b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h @@ -452,6 +452,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/gCreate/gMax1.5+/Configuration_adv.h b/Marlin/example_configurations/gCreate/gMax1.5+/Configuration_adv.h index 631bdd7a69..112cc0d328 100644 --- a/Marlin/example_configurations/gCreate/gMax1.5+/Configuration_adv.h +++ b/Marlin/example_configurations/gCreate/gMax1.5+/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/makibox/Configuration_adv.h b/Marlin/example_configurations/makibox/Configuration_adv.h index 52479f445e..8d6f91f950 100644 --- a/Marlin/example_configurations/makibox/Configuration_adv.h +++ b/Marlin/example_configurations/makibox/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h index 3f5a8d313d..d3faf50e86 100644 --- a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h +++ b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/example_configurations/wt150/Configuration_adv.h b/Marlin/example_configurations/wt150/Configuration_adv.h index 1cc92dbfa6..568014f27c 100644 --- a/Marlin/example_configurations/wt150/Configuration_adv.h +++ b/Marlin/example_configurations/wt150/Configuration_adv.h @@ -450,6 +450,14 @@ //#define JUNCTION_DEVIATION_INCLUDE_E #endif +/** + * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies + * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible + * vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the + * lowest stepping frequencies. + */ +//#define ADAPTIVE_STEP_SMOOTHING + // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU. #define MICROSTEP_MODES { 16, 16, 16, 16, 16 } // [1,2,4,8,16] diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index f52d6fc574..b4099a9ca1 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -1628,10 +1628,16 @@ bool Planner::_populate_block(block_t * const block, bool split_move, // Bail if this is a zero-length block if (block->step_event_count < MIN_STEPS_PER_SEGMENT) return false; - // For a mixing extruder, get a magnified step_event_count for each + // For a mixing extruder, get a magnified esteps for each #if ENABLED(MIXING_EXTRUDER) for (uint8_t i = 0; i < MIXING_STEPPERS; i++) - block->mix_event_count[i] = mixing_factor[i] * block->step_event_count; + block->mix_steps[i] = mixing_factor[i] * ( + #if ENABLED(LIN_ADVANCE) + esteps + #else + block->step_event_count + #endif + ); #endif #if FAN_COUNT > 0 diff --git a/Marlin/planner.h b/Marlin/planner.h index 0fea595d3c..39b23928c8 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -103,7 +103,7 @@ typedef struct { uint8_t active_extruder; // The extruder to move (if E move) #if ENABLED(MIXING_EXTRUDER) - uint32_t mix_event_count[MIXING_STEPPERS]; // Scaled step_event_count for the mixing steppers + uint32_t mix_steps[MIXING_STEPPERS]; // Scaled steps[E_AXIS] for the mixing steppers #endif // Settings for the trapezoid generator @@ -125,7 +125,7 @@ typedef struct { // Advance extrusion #if ENABLED(LIN_ADVANCE) bool use_advance_lead; - uint16_t advance_speed, // Timer value for extruder speed offset + uint16_t advance_speed, // STEP timer value for extruder speed offset ISR max_adv_steps, // max. advance steps to get cruising speed pressure (not always nominal_speed!) final_adv_steps; // advance steps due to exit speed float e_D_ratio; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index c03a58d84f..60ab49f28a 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -46,6 +46,29 @@ * and Philipp Tiefenbacher. */ +/** + * __________________________ + * /| |\ _________________ ^ + * / | | \ /| |\ | + * / | | \ / | | \ s + * / | | | | | \ p + * / | | | | | \ e + * +-----+------------------------+---+--+---------------+----+ e + * | BLOCK 1 | BLOCK 2 | d + * + * time -----> + * + * The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates + * first block->accelerate_until step_events_completed, then keeps going at constant speed until + * step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. + * The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far. + */ + +/** + * Marlin uses the Bresenham algorithm. For a detailed explanation of theory and + * method see https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html + */ + /** * Jerk controlled movements planner added Apr 2018 by Eduardo José Tagle. * Equations based on Synthethos TinyG2 sources, but the fixed-point @@ -86,10 +109,14 @@ block_t* Stepper::current_block = NULL; // A pointer to the block currently bei // private: uint8_t Stepper::last_direction_bits = 0, - Stepper::last_movement_extruder = 0xFF, Stepper::axis_did_move; + bool Stepper::abort_current_block; +#if DISABLED(MIXING_EXTRUDER) + uint8_t Stepper::last_moved_extruder = 0xFF; +#endif + #if ENABLED(X_DUAL_ENDSTOPS) bool Stepper::locked_X_motor = false, Stepper::locked_X2_motor = false; #endif @@ -100,19 +127,30 @@ bool Stepper::abort_current_block; bool Stepper::locked_Z_motor = false, Stepper::locked_Z2_motor = false; #endif -/** - * Marlin uses the Bresenham algorithm. For a detailed explanation of theory and - * method see https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html - * - * The implementation used here additionally rounds up the starting seed. - */ +uint32_t Stepper::acceleration_time, Stepper::deceleration_time; +uint8_t Stepper::steps_per_isr; -int32_t Stepper::counter_X = 0, - Stepper::counter_Y = 0, - Stepper::counter_Z = 0, - Stepper::counter_E = 0; +#if DISABLED(ADAPTIVE_STEP_SMOOTHING) + constexpr +#endif + uint8_t Stepper::oversampling_factor; -uint32_t Stepper::step_events_completed = 0; // The number of step events executed in the current block +int32_t Stepper::delta_error[XYZE] = { 0 }; + +uint32_t Stepper::advance_dividend[XYZE] = { 0 }, + Stepper::advance_divisor = 0, + Stepper::step_events_completed = 0, // The number of step events executed in the current block + Stepper::accelerate_until, // The point from where we need to stop acceleration + Stepper::decelerate_after, // The point from where we need to start decelerating + Stepper::step_event_count; // The total event count for the current block + +#if ENABLED(MIXING_EXTRUDER) + int32_t Stepper::delta_error_m[MIXING_STEPPERS]; + uint32_t Stepper::advance_dividend_m[MIXING_STEPPERS], + Stepper::advance_divisor_m; +#else + int8_t Stepper::active_extruder; // Active extruder +#endif #if ENABLED(S_CURVE_ACCELERATION) int32_t __attribute__((used)) Stepper::bezier_A __asm__("bezier_A"); // A coefficient in Bézier speed curve with alias for assembler @@ -125,49 +163,32 @@ uint32_t Stepper::step_events_completed = 0; // The number of step events execut #endif uint32_t Stepper::nextMainISR = 0; -bool Stepper::all_steps_done = false; #if ENABLED(LIN_ADVANCE) - uint32_t Stepper::LA_decelerate_after; + constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF; + uint32_t Stepper::nextAdvanceISR = LA_ADV_NEVER, + Stepper::LA_isr_rate = LA_ADV_NEVER; + uint16_t Stepper::LA_current_adv_steps = 0, + Stepper::LA_final_adv_steps, + Stepper::LA_max_adv_steps; - constexpr uint32_t ADV_NEVER = 0xFFFFFFFF; - uint32_t Stepper::nextAdvanceISR = ADV_NEVER, - Stepper::eISR_Rate = ADV_NEVER; - uint16_t Stepper::current_adv_steps = 0, - Stepper::final_adv_steps, - Stepper::max_adv_steps; + int8_t Stepper::LA_steps = 0; - int8_t Stepper::e_steps = 0; - - #if E_STEPPERS > 1 - int8_t Stepper::LA_active_extruder; // Copy from current executed block. Needed because current_block is set to NULL "too early". - #else - constexpr int8_t Stepper::LA_active_extruder; - #endif - - bool Stepper::use_advance_lead; + bool Stepper::LA_use_advance_lead; #endif // LIN_ADVANCE -uint32_t Stepper::acceleration_time, Stepper::deceleration_time; - -volatile int32_t Stepper::count_position[NUM_AXIS] = { 0 }; -int8_t Stepper::count_direction[NUM_AXIS] = { 1, 1, 1, 1 }; - -#if ENABLED(MIXING_EXTRUDER) - int32_t Stepper::counter_m[MIXING_STEPPERS]; -#endif - -uint32_t Stepper::ticks_nominal; -uint8_t Stepper::step_loops, Stepper::step_loops_nominal; - +int32_t Stepper::ticks_nominal = -1; #if DISABLED(S_CURVE_ACCELERATION) uint32_t Stepper::acc_step_rate; // needed for deceleration start point #endif volatile int32_t Stepper::endstops_trigsteps[XYZ]; +volatile int32_t Stepper::count_position[NUM_AXIS] = { 0 }; +int8_t Stepper::count_direction[NUM_AXIS] = { 0, 0, 0, 0 }; + #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS) #define DUAL_ENDSTOP_APPLY_STEP(A,V) \ if (homing_dual_axis) { \ @@ -200,7 +221,7 @@ volatile int32_t Stepper::endstops_trigsteps[XYZ]; X2_DIR_WRITE(v); \ } \ else { \ - if (current_block->active_extruder) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \ + if (movement_extruder()) X2_DIR_WRITE(v); else X_DIR_WRITE(v); \ } #define X_APPLY_STEP(v,ALWAYS) \ if (extruder_duplication_enabled || ALWAYS) { \ @@ -208,7 +229,7 @@ volatile int32_t Stepper::endstops_trigsteps[XYZ]; X2_STEP_WRITE(v); \ } \ else { \ - if (current_block->active_extruder) X2_STEP_WRITE(v); else X_STEP_WRITE(v); \ + if (movement_extruder()) X2_STEP_WRITE(v); else X_STEP_WRITE(v); \ } #else #define X_APPLY_DIR(v,Q) X_DIR_WRITE(v) @@ -240,7 +261,7 @@ volatile int32_t Stepper::endstops_trigsteps[XYZ]; #endif #if DISABLED(MIXING_EXTRUDER) - #define E_APPLY_STEP(v,Q) E_STEP_WRITE(current_block->active_extruder, v) + #define E_APPLY_STEP(v,Q) E_STEP_WRITE(active_extruder, v) #endif // intRes = longIn1 * longIn2 >> 24 @@ -303,25 +324,6 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2 return intRes; } -// Some useful constants - -/** - * __________________________ - * /| |\ _________________ ^ - * / | | \ /| |\ | - * / | | \ / | | \ s - * / | | | | | \ p - * / | | | | | \ e - * +-----+------------------------+---+--+---------------+----+ e - * | BLOCK 1 | BLOCK 2 | d - * - * time -----> - * - * The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates - * first block->accelerate_until step_events_completed, then keeps going at constant speed until - * step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. - * The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far. - */ void Stepper::wake_up() { // TCNT1 = 0; ENABLE_STEPPER_DRIVER_INTERRUPT(); @@ -357,14 +359,25 @@ void Stepper::set_directions() { #endif #if DISABLED(LIN_ADVANCE) - if (motor_direction(E_AXIS)) { - REV_E_DIR(current_block->active_extruder); - count_direction[E_AXIS] = -1; - } - else { - NORM_E_DIR(current_block->active_extruder); - count_direction[E_AXIS] = 1; - } + #if ENABLED(MIXING_EXTRUDER) + if (motor_direction(E_AXIS)) { + MIXING_STEPPERS_LOOP(j) REV_E_DIR(j); + count_direction[E_AXIS] = -1; + } + else { + MIXING_STEPPERS_LOOP(j) NORM_E_DIR(j); + count_direction[E_AXIS] = 1; + } + #else + if (motor_direction(E_AXIS)) { + REV_E_DIR(active_extruder); + count_direction[E_AXIS] = -1; + } + else { + NORM_E_DIR(active_extruder); + count_direction[E_AXIS] = 1; + } + #endif #endif // !LIN_ADVANCE } @@ -1097,15 +1110,6 @@ void Stepper::set_directions() { * Stepper Driver Interrupt * * Directly pulses the stepper motors at high frequency. - * Timer 1 runs at a base frequency of 2MHz, with this ISR using OCR1A compare mode. - * - * OCR1A Frequency - * 1 2 MHz - * 50 40 KHz - * 100 20 KHz - capped max rate - * 200 10 KHz - nominal max rate - * 2000 1 KHz - sleep rate - * 4000 500 Hz - init rate */ HAL_STEP_TIMER_ISR { @@ -1119,10 +1123,6 @@ HAL_STEP_TIMER_ISR { #define STEP_MULTIPLY(A,B) MultiU24X32toH16(A, B) void Stepper::isr() { - - // Disable interrupts, to avoid ISR preemption while we reprogram the period - DISABLE_ISRS(); - // Program timer compare for the maximum period, so it does NOT // flag an interrupt while this ISR is running - So changes from small // periods to big periods are respected and the timer does not reset to 0 @@ -1169,7 +1169,7 @@ void Stepper::isr() { #if ENABLED(LIN_ADVANCE) // Compute the time remaining for the advance isr - if (nextAdvanceISR != ADV_NEVER) nextAdvanceISR -= interval; + if (nextAdvanceISR != LA_ADV_NEVER) nextAdvanceISR -= interval; #endif /** @@ -1211,10 +1211,8 @@ void Stepper::isr() { /** * Get the current tick value + margin * Assuming at least 6µs between calls to this ISR... - * On AVR the ISR epilogue is estimated at 40 instructions - close to 2.5µS. - * On ARM the ISR epilogue is estimated at 10 instructions - close to 200nS. - * In either case leave at least 8µS for other tasks to execute - That allows - * up to 100khz stepping rates + * On AVR the ISR epilogue+prologue is estimated at 100 instructions - Give 8µs as margin + * On ARM the ISR epilogue+prologue is estimated at 20 instructions - Give 1µs as margin */ min_ticks = HAL_timer_get_count(STEP_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * 8); // ISR never takes more than 1ms, so this shouldn't cause trouble @@ -1262,97 +1260,34 @@ void Stepper::stepper_pulse_phase_isr() { if (!current_block) return; // Take multiple steps per interrupt (For high speed moves) - all_steps_done = false; - for (uint8_t i = step_loops; i--;) { + for (uint8_t i = steps_per_isr; i--;) { - #define _COUNTER(AXIS) counter_## AXIS #define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP #define _INVERT_STEP_PIN(AXIS) INVERT_## AXIS ##_STEP_PIN - // Advance the Bresenham counter; start a pulse if the axis needs a step + // Start an active pulse, if Bresenham says so, and update position #define PULSE_START(AXIS) do{ \ - _COUNTER(AXIS) += current_block->steps[_AXIS(AXIS)]; \ - if (_COUNTER(AXIS) >= 0) { _APPLY_STEP(AXIS)(!_INVERT_STEP_PIN(AXIS), 0); } \ - }while(0) - - // Advance the Bresenham counter; start a pulse if the axis needs a step - #define STEP_TICK(AXIS) do { \ - if (_COUNTER(AXIS) >= 0) { \ - _COUNTER(AXIS) -= current_block->step_event_count; \ + delta_error[_AXIS(AXIS)] += advance_dividend[_AXIS(AXIS)]; \ + if (delta_error[_AXIS(AXIS)] >= 0) { \ + _APPLY_STEP(AXIS)(!_INVERT_STEP_PIN(AXIS), 0); \ count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \ } \ }while(0) - // Stop an active pulse, if any - #define PULSE_STOP(AXIS) _APPLY_STEP(AXIS)(_INVERT_STEP_PIN(AXIS), 0) + // Stop an active pulse, if any, and adjust error term + #define PULSE_STOP(AXIS) do { \ + if (delta_error[_AXIS(AXIS)] >= 0) { \ + delta_error[_AXIS(AXIS)] -= advance_divisor; \ + _APPLY_STEP(AXIS)(_INVERT_STEP_PIN(AXIS), 0); \ + } \ + }while(0) - /** - * Estimate the number of cycles that the stepper logic already takes - * up between the start and stop of the X stepper pulse. - * - * Currently this uses very modest estimates of around 5 cycles. - * True values may be derived by careful testing. - * - * Once any delay is added, the cost of the delay code itself - * may be subtracted from this value to get a more accurate delay. - * Delays under 20 cycles (1.25µs) will be very accurate, using NOPs. - * Longer delays use a loop. The resolution is 8 cycles. - */ - #if HAS_X_STEP - #define _CYCLE_APPROX_1 5 - #else - #define _CYCLE_APPROX_1 0 - #endif - #if ENABLED(X_DUAL_STEPPER_DRIVERS) - #define _CYCLE_APPROX_2 _CYCLE_APPROX_1 + 4 - #else - #define _CYCLE_APPROX_2 _CYCLE_APPROX_1 - #endif - #if HAS_Y_STEP - #define _CYCLE_APPROX_3 _CYCLE_APPROX_2 + 5 - #else - #define _CYCLE_APPROX_3 _CYCLE_APPROX_2 - #endif - #if ENABLED(Y_DUAL_STEPPER_DRIVERS) - #define _CYCLE_APPROX_4 _CYCLE_APPROX_3 + 4 - #else - #define _CYCLE_APPROX_4 _CYCLE_APPROX_3 - #endif - #if HAS_Z_STEP - #define _CYCLE_APPROX_5 _CYCLE_APPROX_4 + 5 - #else - #define _CYCLE_APPROX_5 _CYCLE_APPROX_4 - #endif - #if ENABLED(Z_DUAL_STEPPER_DRIVERS) - #define _CYCLE_APPROX_6 _CYCLE_APPROX_5 + 4 - #else - #define _CYCLE_APPROX_6 _CYCLE_APPROX_5 - #endif - #if DISABLED(LIN_ADVANCE) - #if ENABLED(MIXING_EXTRUDER) - #define _CYCLE_APPROX_7 _CYCLE_APPROX_6 + (MIXING_STEPPERS) * 6 - #else - #define _CYCLE_APPROX_7 _CYCLE_APPROX_6 + 5 - #endif - #else - #define _CYCLE_APPROX_7 _CYCLE_APPROX_6 - #endif - - #define CYCLES_EATEN_XYZE _CYCLE_APPROX_7 - #define EXTRA_CYCLES_XYZE (STEP_PULSE_CYCLES - (CYCLES_EATEN_XYZE)) - - /** - * If a minimum pulse time was specified get the timer 0 value. - * - * On AVR the TCNT0 timer has an 8x prescaler, so it increments every 8 cycles. - * That's every 0.5µs on 16MHz and every 0.4µs on 20MHz. - * 20 counts of TCNT0 -by itself- is a good pulse delay. - * 10µs = 160 or 200 cycles. - */ - #if EXTRA_CYCLES_XYZE > 20 - hal_timer_t pulse_start = HAL_timer_get_count(PULSE_TIMER_NUM); + #if MINIMUM_STEPPER_PULSE > 0 + // Get the timer count and estimate the end of the pulse + hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE)); #endif + // Pulse start #if HAS_X_STEP PULSE_START(X); #endif @@ -1363,64 +1298,48 @@ void Stepper::stepper_pulse_phase_isr() { PULSE_START(Z); #endif + // Pulse E/Mixing extruders #if ENABLED(LIN_ADVANCE) - counter_E += current_block->steps[E_AXIS]; - if (counter_E >= 0) { - #if DISABLED(MIXING_EXTRUDER) - // Don't step E here for mixing extruder - motor_direction(E_AXIS) ? --e_steps : ++e_steps; - #endif + // Tick the E axis, correct error term and update position + delta_error[E_AXIS] += advance_dividend[E_AXIS]; + if (delta_error[E_AXIS] >= 0) { + count_position[E_AXIS] += count_direction[E_AXIS]; + delta_error[E_AXIS] -= advance_divisor; + + // Don't step E here - But remember the number of steps to perform + motor_direction(E_AXIS) ? --LA_steps : ++LA_steps; } - - #if ENABLED(MIXING_EXTRUDER) - // Step mixing steppers proportionally - const bool dir = motor_direction(E_AXIS); - MIXING_STEPPERS_LOOP(j) { - counter_m[j] += current_block->steps[E_AXIS]; - if (counter_m[j] >= 0) { - counter_m[j] -= current_block->mix_event_count[j]; - dir ? --e_steps[j] : ++e_steps[j]; - } - } - #endif - #else // !LIN_ADVANCE - use linear interpolation for E also - #if ENABLED(MIXING_EXTRUDER) - // Keep updating the single E axis - counter_E += current_block->steps[E_AXIS]; - // Tick the counters used for this mix + + // Tick the E axis + delta_error[E_AXIS] += advance_dividend[E_AXIS]; + if (delta_error[E_AXIS] >= 0) { + count_position[E_AXIS] += count_direction[E_AXIS]; + delta_error[E_AXIS] -= advance_divisor; + } + + // Tick the counters used for this mix in proper proportion MIXING_STEPPERS_LOOP(j) { // Step mixing steppers (proportionally) - counter_m[j] += current_block->steps[E_AXIS]; + delta_error_m[j] += advance_dividend_m[j]; // Step when the counter goes over zero - if (counter_m[j] >= 0) E_STEP_WRITE(j, !INVERT_E_STEP_PIN); + if (delta_error_m[j] >= 0) E_STEP_WRITE(j, !INVERT_E_STEP_PIN); } + #else // !MIXING_EXTRUDER PULSE_START(E); #endif #endif // !LIN_ADVANCE - #if HAS_X_STEP - STEP_TICK(X); - #endif - #if HAS_Y_STEP - STEP_TICK(Y); - #endif - #if HAS_Z_STEP - STEP_TICK(Z); - #endif - - STEP_TICK(E); // Always tick the single E axis - - // For minimum pulse time wait before stopping pulses - #if EXTRA_CYCLES_XYZE > 20 - while (EXTRA_CYCLES_XYZE > (uint32_t)(HAL_timer_get_count(PULSE_TIMER_NUM) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ } - pulse_start = HAL_timer_get_count(PULSE_TIMER_NUM); - #elif EXTRA_CYCLES_XYZE > 0 - DELAY_NS(EXTRA_CYCLES_XYZE * NANOSECONDS_PER_CYCLE); + #if MINIMUM_STEPPER_PULSE > 0 + // Just wait for the requested pulse duration + while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ } + // Get the timer count and estimate the end of the pulse for the OFF phase + pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE)); #endif + // Pulse stop #if HAS_X_STEP PULSE_STOP(X); #endif @@ -1434,8 +1353,8 @@ void Stepper::stepper_pulse_phase_isr() { #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) MIXING_STEPPERS_LOOP(j) { - if (counter_m[j] >= 0) { - counter_m[j] -= current_block->mix_event_count[j]; + if (delta_error_m[j] >= 0) { + delta_error_m[j] -= advance_divisor_m; E_STEP_WRITE(j, INVERT_E_STEP_PIN); } } @@ -1444,18 +1363,14 @@ void Stepper::stepper_pulse_phase_isr() { #endif #endif // !LIN_ADVANCE - if (++step_events_completed >= current_block->step_event_count) { - all_steps_done = true; - break; - } + // If all events done, break loop now + if (++step_events_completed >= step_event_count) break; - // For minimum pulse time wait after stopping pulses also - #if EXTRA_CYCLES_XYZE > 20 - if (i) while (EXTRA_CYCLES_XYZE > (uint32_t)(HAL_timer_get_count(PULSE_TIMER_NUM) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ } - #elif EXTRA_CYCLES_XYZE > 0 - if (i) DELAY_NS(EXTRA_CYCLES_XYZE * NANOSECONDS_PER_CYCLE); + #if MINIMUM_STEPPER_PULSE > 0 + // For minimum pulse time wait after stopping pulses also + // Just wait for the requested pulse duration + if (i) while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ } #endif - } // steps_loop } @@ -1471,101 +1386,119 @@ uint32_t Stepper::stepper_block_phase_isr() { // If there is a current block if (current_block) { - // Calculate new timer value - if (step_events_completed <= current_block->accelerate_until) { - - #if ENABLED(S_CURVE_ACCELERATION) - // Get the next speed to use (Jerk limited!) - uint32_t acc_step_rate = - acceleration_time < current_block->acceleration_time - ? _eval_bezier_curve(acceleration_time) - : current_block->cruise_rate; - #else - acc_step_rate = STEP_MULTIPLY(acceleration_time, current_block->acceleration_rate) + current_block->initial_rate; - NOMORE(acc_step_rate, current_block->nominal_rate); - #endif - - // step_rate to timer interval - interval = calc_timer_interval(acc_step_rate); - acceleration_time += interval; - - #if ENABLED(LIN_ADVANCE) - if (current_block->use_advance_lead) { - if (step_events_completed == step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) { - nextAdvanceISR = 0; // Wake up eISR on first acceleration loop and fire ISR if final adv_rate is reached - eISR_Rate = current_block->advance_speed; - } - } - else { - eISR_Rate = ADV_NEVER; - if (e_steps) nextAdvanceISR = 0; - } - #endif // LIN_ADVANCE - } - else if (step_events_completed > current_block->decelerate_after) { - uint32_t step_rate; - - #if ENABLED(S_CURVE_ACCELERATION) - // If this is the 1st time we process the 2nd half of the trapezoid... - if (!bezier_2nd_half) { - // Initialize the Bézier speed curve - _calc_bezier_curve_coeffs(current_block->cruise_rate, current_block->final_rate, current_block->deceleration_time_inverse); - bezier_2nd_half = true; - } - - // Calculate the next speed to use - step_rate = deceleration_time < current_block->deceleration_time - ? _eval_bezier_curve(deceleration_time) - : current_block->final_rate; - #else - - // Using the old trapezoidal control - step_rate = STEP_MULTIPLY(deceleration_time, current_block->acceleration_rate); - if (step_rate < acc_step_rate) { // Still decelerating? - step_rate = acc_step_rate - step_rate; - NOLESS(step_rate, current_block->final_rate); - } - else - step_rate = current_block->final_rate; - #endif - - // step_rate to timer interval - interval = calc_timer_interval(step_rate); - deceleration_time += interval; - - #if ENABLED(LIN_ADVANCE) - if (current_block->use_advance_lead) { - if (step_events_completed <= current_block->decelerate_after + step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) { - nextAdvanceISR = 0; // Wake up eISR on first deceleration loop - eISR_Rate = current_block->advance_speed; - } - } - else { - eISR_Rate = ADV_NEVER; - if (e_steps) nextAdvanceISR = 0; - } - #endif // LIN_ADVANCE - } - else { - - #if ENABLED(LIN_ADVANCE) - // If there are any esteps, fire the next advance_isr "now" - if (e_steps && eISR_Rate != current_block->advance_speed) nextAdvanceISR = 0; - #endif - - // The timer interval is just the nominal value for the nominal speed - interval = ticks_nominal; - - // Ensure this runs at the correct step rate, even if it just came off an acceleration - step_loops = step_loops_nominal; - } - // If current block is finished, reset pointer - if (all_steps_done) { + if (step_events_completed >= step_event_count) { axis_did_move = 0; current_block = NULL; planner.discard_current_block(); } + else { + // Step events not completed yet... + + // Are we in acceleration phase ? + if (step_events_completed <= accelerate_until) { // Calculate new timer value + + #if ENABLED(S_CURVE_ACCELERATION) + // Get the next speed to use (Jerk limited!) + uint32_t acc_step_rate = + acceleration_time < current_block->acceleration_time + ? _eval_bezier_curve(acceleration_time) + : current_block->cruise_rate; + #else + acc_step_rate = STEP_MULTIPLY(acceleration_time, current_block->acceleration_rate) + current_block->initial_rate; + NOMORE(acc_step_rate, current_block->nominal_rate); + #endif + + // acc_step_rate is in steps/second + + // step_rate to timer interval and steps per stepper isr + interval = calc_timer_interval(acc_step_rate, oversampling_factor, &steps_per_isr); + acceleration_time += interval; + + #if ENABLED(LIN_ADVANCE) + if (LA_use_advance_lead) { + // Wake up eISR on first acceleration loop and fire ISR if final adv_rate is reached + if (step_events_completed == steps_per_isr || (LA_steps && LA_isr_rate != current_block->advance_speed)) { + nextAdvanceISR = 0; + LA_isr_rate = current_block->advance_speed; + } + } + else { + LA_isr_rate = LA_ADV_NEVER; + if (LA_steps) nextAdvanceISR = 0; + } + #endif // LIN_ADVANCE + } + // Are we in Deceleration phase ? + else if (step_events_completed > decelerate_after) { + uint32_t step_rate; + + #if ENABLED(S_CURVE_ACCELERATION) + // If this is the 1st time we process the 2nd half of the trapezoid... + if (!bezier_2nd_half) { + // Initialize the Bézier speed curve + _calc_bezier_curve_coeffs(current_block->cruise_rate, current_block->final_rate, current_block->deceleration_time_inverse); + bezier_2nd_half = true; + // The first point starts at cruise rate. Just save evaluation of the Bézier curve + step_rate = current_block->cruise_rate; + } + else { + // Calculate the next speed to use + step_rate = deceleration_time < current_block->deceleration_time + ? _eval_bezier_curve(deceleration_time) + : current_block->final_rate; + } + #else + + // Using the old trapezoidal control + step_rate = STEP_MULTIPLY(deceleration_time, current_block->acceleration_rate); + if (step_rate < acc_step_rate) { // Still decelerating? + step_rate = acc_step_rate - step_rate; + NOLESS(step_rate, current_block->final_rate); + } + else + step_rate = current_block->final_rate; + #endif + + // step_rate is in steps/second + + // step_rate to timer interval and steps per stepper isr + interval = calc_timer_interval(step_rate, oversampling_factor, &steps_per_isr); + deceleration_time += interval; + + #if ENABLED(LIN_ADVANCE) + if (LA_use_advance_lead) { + if (step_events_completed <= decelerate_after + steps_per_isr || + (LA_steps && LA_isr_rate != current_block->advance_speed) + ) { + nextAdvanceISR = 0; // Wake up eISR on first deceleration loop + LA_isr_rate = current_block->advance_speed; + } + } + else { + LA_isr_rate = LA_ADV_NEVER; + if (LA_steps) nextAdvanceISR = 0; + } + #endif // LIN_ADVANCE + } + // We must be in cruise phase otherwise + else { + + #if ENABLED(LIN_ADVANCE) + // If there are any esteps, fire the next advance_isr "now" + if (LA_steps && LA_isr_rate != current_block->advance_speed) nextAdvanceISR = 0; + #endif + + // Calculate the ticks_nominal for this nominal speed, if not done yet + if (ticks_nominal < 0) { + // step_rate to timer interval and loops for the nominal speed + ticks_nominal = calc_timer_interval(current_block->nominal_rate, oversampling_factor, &steps_per_isr); + } + + // The timer interval is just the nominal value for the nominal speed + interval = ticks_nominal; + } + } } // If there is no current block at this point, attempt to pop one from the buffer @@ -1660,25 +1593,82 @@ uint32_t Stepper::stepper_block_phase_isr() { //if (!!current_block->steps[C_AXIS]) SBI(axis_bits, Z_HEAD); axis_did_move = axis_bits; + // No acceleration / deceleration time elapsed so far + acceleration_time = deceleration_time = 0; + + uint8_t oversampling = 0; // Assume we won't use it + #if ENABLED(ADAPTIVE_STEP_SMOOTHING) + // At this point, we must decide if we can use Stepper movement axis smoothing. + uint32_t max_rate = current_block->nominal_rate; // Get the maximum rate (maximum event speed) + while (max_rate < MIN_STEP_ISR_FREQUENCY) { + max_rate <<= 1; + if (max_rate >= MAX_1X_STEP_ISR_FREQUENCY) break; + ++oversampling; + } + oversampling_factor = oversampling; + #endif + + // Based on the oversampling factor, do the calculations + step_event_count = current_block->step_event_count << oversampling; + + // Initialize Bresenham delta errors to 1/2 + delta_error[X_AXIS] = delta_error[Y_AXIS] = delta_error[Z_AXIS] = delta_error[E_AXIS] = -int32_t(step_event_count); + + // Calculate Bresenham dividends + advance_dividend[X_AXIS] = current_block->steps[X_AXIS] << 1; + advance_dividend[Y_AXIS] = current_block->steps[Y_AXIS] << 1; + advance_dividend[Z_AXIS] = current_block->steps[Z_AXIS] << 1; + advance_dividend[E_AXIS] = current_block->steps[E_AXIS] << 1; + + // Calculate Bresenham divisor + advance_divisor = step_event_count << 1; + + // No step events completed so far + step_events_completed = 0; + + // Compute the acceleration and deceleration points + accelerate_until = current_block->accelerate_until << oversampling; + decelerate_after = current_block->decelerate_after << oversampling; + + #if ENABLED(MIXING_EXTRUDER) + const uint32_t e_steps = ( + #if ENABLED(LIN_ADVANCE) + current_block->steps[E_AXIS] + #else + step_event_count + #endif + ); + MIXING_STEPPERS_LOOP(i) { + delta_error_m[i] = -int32_t(e_steps); + advance_dividend_m[i] = current_block->mix_steps[i] << 1; + } + advance_divisor_m = e_steps << 1; + #else + active_extruder = current_block->active_extruder; + #endif + // Initialize the trapezoid generator from the current block. #if ENABLED(LIN_ADVANCE) - #if E_STEPPERS > 1 - if (current_block->active_extruder != last_movement_extruder) { - current_adv_steps = 0; // If the now active extruder wasn't in use during the last move, its pressure is most likely gone. - LA_active_extruder = current_block->active_extruder; - } + #if DISABLED(MIXING_EXTRUDER) && E_STEPPERS > 1 + // If the now active extruder wasn't in use during the last move, its pressure is most likely gone. + if (active_extruder != last_moved_extruder) LA_current_adv_steps = 0; #endif - if ((use_advance_lead = current_block->use_advance_lead)) { - LA_decelerate_after = current_block->decelerate_after; - final_adv_steps = current_block->final_adv_steps; - max_adv_steps = current_block->max_adv_steps; + if ((LA_use_advance_lead = current_block->use_advance_lead)) { + LA_final_adv_steps = current_block->final_adv_steps; + LA_max_adv_steps = current_block->max_adv_steps; } #endif - if (current_block->direction_bits != last_direction_bits || current_block->active_extruder != last_movement_extruder) { + if (current_block->direction_bits != last_direction_bits + #if DISABLED(MIXING_EXTRUDER) + || active_extruder != last_moved_extruder + #endif + ) { last_direction_bits = current_block->direction_bits; - last_movement_extruder = current_block->active_extruder; + #if DISABLED(MIXING_EXTRUDER) + last_moved_extruder = active_extruder; + #endif set_directions(); } @@ -1691,17 +1681,15 @@ uint32_t Stepper::stepper_block_phase_isr() { // on the next call to this ISR, will be discarded. endstops.check_possible_change(); - // No acceleration / deceleration time elapsed so far - acceleration_time = deceleration_time = 0; + #if ENABLED(Z_LATE_ENABLE) + // If delayed Z enable, enable it now. This option will severely interfere with + // timing between pulses when chaining motion between blocks, and it could lead + // to lost steps in both X and Y axis, so avoid using it unless strictly necessary!! + if (current_block->steps[Z_AXIS]) enable_Z(); + #endif - // No step events completed so far - step_events_completed = 0; - - // step_rate to timer interval for the nominal speed - ticks_nominal = calc_timer_interval(current_block->nominal_rate); - - // make a note of the number of step loops required at nominal speed - step_loops_nominal = step_loops; + // Mark the time_nominal as not calculated yet + ticks_nominal = -1; #if DISABLED(S_CURVE_ACCELERATION) // Set as deceleration point the initial rate of the block @@ -1711,24 +1699,12 @@ uint32_t Stepper::stepper_block_phase_isr() { #if ENABLED(S_CURVE_ACCELERATION) // Initialize the Bézier speed curve _calc_bezier_curve_coeffs(current_block->initial_rate, current_block->cruise_rate, current_block->acceleration_time_inverse); - - // We have not started the 2nd half of the trapezoid + // We haven't started the 2nd half of the trapezoid bezier_2nd_half = false; #endif - // Initialize Bresenham counters to 1/2 the ceiling, with proper roundup (as explained in the article linked above) - counter_X = counter_Y = counter_Z = counter_E = -int32_t((current_block->step_event_count + 1) >> 1); - #if ENABLED(MIXING_EXTRUDER) - MIXING_STEPPERS_LOOP(i) - counter_m[i] = -int32_t((current_block->mix_event_count[i] + 1) >> 1); - #endif - - #if ENABLED(Z_LATE_ENABLE) - // If delayed Z enable, enable it now. This option will severely interfere with - // timing between pulses when chaining motion between blocks, and it could lead - // to lost steps in both X and Y axis, so avoid using it unless strictly necessary!! - if (current_block->steps[Z_AXIS]) enable_Z(); - #endif + // Calculate the initial timer interval + interval = calc_timer_interval(current_block->initial_rate, oversampling_factor, &steps_per_isr); } } @@ -1738,65 +1714,85 @@ uint32_t Stepper::stepper_block_phase_isr() { #if ENABLED(LIN_ADVANCE) - #define CYCLES_EATEN_E (E_STEPPERS * 5) - #define EXTRA_CYCLES_E (STEP_PULSE_CYCLES - (CYCLES_EATEN_E)) - - // Timer interrupt for E. e_steps is set in the main routine; + // Timer interrupt for E. LA_steps is set in the main routine uint32_t Stepper::advance_isr() { uint32_t interval; - if (use_advance_lead) { - if (step_events_completed > LA_decelerate_after && current_adv_steps > final_adv_steps) { - e_steps--; - current_adv_steps--; - interval = eISR_Rate; + if (LA_use_advance_lead) { + if (step_events_completed > decelerate_after && LA_current_adv_steps > LA_final_adv_steps) { + LA_steps--; + LA_current_adv_steps--; + interval = LA_isr_rate; } - else if (step_events_completed < LA_decelerate_after && current_adv_steps < max_adv_steps) { - //step_events_completed <= (uint32_t)current_block->accelerate_until) { - e_steps++; - current_adv_steps++; - interval = eISR_Rate; + else if (step_events_completed < decelerate_after && LA_current_adv_steps < LA_max_adv_steps) { + //step_events_completed <= (uint32_t)accelerate_until) { + LA_steps++; + LA_current_adv_steps++; + interval = LA_isr_rate; } else - interval = eISR_Rate = ADV_NEVER; + interval = LA_isr_rate = LA_ADV_NEVER; } else - interval = ADV_NEVER; + interval = LA_ADV_NEVER; - if (e_steps >= 0) - NORM_E_DIR(LA_active_extruder); - else - REV_E_DIR(LA_active_extruder); + #if ENABLED(MIXING_EXTRUDER) + if (LA_steps >= 0) + MIXING_STEPPERS_LOOP(j) NORM_E_DIR(j); + else + MIXING_STEPPERS_LOOP(j) REV_E_DIR(j); + #else + if (LA_steps >= 0) + NORM_E_DIR(active_extruder); + else + REV_E_DIR(active_extruder); + #endif // Step E stepper if we have steps - while (e_steps) { + while (LA_steps) { - #if EXTRA_CYCLES_E > 20 - hal_timer_t pulse_start = HAL_timer_get_count(PULSE_TIMER_NUM); + #if MINIMUM_STEPPER_PULSE > 0 + hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE)); #endif - E_STEP_WRITE(LA_active_extruder, !INVERT_E_STEP_PIN); - - // For minimum pulse time wait before stopping pulses - #if EXTRA_CYCLES_E > 20 - while (EXTRA_CYCLES_E > (hal_timer_t)(HAL_timer_get_count(PULSE_TIMER_NUM) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ } - pulse_start = HAL_timer_get_count(PULSE_TIMER_NUM); - #elif EXTRA_CYCLES_E > 0 - DELAY_NS(EXTRA_CYCLES_E * NANOSECONDS_PER_CYCLE); + #if ENABLED(MIXING_EXTRUDER) + MIXING_STEPPERS_LOOP(j) { + // Step mixing steppers (proportionally) + delta_error_m[j] += advance_dividend_m[j]; + // Step when the counter goes over zero + if (delta_error_m[j] >= 0) E_STEP_WRITE(j, !INVERT_E_STEP_PIN); + } + #else + E_STEP_WRITE(active_extruder, !INVERT_E_STEP_PIN); #endif - e_steps < 0 ? ++e_steps : --e_steps; - - E_STEP_WRITE(LA_active_extruder, INVERT_E_STEP_PIN); - - // For minimum pulse time wait before looping - #if EXTRA_CYCLES_E > 20 - if (e_steps) while (EXTRA_CYCLES_E > (hal_timer_t)(HAL_timer_get_count(PULSE_TIMER_NUM) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ } - #elif EXTRA_CYCLES_E > 0 - if (e_steps) DELAY_NS(EXTRA_CYCLES_E * NANOSECONDS_PER_CYCLE); + #if MINIMUM_STEPPER_PULSE > 0 + // Just wait for the requested pulse duration + while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ } + // Get the timer count and estimate the end of the pulse for the OFF phase + pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE)); #endif - } // e_steps + LA_steps < 0 ? ++LA_steps : --LA_steps; + + #if ENABLED(MIXING_EXTRUDER) + MIXING_STEPPERS_LOOP(j) { + if (delta_error_m[j] >= 0) { + delta_error_m[j] -= advance_divisor_m; + E_STEP_WRITE(j, INVERT_E_STEP_PIN); + } + } + #else + E_STEP_WRITE(active_extruder, INVERT_E_STEP_PIN); + #endif + + #if MINIMUM_STEPPER_PULSE > 0 + // For minimum pulse time wait before looping + // Just wait for the requested pulse duration + if (LA_steps) while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ } + #endif + + } // LA_steps return interval; } @@ -2104,8 +2100,8 @@ void Stepper::report_positions() { #define _APPLY_DIR(AXIS, INVERT) AXIS ##_APPLY_DIR(INVERT, true) #if EXTRA_CYCLES_BABYSTEP > 20 - #define _SAVE_START const hal_timer_t pulse_start = HAL_timer_get_count(STEP_TIMER_NUM) - #define _PULSE_WAIT while (EXTRA_CYCLES_BABYSTEP > (uint32_t)(HAL_timer_get_count(STEP_TIMER_NUM) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ } + #define _SAVE_START const hal_timer_t pulse_start = HAL_timer_get_count(PULSE_TIMER_NUM) + #define _PULSE_WAIT while (EXTRA_CYCLES_BABYSTEP > (uint32_t)(HAL_timer_get_count(PULSE_TIMER_NUM) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ } #else #define _SAVE_START NOOP #if EXTRA_CYCLES_BABYSTEP > 0 diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 8d31429f51..63330b589a 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -99,10 +99,14 @@ class Stepper { private: static uint8_t last_direction_bits, // The next stepping-bits to be output - last_movement_extruder, // Last movement extruder, as computed when the last movement was fetched from planner axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner + static bool abort_current_block; // Signals to the stepper that current block should be aborted + #if DISABLED(MIXING_EXTRUDER) + static uint8_t last_moved_extruder; // Last-moved extruder, as set when the last movement was fetched from planner + #endif + #if ENABLED(X_DUAL_ENDSTOPS) static bool locked_X_motor, locked_X2_motor; #endif @@ -113,9 +117,34 @@ class Stepper { static bool locked_Z_motor, locked_Z2_motor; #endif - // Counter variables for the Bresenham line tracer - static int32_t counter_X, counter_Y, counter_Z, counter_E; - static uint32_t step_events_completed; // The number of step events executed in the current block + static uint32_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks + static uint8_t steps_per_isr; // Count of steps to perform per Stepper ISR call + + #if ENABLED(ADAPTIVE_STEP_SMOOTHING) + static uint8_t oversampling_factor; // Oversampling factor (log2(multiplier)) to increase temporal resolution of axis + #else + static constexpr uint8_t oversampling_factor = 0; + #endif + + // Delta error variables for the Bresenham line tracer + static int32_t delta_error[XYZE]; + static uint32_t advance_dividend[XYZE], + advance_divisor, + step_events_completed, // The number of step events executed in the current block + accelerate_until, // The point from where we need to stop acceleration + decelerate_after, // The point from where we need to start decelerating + step_event_count; // The total event count for the current block + + // Mixing extruder mix delta_errors for bresenham tracing + #if ENABLED(MIXING_EXTRUDER) + static int32_t delta_error_m[MIXING_STEPPERS]; + static uint32_t advance_dividend_m[MIXING_STEPPERS], + advance_divisor_m; + #define MIXING_STEPPERS_LOOP(VAR) \ + for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++) + #else + static int8_t active_extruder; // Active extruder + #endif #if ENABLED(S_CURVE_ACCELERATION) static int32_t bezier_A, // A coefficient in Bézier speed curve @@ -128,33 +157,19 @@ class Stepper { #endif static uint32_t nextMainISR; // time remaining for the next Step ISR - static bool all_steps_done; // all steps done - #if ENABLED(LIN_ADVANCE) - - static uint32_t LA_decelerate_after; // Copy from current executed block. Needed because current_block is set to NULL "too early". - static uint32_t nextAdvanceISR, eISR_Rate; - static uint16_t current_adv_steps, final_adv_steps, max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early". - static int8_t e_steps; - static bool use_advance_lead; - #if E_STEPPERS > 1 - static int8_t LA_active_extruder; // Copy from current executed block. Needed because current_block is set to NULL "too early". - #else - static constexpr int8_t LA_active_extruder = 0; - #endif - + static uint32_t nextAdvanceISR, LA_isr_rate; + static uint16_t LA_current_adv_steps, LA_final_adv_steps, LA_max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early". + static int8_t LA_steps; + static bool LA_use_advance_lead; #endif // LIN_ADVANCE - static uint32_t acceleration_time, deceleration_time; - static uint8_t step_loops, step_loops_nominal; - - static uint32_t ticks_nominal; + static int32_t ticks_nominal; #if DISABLED(S_CURVE_ACCELERATION) static uint32_t acc_step_rate; // needed for deceleration start point #endif static volatile int32_t endstops_trigsteps[XYZ]; - static volatile int32_t endstops_stepsTotal, endstops_stepsDone; // // Positions of stepper motors, in step units @@ -166,16 +181,6 @@ class Stepper { // static int8_t count_direction[NUM_AXIS]; - // - // Mixing extruder mix counters - // - #if ENABLED(MIXING_EXTRUDER) - static int32_t counter_m[MIXING_STEPPERS]; - #define MIXING_STEPPERS_LOOP(VAR) \ - for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++) \ - if (current_block->mix_event_count[VAR]) - #endif - public: // @@ -222,7 +227,15 @@ class Stepper { FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { return TEST(axis_did_move, axis); } // The extruder associated to the last movement - FORCE_INLINE static uint8_t movement_extruder() { return last_movement_extruder; } + FORCE_INLINE static uint8_t movement_extruder() { + return + #if ENABLED(MIXING_EXTRUDER) + 0 + #else + last_moved_extruder + #endif + ; + } // Handle a triggered endstop static void endstop_triggered(const AxisEnum axis); @@ -290,25 +303,42 @@ class Stepper { // Set direction bits for all steppers static void set_directions(); - FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) { + FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t scale, uint8_t* loops) { uint32_t timer; - NOMORE(step_rate, uint32_t(MAX_STEP_FREQUENCY)); + // Scale the frequency, as requested by the caller + step_rate <<= scale; - if (step_rate > 20000) { // If steprate > 20kHz >> step 4 times - step_rate >>= 2; - step_loops = 4; - } - else if (step_rate > 10000) { // If steprate > 10kHz >> step 2 times - step_rate >>= 1; - step_loops = 2; - } - else { - step_loops = 1; - } + uint8_t multistep = 1; + #if DISABLED(DISABLE_MULTI_STEPPING) - NOLESS(step_rate, uint32_t(F_CPU / 500000U)); - step_rate -= F_CPU / 500000; // Correct for minimal speed + // The stepping frequency limits for each multistepping rate + static const uint32_t limit[] PROGMEM = { + ( MAX_1X_STEP_ISR_FREQUENCY ), + ( MAX_2X_STEP_ISR_FREQUENCY >> 1), + ( MAX_4X_STEP_ISR_FREQUENCY >> 2), + ( MAX_8X_STEP_ISR_FREQUENCY >> 3), + ( MAX_16X_STEP_ISR_FREQUENCY >> 4), + ( MAX_32X_STEP_ISR_FREQUENCY >> 5), + ( MAX_64X_STEP_ISR_FREQUENCY >> 6), + (MAX_128X_STEP_ISR_FREQUENCY >> 7) + }; + + // Select the proper multistepping + uint8_t idx = 0; + while (idx < 7 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) { + step_rate >>= 1; + multistep <<= 1; + ++idx; + }; + #else + NOMORE(step_rate, uint32_t(MAX_1X_STEP_ISR_FREQUENCY)); + #endif + *loops = multistep; + + constexpr uint32_t min_step_rate = F_CPU / 500000U; + NOLESS(step_rate, min_step_rate); + step_rate -= min_step_rate; // Correct for minimal speed if (step_rate >= (8 * 256)) { // higher step rate const uint8_t tmp_step_rate = (step_rate & 0x00FF); const uint16_t table_address = (uint16_t)&speed_lookuptable_fast[(uint8_t)(step_rate >> 8)][0], @@ -322,10 +352,8 @@ class Stepper { timer = (uint16_t)pgm_read_word_near(table_address) - (((uint16_t)pgm_read_word_near(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3); } - if (timer < 100) { // (20kHz - this should never happen) - timer = 100; - SERIAL_ECHOLNPAIR(MSG_STEPPER_TOO_HIGH, step_rate); - } + // (there is no need to limit the timer value here. All limits have been + // applied above, and AVR is able to keep up at 30khz Stepping ISR rate) return timer; }