diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index aded988bba30bfdbc7c8948af6645ac7dddee585..1835144e84beb07f6db9d288f26cbf8e782672cc 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/src/config/default/Configuration_adv.h b/Marlin/src/config/default/Configuration_adv.h index aded988bba30bfdbc7c8948af6645ac7dddee585..1835144e84beb07f6db9d288f26cbf8e782672cc 100644 --- a/Marlin/src/config/default/Configuration_adv.h +++ b/Marlin/src/config/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/src/config/examples/AlephObjects/TAZ4/Configuration_adv.h b/Marlin/src/config/examples/AlephObjects/TAZ4/Configuration_adv.h index 1f3561684fa8bdffc2e37dbb4fee36f2cebfbdf1..0b28a2c1e5741f077a913c11273b13fa7b9abb8c 100644 --- a/Marlin/src/config/examples/AlephObjects/TAZ4/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Anet/A6/Configuration_adv.h b/Marlin/src/config/examples/Anet/A6/Configuration_adv.h index 27c62cfdec29c24f12b9cf4311f665552b6f58f9..323320ce66a3ba9377d0abad6f3f08473fbe9a79 100644 --- a/Marlin/src/config/examples/Anet/A6/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Anet/A8/Configuration_adv.h b/Marlin/src/config/examples/Anet/A8/Configuration_adv.h index 8cb51bb3c1404f500587607e2c1a012988b08304..f583a68c55e265df00cfab44370685fdc1198592 100644 --- a/Marlin/src/config/examples/Anet/A8/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Azteeg/X5GT/Configuration_adv.h b/Marlin/src/config/examples/Azteeg/X5GT/Configuration_adv.h index aded988bba30bfdbc7c8948af6645ac7dddee585..1835144e84beb07f6db9d288f26cbf8e782672cc 100644 --- a/Marlin/src/config/examples/Azteeg/X5GT/Configuration_adv.h +++ b/Marlin/src/config/examples/Azteeg/X5GT/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/src/config/examples/BIBO/TouchX/cyclops/Configuration_adv.h b/Marlin/src/config/examples/BIBO/TouchX/cyclops/Configuration_adv.h index 412dda323f42f2a52f5a355d12e7574100321900..64bd3e3e3c40b0f0a980db4f82cf51f6b65e0137 100644 --- a/Marlin/src/config/examples/BIBO/TouchX/cyclops/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/BIBO/TouchX/default/Configuration_adv.h b/Marlin/src/config/examples/BIBO/TouchX/default/Configuration_adv.h index 53f3c847133042e5fcf020556e2da533d1989e47..9d9fc69dc3c07ac29adcee7dcd8793cfe0169e0b 100644 --- a/Marlin/src/config/examples/BIBO/TouchX/default/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/BQ/Hephestos/Configuration_adv.h b/Marlin/src/config/examples/BQ/Hephestos/Configuration_adv.h index 71e20c48bfa8069f6c31109285999e502d65211c..eb59c8cc8d2776ecb78241e786ee121ebeba3d72 100644 --- a/Marlin/src/config/examples/BQ/Hephestos/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/BQ/Hephestos_2/Configuration_adv.h b/Marlin/src/config/examples/BQ/Hephestos_2/Configuration_adv.h index 6e5f5c87717435dbf21a595efb2732be2d6beb87..a8072b4389a2999599b91c0b4c120f5ff791bdb7 100644 --- a/Marlin/src/config/examples/BQ/Hephestos_2/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/BQ/WITBOX/Configuration_adv.h b/Marlin/src/config/examples/BQ/WITBOX/Configuration_adv.h index 71e20c48bfa8069f6c31109285999e502d65211c..eb59c8cc8d2776ecb78241e786ee121ebeba3d72 100644 --- a/Marlin/src/config/examples/BQ/WITBOX/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Cartesio/Configuration_adv.h b/Marlin/src/config/examples/Cartesio/Configuration_adv.h index cf6fa1f30fc9371005efc76cf801c00d62fe1c21..fc1477628fdc9836bbfb22cbd0852e54481f7425 100644 --- a/Marlin/src/config/examples/Cartesio/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Creality/CR-10/Configuration_adv.h b/Marlin/src/config/examples/Creality/CR-10/Configuration_adv.h index 128bb29df1cd2acf282a646edf181dac676f4eeb..b35d6816399c0afd501cbbd4a9087e5b3032b504 100755 --- a/Marlin/src/config/examples/Creality/CR-10/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Creality/CR-10S/Configuration_adv.h b/Marlin/src/config/examples/Creality/CR-10S/Configuration_adv.h index e2a09e10b3a2b9ef5461122cefd9b1fb86f900f6..5ef9925d16877a38a225c3c795685bc3f4194fab 100644 --- a/Marlin/src/config/examples/Creality/CR-10S/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Creality/CR-10mini/Configuration_adv.h b/Marlin/src/config/examples/Creality/CR-10mini/Configuration_adv.h index 166587aa6b134591cb61e8309414f0cb3e9a6f81..3e81a4fdc2e52cef04efa325289aee3e9b0a6317 100644 --- a/Marlin/src/config/examples/Creality/CR-10mini/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Creality/CR-8/Configuration_adv.h b/Marlin/src/config/examples/Creality/CR-8/Configuration_adv.h index 45898905d0807fbb6145406fe4fcca8c4d1ceabe..dbdf78aec183b8f3ed4c15b8c048ea1eef8b9b58 100644 --- a/Marlin/src/config/examples/Creality/CR-8/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Creality/Ender-2/Configuration_adv.h b/Marlin/src/config/examples/Creality/Ender-2/Configuration_adv.h index 0402deab0ec2d5abac174c14e92749532f5f725d..6656c13ec4665f59caa4250ac6a5f839c1969260 100644 --- a/Marlin/src/config/examples/Creality/Ender-2/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Creality/Ender-3/Configuration_adv.h b/Marlin/src/config/examples/Creality/Ender-3/Configuration_adv.h index ff6c86bcb9f66c1577a52b4163f52d3d7017cb2e..7d9e2e2d4df16e37443ff758f24b15b59757790d 100644 --- a/Marlin/src/config/examples/Creality/Ender-3/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Creality/Ender-4/Configuration_adv.h b/Marlin/src/config/examples/Creality/Ender-4/Configuration_adv.h index 45898905d0807fbb6145406fe4fcca8c4d1ceabe..dbdf78aec183b8f3ed4c15b8c048ea1eef8b9b58 100644 --- a/Marlin/src/config/examples/Creality/Ender-4/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Felix/Configuration_adv.h b/Marlin/src/config/examples/Felix/Configuration_adv.h index 9f61140daf15bda3f347bd43948b5557b5d76d45..ac7854978ad7ea685e8559b3ec270c4a4eaa3895 100644 --- a/Marlin/src/config/examples/Felix/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/FolgerTech/i3-2020/Configuration_adv.h b/Marlin/src/config/examples/FolgerTech/i3-2020/Configuration_adv.h index e9ad23b8734cf70656782f4527c3abd8c06d2b18..27b6f5c8b67642ef3395ef5e700c497a50122e07 100644 --- a/Marlin/src/config/examples/FolgerTech/i3-2020/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Geeetech/Prusa i3 Pro C/Configuration_adv.h b/Marlin/src/config/examples/Geeetech/Prusa i3 Pro C/Configuration_adv.h index 58fcca7a6e8979362ea9627708c55c73230609eb..51f1427f8270160047883062178313fb1e90361c 100644 --- a/Marlin/src/config/examples/Geeetech/Prusa i3 Pro C/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Geeetech/Prusa i3 Pro W/Configuration_adv.h b/Marlin/src/config/examples/Geeetech/Prusa i3 Pro W/Configuration_adv.h index 58fcca7a6e8979362ea9627708c55c73230609eb..51f1427f8270160047883062178313fb1e90361c 100644 --- a/Marlin/src/config/examples/Geeetech/Prusa i3 Pro W/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Infitary/i3-M508/Configuration_adv.h b/Marlin/src/config/examples/Infitary/i3-M508/Configuration_adv.h index a4d4ca066bd9e82553e1dc9f5dac2581bba1b0ec..af3f7ef3062cee330ad95416bbe2508e0b8b817c 100644 --- a/Marlin/src/config/examples/Infitary/i3-M508/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/JGAurora/A5/Configuration_adv.h b/Marlin/src/config/examples/JGAurora/A5/Configuration_adv.h index cb5c2910368e23ef5bac66805cdce3edb9e84c98..a5e92f937c9b09b6c12fd803709e37ed7f4501de 100644 --- a/Marlin/src/config/examples/JGAurora/A5/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/MakerParts/Configuration.h b/Marlin/src/config/examples/MakerParts/Configuration.h index 9bc73e9947b44ff1a3cf6fec0ba55e7d7af9a3f4..fbdabf2a3228f5f951e41d17676e23028bb1010b 100644 --- a/Marlin/src/config/examples/MakerParts/Configuration.h +++ b/Marlin/src/config/examples/MakerParts/Configuration.h @@ -631,7 +631,7 @@ * Override with M201 * X, Y, Z, E0 [, E1[, E2[, E3[, E4]]]] */ -#define DEFAULT_MAX_ACCELERATION { MAX_XYAXIS_ACCEL, MAX_XYAXIS_ACCEL, 100, 200 } +#define DEFAULT_MAX_ACCELERATION { MAX_XYAXIS_ACCEL, MAX_XYAXIS_ACCEL, 10, 200 } /** * Default Acceleration (change/s) change = mm/s diff --git a/Marlin/src/config/examples/MakerParts/Configuration_adv.h b/Marlin/src/config/examples/MakerParts/Configuration_adv.h index 14e96f7605351242c5fcac81100684e24a257cff..fc2cafd95cf13a1c90ba343a3facd284b25d2678 100644 --- a/Marlin/src/config/examples/MakerParts/Configuration_adv.h +++ b/Marlin/src/config/examples/MakerParts/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/src/config/examples/Malyan/M150/Configuration_adv.h b/Marlin/src/config/examples/Malyan/M150/Configuration_adv.h index 91363bb917231be938629ae5587d0b578d5d7623..ae0d791eb90886de6d0412d165259a04f651f38c 100644 --- a/Marlin/src/config/examples/Malyan/M150/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Malyan/M200/Configuration_adv.h b/Marlin/src/config/examples/Malyan/M200/Configuration_adv.h index f690d9335ee529f248cda5f7d8c7e94a7f3c7a70..2b7ebec3f395b1d62e798c37b6628eeb568059bf 100644 --- a/Marlin/src/config/examples/Malyan/M200/Configuration_adv.h +++ b/Marlin/src/config/examples/Malyan/M200/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/src/config/examples/Micromake/C1/enhanced/Configuration_adv.h b/Marlin/src/config/examples/Micromake/C1/enhanced/Configuration_adv.h index d3566efd10ab04726b70007a207bd0e338f75e47..34d97d8d83d3f28a04486f84b90499fbf9cc7eb0 100644 --- a/Marlin/src/config/examples/Micromake/C1/enhanced/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Mks/Sbase/Configuration_adv.h b/Marlin/src/config/examples/Mks/Sbase/Configuration_adv.h index 6a59bd4dbf72a1ab2184ab17e8ac1518c6ea4321..7ef674c6500f938da8ea7eb5eb782a282dd3deb7 100644 --- a/Marlin/src/config/examples/Mks/Sbase/Configuration_adv.h +++ b/Marlin/src/config/examples/Mks/Sbase/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/src/config/examples/RigidBot/Configuration_adv.h b/Marlin/src/config/examples/RigidBot/Configuration_adv.h index 3ca2290440946402dbf791faa189fd97a33c7e93..fead01d24d4e827ecda19455457f073594f1e5f5 100644 --- a/Marlin/src/config/examples/RigidBot/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/SCARA/Configuration_adv.h b/Marlin/src/config/examples/SCARA/Configuration_adv.h index af6fbba0caab2b40480a4c75a9d71af0170cfb4c..7bee58d836e925d7a3874ce69e9eb9c2334fc724 100644 --- a/Marlin/src/config/examples/SCARA/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Sanguinololu/Configuration_adv.h b/Marlin/src/config/examples/Sanguinololu/Configuration_adv.h index 29a75957bd00fc9b428a6537a18326f852685cdd..f21cc63fa1af52d47d406c6dd05f8264118aba13 100644 --- a/Marlin/src/config/examples/Sanguinololu/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/TheBorg/Configuration_adv.h b/Marlin/src/config/examples/TheBorg/Configuration_adv.h index a02e2268aa1c0459a09590ffb5d0221dc39ebbbc..ea0b8c5dd8874aab94988995410c0ff915e43930 100644 --- a/Marlin/src/config/examples/TheBorg/Configuration_adv.h +++ b/Marlin/src/config/examples/TheBorg/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/src/config/examples/TinyBoy2/Configuration_adv.h b/Marlin/src/config/examples/TinyBoy2/Configuration_adv.h index 7415412f4ad074b0f5ec442017d9ff41680222b5..d3da581bd2e4857c0d44233b240b8b305104af7a 100644 --- a/Marlin/src/config/examples/TinyBoy2/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/UltiMachine/Archim2/Configuration_adv.h b/Marlin/src/config/examples/UltiMachine/Archim2/Configuration_adv.h index 91b4eef70218fe1a352ae641c688432d10b64d86..09c173062b09812e684830e4d9e572b14b68815a 100644 --- a/Marlin/src/config/examples/UltiMachine/Archim2/Configuration_adv.h +++ b/Marlin/src/config/examples/UltiMachine/Archim2/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/src/config/examples/Velleman/K8200/Configuration_adv.h b/Marlin/src/config/examples/Velleman/K8200/Configuration_adv.h index 32c84639d75b590c591fe63e3c6744dd7e89a56d..9076cd5afc0ae2a38ece2ca86053917dad54067d 100644 --- a/Marlin/src/config/examples/Velleman/K8200/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Velleman/K8400/Configuration_adv.h b/Marlin/src/config/examples/Velleman/K8400/Configuration_adv.h index d2cbf76effd9c4602b4a5aacf045ca17edf0e961..ae3fb55ad24de5197b8f8b6c0382da643b4d0fd1 100644 --- a/Marlin/src/config/examples/Velleman/K8400/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/Wanhao/Duplicator 6/Configuration_adv.h b/Marlin/src/config/examples/Wanhao/Duplicator 6/Configuration_adv.h index 2ebf20b82d573e4d7d5279f13b2e953547bd973e..91898ddfbbdce2bc2dd30020ac9017e2c8856195 100644 --- a/Marlin/src/config/examples/Wanhao/Duplicator 6/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/delta/FLSUN/auto_calibrate/Configuration_adv.h b/Marlin/src/config/examples/delta/FLSUN/auto_calibrate/Configuration_adv.h index a26c0308179e9d5ee7f80695fd671556677713a4..29cfc660655778559bfc05c15ea9120ccab79e2d 100644 --- a/Marlin/src/config/examples/delta/FLSUN/auto_calibrate/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/delta/FLSUN/kossel/Configuration_adv.h b/Marlin/src/config/examples/delta/FLSUN/kossel/Configuration_adv.h index 47781e1b56ec113c801833ad9904954e53faa3c4..884926824af7e6e4904baecc9a7ee635796cbb45 100644 --- a/Marlin/src/config/examples/delta/FLSUN/kossel/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/delta/FLSUN/kossel_mini/Configuration_adv.h b/Marlin/src/config/examples/delta/FLSUN/kossel_mini/Configuration_adv.h index 48d39fe08b4b0c5b26ba852289ddcb8625bae295..293a54312989e58720e70310ef2747f6ed1d3249 100644 --- a/Marlin/src/config/examples/delta/FLSUN/kossel_mini/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/delta/generic/Configuration_adv.h b/Marlin/src/config/examples/delta/generic/Configuration_adv.h index 48d39fe08b4b0c5b26ba852289ddcb8625bae295..293a54312989e58720e70310ef2747f6ed1d3249 100644 --- a/Marlin/src/config/examples/delta/generic/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/delta/kossel_mini/Configuration_adv.h b/Marlin/src/config/examples/delta/kossel_mini/Configuration_adv.h index 48d39fe08b4b0c5b26ba852289ddcb8625bae295..293a54312989e58720e70310ef2747f6ed1d3249 100644 --- a/Marlin/src/config/examples/delta/kossel_mini/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/delta/kossel_pro/Configuration_adv.h b/Marlin/src/config/examples/delta/kossel_pro/Configuration_adv.h index afa2ac030ae690526b5a4cb2551f815e4cc0b3d9..018553c03284dbfdf6979d9eefcd0e6d26a84cd6 100644 --- a/Marlin/src/config/examples/delta/kossel_pro/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/delta/kossel_xl/Configuration_adv.h b/Marlin/src/config/examples/delta/kossel_xl/Configuration_adv.h index 1469f244d961c6cb5c239526eb2f8dad97533ba1..20f56d31c92ff9211c99b73686e792f15a87b39e 100644 --- a/Marlin/src/config/examples/delta/kossel_xl/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/gCreate/gMax1.5+/Configuration_adv.h b/Marlin/src/config/examples/gCreate/gMax1.5+/Configuration_adv.h index 3c225ec0734c0c1bf4e6b0de5715a5ce03f4646f..0f8df2f8bfa3d7c1b4ff99cb19c3c96fc9521b29 100644 --- a/Marlin/src/config/examples/gCreate/gMax1.5+/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/makibox/Configuration_adv.h b/Marlin/src/config/examples/makibox/Configuration_adv.h index 91999d98f1f799bae8e264dea7ee8b09ac5cff6c..ac0bf8cadcb54f22ce7ab88548c5282d74d01ece 100644 --- a/Marlin/src/config/examples/makibox/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/tvrrug/Round2/Configuration_adv.h b/Marlin/src/config/examples/tvrrug/Round2/Configuration_adv.h index 001834a8db257d6b5ffd148b7c66f9b2cc27eda3..66dcabdfc6d32baa8fd5597e1234fa897aedefe8 100644 --- a/Marlin/src/config/examples/tvrrug/Round2/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/config/examples/wt150/Configuration_adv.h b/Marlin/src/config/examples/wt150/Configuration_adv.h index 3f7d68db8df79b5b1ee68baac5846ab91b05fff0..c303b7800174aacddbbfb24ea4018d5bb3e0be17 100644 --- a/Marlin/src/config/examples/wt150/Configuration_adv.h +++ b/Marlin/src/config/examples/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/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 338c76ffea87b9f8b9105f135b3ea77cb788d76d..3ddf5462c6efc11ecd0ee5a3e4924a975109c405 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -215,22 +215,6 @@ #define DEFAULT_KEEPALIVE_INTERVAL 2 #endif -#ifdef CPU_32_BIT - /** - * Hidden options for developer - */ - // Double stepping starts at STEP_DOUBLER_FREQUENCY + 1, quad stepping starts at STEP_DOUBLER_FREQUENCY * 2 + 1 - #ifndef STEP_DOUBLER_FREQUENCY - #if ENABLED(LIN_ADVANCE) - #define STEP_DOUBLER_FREQUENCY 60000 // Hz - #else - #define STEP_DOUBLER_FREQUENCY 80000 // Hz - #endif - #endif - // Disable double / quad stepping - //#define DISABLE_MULTI_STEPPING -#endif - /** * Provide a MAX_AUTORETRACT for older configs */ @@ -238,23 +222,6 @@ #define MAX_AUTORETRACT 99 #endif -/** - * MAX_STEP_FREQUENCY differs for TOSHIBA - */ -#if ENABLED(CONFIG_STEPPERS_TOSHIBA) - #ifdef CPU_32_BIT - #define MAX_STEP_FREQUENCY STEP_DOUBLER_FREQUENCY // Max step frequency for Toshiba Stepper Controllers, 96kHz is close to maximum for an Arduino Due - #else - #define MAX_STEP_FREQUENCY 10000 // Max step frequency for Toshiba Stepper Controllers - #endif -#else - #ifdef CPU_32_BIT - #define MAX_STEP_FREQUENCY (STEP_DOUBLER_FREQUENCY * 4) // Max step frequency for the Due is approx. 330kHz - #else - #define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) - #endif -#endif - // MS1 MS2 Stepper Driver Microstepping mode table #define MICROSTEP1 LOW,LOW #if ENABLED(HEROIC_STEPPER_DRIVERS) @@ -1346,15 +1313,6 @@ #define MANUAL_PROBE_HEIGHT Z_HOMING_HEIGHT #endif -// Stepper pulse duration, in cycles -#define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE) * CYCLES_PER_MICROSECOND) -#ifdef CPU_32_BIT - // Add additional delay for between direction signal and pulse signal of stepper - #ifndef STEPPER_DIRECTION_DELAY - #define STEPPER_DIRECTION_DELAY 0 // time in microseconds - #endif -#endif - #ifndef __SAM3X8E__ //todo: hal: broken hal encapsulation #undef UI_VOLTAGE_LEVEL #undef RADDS_DISPLAY @@ -1486,4 +1444,132 @@ #define USE_EXECUTE_COMMANDS_IMMEDIATE #endif +// +// Estimate the amount of time the ISR will take to execute +// +#ifdef CPU_32_BIT + + // The base ISR takes 792 cycles + #define ISR_BASE_CYCLES 792UL + + // Linear advance base time is 64 cycles + #if ENABLED(LIN_ADVANCE) + #define ISR_LA_BASE_CYCLES 64UL + #else + #define ISR_LA_BASE_CYCLES 0UL + #endif + + // S curve interpolation adds 40 cycles + #if ENABLED(S_CURVE_ACCELERATION) + #define ISR_S_CURVE_CYCLES 40UL + #else + #define ISR_S_CURVE_CYCLES 0UL + #endif + + // Stepper Loop base cycles + #define ISR_LOOP_BASE_CYCLES 4UL + + // And each stepper takes 16 cycles + #define ISR_STEPPER_CYCLES 16UL + +#else + + // 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 + +#endif + +// 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 + ((MINIMUM_STEPPER_PULSE*2UL) > MIN_ISR_LOOP_CYCLES ? (MINIMUM_STEPPER_PULSE*2UL) : 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 ((MINIMUM_STEPPER_PULSE*2UL) > MIN_ISR_LA_LOOP_CYCLES ? (MINIMUM_STEPPER_PULSE*2UL) : 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_S_CURVE_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/src/module/planner.cpp b/Marlin/src/module/planner.cpp index af16e6d55f9bd4bd71f140ea9cb9a10cb218968a..d1e423c3d0eb69642e102d15eed9adb6b6492544 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -679,9 +679,9 @@ void Planner::init() { return r11 | (uint16_t(r12) << 8) | (uint32_t(r13) << 16); } #else - // All the other 32 CPUs can easily perform the inverse using hardware division, + // All other 32-bit MPUs can easily do inverse using hardware division, // so we don't need to reduce precision or to use assembly language at all. - // This routine, for all the other archs, returns 0x100000000 / d ~= 0xFFFFFFFF / d + // This routine, for all other archs, returns 0x100000000 / d ~= 0xFFFFFFFF / d static FORCE_INLINE uint32_t get_period_inverse(const uint32_t d) { return 0xFFFFFFFF / d; } #endif #endif @@ -1646,10 +1646,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/src/module/planner.h b/Marlin/src/module/planner.h index 8e5d52b098dbad4f3d83243838acb75242e44c00..94dda12ff9cbf8807be32d94b0165f8875cc17e1 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -108,7 +108,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 @@ -130,7 +130,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/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 6f21d84aaacf908616c29f91157eb144f31a2032..bb218c22ccef2bd96c590206e9f6ce5351c79ea3 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/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 @@ -97,10 +120,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 @@ -111,19 +138,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; + +int32_t Stepper::delta_error[XYZE] = { 0 }; -uint32_t Stepper::step_events_completed = 0; // The number of step events executed in the current block +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 @@ -132,55 +170,38 @@ uint32_t Stepper::step_events_completed = 0; // The number of step events execut uint32_t __attribute__((used)) Stepper::bezier_F __asm__("bezier_F"); // F coefficient in Bézier speed curve with alias for assembler uint32_t __attribute__((used)) Stepper::bezier_AV __asm__("bezier_AV"); // AV coefficient in Bézier speed curve with alias for assembler #ifdef __AVR__ - bool __attribute__((used)) Stepper::A_negative __asm__("A_negative"); // If A coefficient was negative + bool __attribute__((used)) Stepper::A_negative __asm__("A_negative"); // If A coefficient was negative #endif bool Stepper::bezier_2nd_half; // =false If Bézier curve has been initialized or not #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 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; + 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; - int8_t Stepper::e_steps = 0; + int8_t Stepper::LA_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) { \ @@ -213,7 +234,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) { \ @@ -221,7 +242,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) @@ -253,26 +274,9 @@ 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 -/** - * __________________________ - * /| |\ _________________ ^ - * / | | \ /| |\ | - * / | | \ / | | \ 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(); @@ -308,14 +312,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 } @@ -1128,17 +1143,6 @@ void Stepper::set_directions() { * Stepper Driver Interrupt * * Directly pulses the stepper motors at high frequency. - * - * AVR : - * 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 { @@ -1156,9 +1160,11 @@ HAL_STEP_TIMER_ISR { #endif void Stepper::isr() { - - // Disable interrupts, to avoid ISR preemption while we reprogram the period - DISABLE_ISRS(); + #ifndef __AVR__ + // Disable interrupts, to avoid ISR preemption while we reprogram the period + // (AVR enters the ISR with global interrupts disabled, so no need to do it here) + DISABLE_ISRS(); + #endif // Program timer compare for the maximum period, so it does NOT // flag an interrupt while this ISR is running - So changes from small @@ -1206,7 +1212,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 /** @@ -1248,12 +1254,17 @@ 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 + min_ticks = HAL_timer_get_count(STEP_TIMER_NUM) + hal_timer_t( + #ifdef __AVR__ + 8 + #else + 1 + #endif + * (HAL_TICKS_PER_US) + ); /** * NB: If for some reason the stepper monopolizes the MPU, eventually the @@ -1299,97 +1310,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) - - /** - * 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)) + // 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) - /** - * 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 @@ -1400,64 +1348,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; } - + #else // !LIN_ADVANCE - use linear interpolation for E also #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 + // 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; + } - #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 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 time. + 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 @@ -1471,8 +1403,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); } } @@ -1481,18 +1413,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 + // For minimum pulse time wait after stopping pulses also + // Just wait for the requested pulse time. + if (i) while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ } #endif - } // steps_loop } @@ -1508,100 +1436,118 @@ 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 current block is finished, reset pointer + if (step_events_completed >= step_event_count) { + axis_did_move = 0; + current_block = NULL; + planner.discard_current_block(); + } + else { + // Step events not completed yet... - #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 + // Are we in acceleration phase ? + if (step_events_completed <= accelerate_until) { // Calculate new timer value - // step_rate to timer interval - interval = calc_timer_interval(acc_step_rate); - acceleration_time += interval; + #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 - #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; + // acc_step_rate is in steps/second - #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; - } + // 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; - // Calculate the next speed to use - step_rate = deceleration_time < current_block->deceleration_time - ? _eval_bezier_curve(deceleration_time) - : current_block->final_rate; - #else + #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 + // 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; + // step_rate is in steps/second - #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 { + // 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 there are any esteps, fire the next advance_isr "now" - if (e_steps && eISR_Rate != current_block->advance_speed) nextAdvanceISR = 0; - #endif + #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 { - // The timer interval is just the nominal value for the nominal speed - interval = ticks_nominal; + #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 - // Ensure this runs at the correct step rate, even if it just came off an acceleration - step_loops = step_loops_nominal; - } + // 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); + } - // If current block is finished, reset pointer - if (all_steps_done) { - axis_did_move = 0; - current_block = NULL; - planner.discard_current_block(); + // The timer interval is just the nominal value for the nominal speed + interval = ticks_nominal; + } } } @@ -1697,25 +1643,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(); } @@ -1728,17 +1731,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; - - // 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); + #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 - // 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 @@ -1748,24 +1749,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); } } @@ -1775,65 +1764,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 + 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); + #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 - // 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 MINIMUM_STEPPER_PULSE + // 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 < 0 ? ++e_steps : --e_steps; + LA_steps < 0 ? ++LA_steps : --LA_steps; - E_STEP_WRITE(LA_active_extruder, INVERT_E_STEP_PIN); + #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 - // 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 + // 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 - } // e_steps + } // LA_steps return interval; } @@ -2145,6 +2154,12 @@ void Stepper::report_positions() { #if ENABLED(BABYSTEPPING) + #if MINIMUM_STEPPER_PULSE + #define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE) * CYCLES_PER_MICROSECOND) + #else + #define STEP_PULSE_CYCLES 0 + #endif + #if ENABLED(DELTA) #define CYCLES_EATEN_BABYSTEP (2 * 15) #else @@ -2158,8 +2173,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/src/module/stepper.h b/Marlin/src/module/stepper.h index 951847d54f0d3f95e1bc8ee0552b3d74922c1ac8..427b97f80a53fca3e639eeac6f5bce6159953a36 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -76,10 +76,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 @@ -90,9 +94,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 @@ -107,33 +136,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 @@ -145,16 +160,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: // @@ -201,7 +206,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); @@ -279,34 +292,42 @@ class Stepper { // Set direction bits for all steppers static void set_directions(); - // Limit the speed to 10KHz for AVR - #ifndef STEP_DOUBLER_FREQUENCY - #define STEP_DOUBLER_FREQUENCY 10000 - #endif - - 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; + uint8_t multistep = 1; #if DISABLED(DISABLE_MULTI_STEPPING) - if (step_rate > STEP_DOUBLER_FREQUENCY * 2) { // If steprate > (STEP_DOUBLER_FREQUENCY * 2) kHz >> step 4 times - step_rate >>= 2; - step_loops = 4; - } - else if (step_rate > STEP_DOUBLER_FREQUENCY) { // If steprate > STEP_DOUBLER_FREQUENCY kHz >> step 2 times + + // 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; - step_loops = 2; - } - else + multistep <<= 1; + ++idx; + }; + #else + NOMORE(step_rate, uint32_t(MAX_1X_STEP_ISR_FREQUENCY)); #endif - step_loops = 1; + *loops = multistep; #ifdef CPU_32_BIT // In case of high-performance processor, it is able to calculate in real-time - const uint32_t min_time_per_step = (HAL_STEPPER_TIMER_RATE) / ((STEP_DOUBLER_FREQUENCY) * 2); timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate; - NOLESS(timer, min_time_per_step); // (STEP_DOUBLER_FREQUENCY * 2 kHz - this should never happen) #else constexpr uint32_t min_step_rate = F_CPU / 500000U; NOLESS(step_rate, min_step_rate); @@ -324,10 +345,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) #endif return timer; diff --git a/docs/Bresenham.md b/docs/Bresenham.md new file mode 100644 index 0000000000000000000000000000000000000000..59a215096490af0fd8fc4c6ab2c4b2c41f9f1bde --- /dev/null +++ b/docs/Bresenham.md @@ -0,0 +1,269 @@ +On the Bresenham algorithm as implemented by Marlin: +(Taken from (https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html) + +The basic Bresenham algorithm: + +Consider drawing a line on a raster grid where we restrict the allowable slopes of the line to the range 0 <= m <= 1 + +If we further restrict the line-drawing routine so that it always increments x as it plots, it becomes clear that, having plotted a point at (x,y), the routine has a severely limited range of options as to where it may put the next point on the line: + +- It may plot the point (x+1,y), or: +- It may plot the point (x+1,y+1). + +So, working in the first positive octant of the plane, line drawing becomes a matter of deciding between two possibilities at each step. + +We can draw a diagram of the situation which the plotting program finds itself in having plotted (x,y). + +``` + y+1 +--------------* + | / + | / + | / + | / + | y+e+m*--------+- + | /| ^ | + | / | |m | + | / | | | + | / | v | + | y+e*----|----- |m+ε + | /| | ^ | + | / | | |ε | + | / | | | | + |/ | | v v + y *----+----+----------+-- + x x+1 +``` + +In plotting (x,y) the line drawing routine will, in general, be making a compromise between what it would like to draw and what the resolution of the stepper motors actually allows it to draw. Usually the plotted point (x,y) will be in error, the actual, mathematical point on the line will not be addressable on the pixel grid. So we associate an error, ε, with each y ordinate, the real value of y should be y+ε . This error will range from -0.5 to just under +0.5. + +In moving from x to x+1 we increase the value of the true (mathematical) y-ordinate by an amount equal to the slope of the line, m. We will choose to plot (x+1,y) if the difference between this new value and y is less than 0.5 + +``` +y + ε + m < y + 0.5 +``` + +Otherwise we will plot (x+1,y+1). It should be clear that by so doing we minimize the total error between the mathematical line segment and what actually gets drawn on the display. + +The error resulting from this new point can now be written back into ε, this will allow us to repeat the whole process for the next point along the line, at x+2. + +The new value of error can adopt one of two possible values, depending on what new point is plotted. If (x+1,y) is chosen, the new value of error is given by: + +``` +ε[new] = (y + ε + m) - y +``` + +Otherwise, it is: + +``` +ε[new] = (y + ε + m) - (y + 1) +``` + +This gives an algorithm for a DDA which avoids rounding operations, instead using the error variable ε to control plotting: + +``` + ε = 0, y = y[1] + for x = x1 to x2 do + Plot point at (x,y) + if (ε + m < 0.5) + ε = ε + m + else + y = y + 1, ε = ε + m - 1 + endif + endfor +``` + +This still employs floating point values. Consider, however, what happens if we multiply across both sides of the plotting test by Δx and then by 2: + +``` + ε + m < 0.5 + ε + Δy/Δx < 0.5 +2.ε.Δx + 2.Δy < Δx +``` + +All quantities in this inequality are now integral. + +Substitute ε' for ε.Δx . The test becomes: + +``` +2.(ε' + Δy) < Δx +``` + +This gives an integer-only test for deciding which point to plot. + +The update rules for the error on each step may also be cast into ε' form. Consider the floating-point versions of the update rules: + +``` +ε = ε + m +ε = ε + m - 1 +``` + + Multiplying through by Δx yields: + +``` +ε.Δx = ε.Δx + Δy +ε.Δx = ε.Δx + Δy - Δx +``` + +Which is in ε' form: + +``` +ε' = ε' + Δy +ε' = ε' + Δy - Δx +``` + +Using this new ``error'' value, ε' with the new test and update equations gives Bresenham's integer-only line drawing algorithm: + +``` +ε' = 0, y = y[1] +for x = x1 to x2 do + Plot point at (x,y) + if (2.(ε' + Δy) < Δx) + ε' = ε' + Δy + else + y = y + 1, ε' = ε' + Δy - Δx + endif +endfor +``` + +It is a Integer only algorithm - hence efficient (fast). And the Multiplication by 2 can be implemented by left-shift. 0 <= m <= 1 + +### Oversampling Bresenham algorithm: + +Even if Bresenham does NOT lose steps at all, and also does NOT accumulate error, there is a concept i would call "time resolution" - If the quotient between major axis and minor axis (major axis means, in this context, the axis that must create more step pulses compared with the other ones, including the extruder) + +Well, if the quotient result is not an integer, then Bresenham, at some points in the movement of the major axis, must decide that it has to move the minor axis. It is done in such way that after the full major axis movement has executed, it also has executed the full movements of the minor axis. And the minor axis steps were properly distributed evenly along the major axis movement. So good so far. + +But, as said, Bresenham has "discrete" decision points: It can only decide to move (or not to move) minor axis exactly at the moment the major axis moves. And that is not the ideal point (in time) usually. + +With slow movements that are composed of a similar, but not equal number of steps in all axes, the problem worsens, as the decision points are distributed very sparsely, and there are large delays between those decision points. + +It is nearly trivial to extend Bresenham to "oversample" in that situation: Let's do it: + +Assume that we want to use Bresenham to calculate when to step (move in Y direction), but we want to do it, not for integer increments of the X axis, rather than, for fractional increments. + +Let's call 'r' the count of subdivisions we want to split an integer increment of the X axis: + +``` +m = Δy/Δx = increment of y due to the increment of x1 +``` + +Every time we move `1/r` in the X axis, then the Y axis should move `m.1/r` + +But, as stated previously, due to the resolution of the screen, there are 2 choices: + +- It may plot the point `(x+(1/r),y)`, or: +- It may plot the point `(x+(1/r),y+1)`. + +That decision must be made keeping the error as small as possible: + +``` +-0.5 < ε < 0.5 +``` + +So, the proper condition for that decision is (`m/r` is the increment of y due to the fractional `1/r` increment of `x`): + +``` +y + ε + m/r < y + 0.5 +ε + m/r < 0.5 [1] +``` + +Once we did the decision, then the error update conditions are: + +Decision A: +``` +ε[new] = y + ε + m/r - y +ε[new] = ε + m/r [2] +``` + +Decision B: +``` +ε[new] = y + ε + m/r - (y+1) +ε[new] = ε + m/r - 1 [3] +``` + +We replace m in the decision inequality [1] by its definition: + +``` +ε + m/r < 0.5 +ε + ΔY/(ΔX*r) < 0.5 +``` + +Then, we multiply it by `2.Δx.r`: + +``` +ε + ΔY/(ΔX*r) < 0.5 +2.ΔX.ε.r + 2.ΔY < ΔX.r +``` + +If we define `ε' = 2.ε.ΔX.r` then it becomes: + +``` +ε' + 2.ΔY < ΔX.r [4] +``` + +Now, for the update rules, we multiply by 2.r.ΔX + +``` +ε[new] = ε + m/r +2.r.ΔX.ε[new] = 2.r.ΔX.ε + 2.r.ΔX.ΔY/ΔX/r +2.r.ΔX.ε[new] = 2.r.ΔX.ε + 2.ΔY +ε'[new] = ε' + 2.ΔY [6] +``` + +``` +ε[new] = ε + m/r - 1 +2.r.ΔX.ε[new] = 2.r.ΔX.ε + 2.r.ΔX.ΔY/ΔX/r - 1 . 2.r.ΔX +2.r.ΔX.ε[new] = 2.r.ΔX.ε + 2.ΔY - 2.ΔX.r +ε'[new] = ε' + 2.ΔY - 2.ΔX.r [7] +``` + +All expressions, the decision inequality [4], and the update equations [5] and [6] are integer valued. There is no need for floating point arithmetic at all. + +Summarizing: + +``` +Condition equation: + + ε' + 2.ΔY < ΔX.r [4] + +Error update equations: + + ε'[new] = ε' + 2.ΔY [6] + + ε'[new] = ε' + 2.ΔY - 2.ΔX.r [7] +``` + +This can be implemented in C as: + +```cpp + class OversampledBresenham { + private: + long divisor, // stepsX + dividend, // stepsY + advanceDivisor, // advanceX + advanceDividend; // advanceY + int errorAccumulator; // Error accumulator + + public: + unsigned int ticker; + + OversampledBresenhan(const long& inDividend, const long& inDivisor, int rate) { + ticker = 0; + divisor = inDivisor; + dividend = inDividend; + advanceDivisor = divisor * 2 * rate; + advanceDividend = dividend * 2; + errorAccumulator = -divisor * rate; + } + + bool tick() { + errorAccumulator += advanceDividend; + const bool over = errorAccumulator >= 0; + if (over) { + ticker++; + errorAccumulator -= advanceDivisor; + } + return over; + } + }; +```