moved last_segment_accel to static so values dont get lost between stepper loops, adjusted jerk ramps to grblhal calculations in mm instead of time based calculations. now works with low and very low jerk values.

known issue: decel ramp does not hit 0 speed at end.
This commit is contained in:
Dietz0r
2025-01-05 23:57:55 +01:00
committed by GitHub
parent 990eeff055
commit ca82c9a1e1
+26 -14
View File
@@ -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.