58
58
*
59
59
* time ----->
60
60
*
61
- * The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
62
- * first block->accelerate_until step_events_completed, then keeps going at constant speed until
63
- * step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
64
- * The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far.
61
+ * The speed over time graph forms a TRAPEZOID. The slope of acceleration is calculated by
62
+ * v = u + t
63
+ * where 't' is the accumulated timer values of the steps so far.
64
+ *
65
+ * The Stepper ISR dynamically executes acceleration, deceleration, and cruising according to the block parameters.
66
+ * - Start at block->initial_rate.
67
+ * - Accelerate while step_events_completed < block->accelerate_before.
68
+ * - Cruise while step_events_completed < block->decelerate_start.
69
+ * - Decelerate after that, until all steps are completed.
70
+ * - Reset the trapezoid generator.
65
71
*/
66
72
67
73
/* *
@@ -193,6 +199,7 @@ bool Stepper::abort_current_block;
193
199
;
194
200
#endif
195
201
202
+ // In timer_ticks
196
203
uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
197
204
198
205
#if MULTISTEPPING_LIMIT > 1
@@ -224,8 +231,8 @@ xyze_long_t Stepper::delta_error{0};
224
231
xyze_long_t Stepper::advance_dividend{0 };
225
232
uint32_t Stepper::advance_divisor = 0 ,
226
233
Stepper::step_events_completed = 0 , // The number of step events executed in the current block
227
- Stepper::accelerate_until , // The count at which to stop accelerating
228
- Stepper::decelerate_after , // The count at which to start decelerating
234
+ Stepper::accelerate_before , // The count at which to start cruising
235
+ Stepper::decelerate_start , // The count at which to start decelerating
229
236
Stepper::step_event_count; // The total event count for the current block
230
237
231
238
#if ANY(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER)
@@ -2403,7 +2410,7 @@ hal_timer_t Stepper::block_phase_isr() {
2403
2410
// Step events not completed yet...
2404
2411
2405
2412
// Are we in acceleration phase ?
2406
- if (step_events_completed <= accelerate_until ) { // Calculate new timer value
2413
+ if (step_events_completed < accelerate_before ) { // Calculate new timer value
2407
2414
2408
2415
#if ENABLED(S_CURVE_ACCELERATION)
2409
2416
// Get the next speed to use (Jerk limited!)
@@ -2420,6 +2427,7 @@ hal_timer_t Stepper::block_phase_isr() {
2420
2427
// step_rate to timer interval and steps per stepper isr
2421
2428
interval = calc_multistep_timer_interval (acc_step_rate << oversampling_factor);
2422
2429
acceleration_time += interval;
2430
+ deceleration_time = 0 ; // Reset since we're doing acceleration first.
2423
2431
2424
2432
#if ENABLED(NONLINEAR_EXTRUSION)
2425
2433
calc_nonlinear_e (acc_step_rate << oversampling_factor);
@@ -2456,30 +2464,24 @@ hal_timer_t Stepper::block_phase_isr() {
2456
2464
#endif
2457
2465
}
2458
2466
// Are we in Deceleration phase ?
2459
- else if (step_events_completed > decelerate_after ) {
2467
+ else if (step_events_completed >= decelerate_start ) {
2460
2468
uint32_t step_rate;
2461
2469
2462
2470
#if ENABLED(S_CURVE_ACCELERATION)
2463
-
2464
2471
// If this is the 1st time we process the 2nd half of the trapezoid...
2465
2472
if (!bezier_2nd_half) {
2466
2473
// Initialize the Bézier speed curve
2467
2474
_calc_bezier_curve_coeffs (current_block->cruise_rate , current_block->final_rate , current_block->deceleration_time_inverse );
2468
2475
bezier_2nd_half = true ;
2469
- // The first point starts at cruise rate. Just save evaluation of the Bézier curve
2470
- step_rate = current_block->cruise_rate ;
2471
- }
2472
- else {
2473
- // Calculate the next speed to use
2474
- step_rate = deceleration_time < current_block->deceleration_time
2475
- ? _eval_bezier_curve (deceleration_time)
2476
- : current_block->final_rate ;
2477
2476
}
2478
-
2477
+ // Calculate the next speed to use
2478
+ step_rate = deceleration_time < current_block->deceleration_time
2479
+ ? _eval_bezier_curve (deceleration_time)
2480
+ : current_block->final_rate ;
2479
2481
#else
2480
2482
// Using the old trapezoidal control
2481
2483
step_rate = STEP_MULTIPLY (deceleration_time, current_block->acceleration_rate );
2482
- if (step_rate < acc_step_rate) { // Still decelerating?
2484
+ if (step_rate < acc_step_rate) {
2483
2485
step_rate = acc_step_rate - step_rate;
2484
2486
NOLESS (step_rate, current_block->final_rate );
2485
2487
}
@@ -2542,6 +2544,9 @@ hal_timer_t Stepper::block_phase_isr() {
2542
2544
if (ticks_nominal == 0 ) {
2543
2545
// step_rate to timer interval and loops for the nominal speed
2544
2546
ticks_nominal = calc_multistep_timer_interval (current_block->nominal_rate << oversampling_factor);
2547
+ // Prepare for deceleration
2548
+ IF_DISABLED (S_CURVE_ACCELERATION, acc_step_rate = current_block->nominal_rate );
2549
+ deceleration_time = ticks_nominal / 2 ;
2545
2550
2546
2551
#if ENABLED(NONLINEAR_EXTRUSION)
2547
2552
calc_nonlinear_e (current_block->nominal_rate << oversampling_factor);
@@ -2664,9 +2669,6 @@ hal_timer_t Stepper::block_phase_isr() {
2664
2669
// Set flags for all moving axes, accounting for kinematics
2665
2670
set_axis_moved_for_current_block ();
2666
2671
2667
- // No acceleration / deceleration time elapsed so far
2668
- acceleration_time = deceleration_time = 0 ;
2669
-
2670
2672
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
2671
2673
// Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate
2672
2674
// Otherwise assume no axis smoothing (via oversampling)
@@ -2720,8 +2722,8 @@ hal_timer_t Stepper::block_phase_isr() {
2720
2722
step_events_completed = 0 ;
2721
2723
2722
2724
// Compute the acceleration and deceleration points
2723
- accelerate_until = current_block->accelerate_until << oversampling_factor;
2724
- decelerate_after = current_block->decelerate_after << oversampling_factor;
2725
+ accelerate_before = current_block->accelerate_before << oversampling_factor;
2726
+ decelerate_start = current_block->decelerate_start << oversampling_factor;
2725
2727
2726
2728
TERN_ (MIXING_EXTRUDER, mixer.stepper_setup (current_block->b_color ));
2727
2729
@@ -2807,7 +2809,8 @@ hal_timer_t Stepper::block_phase_isr() {
2807
2809
2808
2810
// Calculate the initial timer interval
2809
2811
interval = calc_multistep_timer_interval (current_block->initial_rate << oversampling_factor);
2810
- acceleration_time += interval;
2812
+ // Initialize ac/deceleration time as if half the time passed.
2813
+ acceleration_time = deceleration_time = interval / 2 ;
2811
2814
2812
2815
#if ENABLED(NONLINEAR_EXTRUSION)
2813
2816
calc_nonlinear_e (current_block->initial_rate << oversampling_factor);
0 commit comments