diff --git a/stepper.c b/stepper.c index 8acc1f8..214c8fc 100644 --- a/stepper.c +++ b/stepper.c @@ -95,6 +95,11 @@ static float cycles_per_min; static volatile segment_t *segment_buffer_tail; static segment_t *segment_buffer_head, *segment_next_head; +#if ENABLE_JERK_ACCELERATION +// Static storage for acceleration value of last computed segment. +static float last_segment_accel = 0.0f; +#endif + // Pointers for the step segment being prepped from the planner buffer. Accessed only by the // main program. Pointers may be planning segments or planner blocks ahead of what being executed. static plan_block_t *pl_block; // Pointer to the planner block being prepped @@ -866,13 +871,14 @@ void st_prep_buffer (void) float dt_max = DT_SEGMENT; // Maximum segment time float dt = 0.0f; // Initialize segment time float time_var = dt_max; // Time worker variable -#if ENABLE_JERK_ACCELERATION - float last_segment_accel = 0.0f; // Acceleration value of last computed segment. Initialize as 0.0 -#endif float mm_var; // mm - Distance worker variable float speed_var; // Speed worker variable float mm_remaining = pl_block->millimeters; // New segment distance from end of block. float minimum_mm = mm_remaining - prep.req_mm_increment; // Guarantee at least one step. +#if ENABLE_ACCELERATION_PROFILES + float time_to_jerk; // time needed for jerk ramp + float mm_to_rampend; // mm needed to complete one jerk ramp mm == V(0)*T + 1/2 A0*T^2 + 1/6 J*T^3 +#endif if (minimum_mm < 0.0f) minimum_mm = 0.0f; @@ -897,15 +903,17 @@ void st_prep_buffer (void) case Ramp_Accel: // NOTE: Acceleration ramp only computes during first do-while loop. -#if ENABLE_JERK_ACCELERATION - if (((mm_remaining - prep.accelerate_until) / (prep.current_speed + 0.001f)) <= (last_segment_accel / pl_block->jerk)) { - //+0.001f to avoid divide by 0 speed, minor effect on jerk ramp (+1.0f was too large for low jerk values) +#if ENABLE_JERK_ACCELERATION + time_to_jerk = last_segment_accel / pl_block->jerk; + mm_to_rampend = (prep.current_speed * time_to_jerk) + (0.5f * last_segment_accel * time_to_jerk * time_to_jerk) + (pl_block->jerk * time_to_jerk * time_to_jerk * time_to_jerk) / 6.0f; + if ((mm_remaining - prep.accelerate_until) > mm_to_rampend) { + //+1.0f to avoid divide by 0 speed, minor effect on jerk ramp // Check if we are on ramp up or ramp down. Ramp down if time to end of acceleration is less than time needed to reach 0 acceleration. // Then limit acceleration change by jerk up to max acceleration and update for next segment. - // Minimum acceleration jerk per time_var to ensure acceleartion completes. Acceleration change at end of ramp is in acceptable jerk range. - last_segment_accel = max(last_segment_accel - pl_block->jerk * time_var, pl_block->jerk * time_var); - } else { + // Minimum acceleration jerk per time_var to ensure acceleration completes. Acceleration change at end of ramp is in acceptable jerk range. last_segment_accel = min(last_segment_accel + pl_block->jerk * time_var, pl_block->max_acceleration); + } else { + last_segment_accel = max(last_segment_accel - pl_block->jerk * time_var, pl_block->jerk * time_var); } speed_var = last_segment_accel * time_var; #else @@ -942,14 +950,15 @@ void st_prep_buffer (void) default: // case Ramp_Decel: // NOTE: mm_var used as a misc worker variable to prevent errors when near zero speed. #if ENABLE_JERK_ACCELERATION - if ((mm_remaining / (prep.current_speed + 0.001f)) <= (last_segment_accel / pl_block->jerk)) { - //+0.001f to avoid divide by 0 speed, minor effect on jerk ramp (+1.0f was too large for low jerk values) - // Check if we are on ramp up or ramp down. Ramp down if time to end of deceleration is less than time needed to reach 0 acceleration. + time_to_jerk = last_segment_accel / pl_block->jerk; + mm_to_rampend = (prep.current_speed * time_to_jerk) + (0.5f * last_segment_accel * time_to_jerk * time_to_jerk) + (pl_block->jerk * time_to_jerk * time_to_jerk * time_to_jerk) / 6.0f; + if (mm_remaining > mm_to_rampend) { + // Check if we are on ramp up or ramp down. Ramp down if travel distance to end of deceleration is less than distance needed to reach 0 acceleration. // Then limit acceleration change by jerk up to max acceleration and update for next segment. // Minimum acceleration of jerk per time_var to ensure acceleration completes. Acceleration change at end of ramp is in acceptable jerk range. - last_segment_accel = max(last_segment_accel - pl_block->jerk * time_var, pl_block->jerk * time_var); - } else { last_segment_accel = min(last_segment_accel + pl_block->jerk * time_var, pl_block->max_acceleration); + } else { + last_segment_accel = max(last_segment_accel - pl_block->jerk * time_var, pl_block->jerk * time_var); } speed_var = last_segment_accel * time_var; // Used as delta speed (mm/min) #else @@ -968,6 +977,9 @@ void st_prep_buffer (void) time_var = 2.0f * (mm_remaining - prep.mm_complete) / (prep.current_speed + prep.exit_speed); mm_remaining = prep.mm_complete; prep.current_speed = prep.exit_speed; +#if ENABLE_JERK_ACCELERATION + last_segment_accel = 0.0f; // reset acceleration variable to 0 for next accel ramp +#endif } dt += time_var; // Add computed ramp time to total segment time.