Deceleration to zero speed improvements. Update defaults.
- A minor issue with deceleration ramps when close to zero velocity. Should be virtually unnoticeable for most CNC systems, but fixed in this push and accurate to physics. - Updated some of the junction deviation defaults. Because the new stepper algorithm can easily maximize a CNC machine’s capabilities or simply go much faster, this means the speed in which it enters junctions has to be a little more constrained. Meaning that, we have to slow a little bit down more so that we don’t exceed the acceleration limits of the stepper motors.
This commit is contained in:
parent
a87f25773c
commit
b562845d9d
14
defaults.h
14
defaults.h
@ -45,7 +45,7 @@
|
|||||||
#define DEFAULT_FEEDRATE 250.0 // mm/min
|
#define DEFAULT_FEEDRATE 250.0 // mm/min
|
||||||
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
|
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
|
||||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||||
#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm
|
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||||
#define DEFAULT_ARC_TOLERANCE 0.005 // mm
|
#define DEFAULT_ARC_TOLERANCE 0.005 // mm
|
||||||
#define DEFAULT_DECIMAL_PLACES 3
|
#define DEFAULT_DECIMAL_PLACES 3
|
||||||
#define DEFAULT_REPORT_INCHES 0 // false
|
#define DEFAULT_REPORT_INCHES 0 // false
|
||||||
@ -83,7 +83,7 @@
|
|||||||
#define DEFAULT_FEEDRATE 254.0 // mm/min (10 ipm)
|
#define DEFAULT_FEEDRATE 254.0 // mm/min (10 ipm)
|
||||||
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
|
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
|
||||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||||
#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm
|
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||||
#define DEFAULT_ARC_TOLERANCE 0.005 // mm
|
#define DEFAULT_ARC_TOLERANCE 0.005 // mm
|
||||||
#define DEFAULT_DECIMAL_PLACES 3
|
#define DEFAULT_DECIMAL_PLACES 3
|
||||||
#define DEFAULT_REPORT_INCHES 1 // true
|
#define DEFAULT_REPORT_INCHES 1 // true
|
||||||
@ -153,17 +153,17 @@
|
|||||||
#define DEFAULT_X_MAX_RATE 7000.0 // mm/min
|
#define DEFAULT_X_MAX_RATE 7000.0 // mm/min
|
||||||
#define DEFAULT_Y_MAX_RATE 7000.0 // mm/min
|
#define DEFAULT_Y_MAX_RATE 7000.0 // mm/min
|
||||||
#define DEFAULT_Z_MAX_RATE 7000.0 // mm/min
|
#define DEFAULT_Z_MAX_RATE 7000.0 // mm/min
|
||||||
#define DEFAULT_X_ACCELERATION (500.0*60*60) // 10 mm/min^2
|
#define DEFAULT_X_ACCELERATION (600.0*60*60) // 10 mm/min^2
|
||||||
#define DEFAULT_Y_ACCELERATION (500.0*60*60) // 10 mm/min^2
|
#define DEFAULT_Y_ACCELERATION (600.0*60*60) // 10 mm/min^2
|
||||||
#define DEFAULT_Z_ACCELERATION (500.0*60*60) // 10 mm/min^2
|
#define DEFAULT_Z_ACCELERATION (600.0*60*60) // 10 mm/min^2
|
||||||
#define DEFAULT_X_MAX_TRAVEL 200.0 // mm
|
#define DEFAULT_X_MAX_TRAVEL 200.0 // mm
|
||||||
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm
|
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm
|
||||||
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm
|
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm
|
||||||
#define DEFAULT_STEP_PULSE_MICROSECONDS 10
|
#define DEFAULT_STEP_PULSE_MICROSECONDS 10
|
||||||
#define DEFAULT_FEEDRATE 1000.0 // mm/min
|
#define DEFAULT_FEEDRATE 1000.0 // mm/min
|
||||||
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
|
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT))
|
||||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||||
#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm
|
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||||
#define DEFAULT_ARC_TOLERANCE 0.005 // mm
|
#define DEFAULT_ARC_TOLERANCE 0.005 // mm
|
||||||
#define DEFAULT_DECIMAL_PLACES 3
|
#define DEFAULT_DECIMAL_PLACES 3
|
||||||
#define DEFAULT_REPORT_INCHES 0 // false
|
#define DEFAULT_REPORT_INCHES 0 // false
|
||||||
|
61
stepper.c
61
stepper.c
@ -107,7 +107,7 @@ typedef struct {
|
|||||||
float steps_remaining;
|
float steps_remaining;
|
||||||
|
|
||||||
uint8_t ramp_type; // Current segment ramp state
|
uint8_t ramp_type; // Current segment ramp state
|
||||||
float mm_eob;
|
float mm_complete;
|
||||||
float current_speed; // Current speed at the end of the segment buffer (mm/min)
|
float current_speed; // Current speed at the end of the segment buffer (mm/min)
|
||||||
float maximum_speed; // Maximum speed of executing block. Not always nominal speed. (mm/min)
|
float maximum_speed; // Maximum speed of executing block. Not always nominal speed. (mm/min)
|
||||||
float exit_speed; // Exit speed of executing block (mm/min)
|
float exit_speed; // Exit speed of executing block (mm/min)
|
||||||
@ -491,8 +491,13 @@ void st_prep_buffer()
|
|||||||
else { prep.current_speed = sqrt(pl_block->entry_speed_sqr); }
|
else { prep.current_speed = sqrt(pl_block->entry_speed_sqr); }
|
||||||
}
|
}
|
||||||
|
|
||||||
prep.mm_eob = 0.0;
|
/* ---------------------------------------------------------------------------------
|
||||||
|
Compute the velocity profile of a new planner block based on its entry and exit
|
||||||
|
speeds, or recompute the profile of a partially-completed planner block if the
|
||||||
|
planner has updated it. For a commanded forced-deceleration, such as from a feed
|
||||||
|
hold, override the planner velocities and decelerate to the target exit speed.
|
||||||
|
*/
|
||||||
|
prep.mm_complete = 0.0;
|
||||||
float inv_2_accel = 0.5/pl_block->acceleration;
|
float inv_2_accel = 0.5/pl_block->acceleration;
|
||||||
if (sys.state == STATE_HOLD) {
|
if (sys.state == STATE_HOLD) {
|
||||||
// Compute velocity profile parameters for a feed hold in-progress. This profile overrides
|
// Compute velocity profile parameters for a feed hold in-progress. This profile overrides
|
||||||
@ -501,12 +506,12 @@ void st_prep_buffer()
|
|||||||
float decel_dist = inv_2_accel*pl_block->entry_speed_sqr;
|
float decel_dist = inv_2_accel*pl_block->entry_speed_sqr;
|
||||||
if (decel_dist < pl_block->millimeters) {
|
if (decel_dist < pl_block->millimeters) {
|
||||||
prep.exit_speed = 0.0;
|
prep.exit_speed = 0.0;
|
||||||
prep.mm_eob = pl_block->millimeters-decel_dist;
|
prep.mm_complete = pl_block->millimeters-decel_dist;
|
||||||
} else {
|
} else {
|
||||||
prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters);
|
prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Compute velocity profile parameters of the prepped planner block.
|
// Compute or recompute velocity profile parameters of the prepped planner block.
|
||||||
prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp.
|
prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp.
|
||||||
prep.accelerate_until = pl_block->millimeters;
|
prep.accelerate_until = pl_block->millimeters;
|
||||||
prep.exit_speed = plan_get_exec_block_exit_speed();
|
prep.exit_speed = plan_get_exec_block_exit_speed();
|
||||||
@ -550,24 +555,31 @@ void st_prep_buffer()
|
|||||||
// Set new segment to point to the current segment data block.
|
// Set new segment to point to the current segment data block.
|
||||||
prep_segment->st_block_index = prep.st_block_index;
|
prep_segment->st_block_index = prep.st_block_index;
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------------
|
||||||
Compute the average velocity of this new segment by determining the total distance
|
Compute the average velocity of this new segment by determining the total distance
|
||||||
traveled over the segment time DT_SEGMENT. The following code first attempts to create
|
traveled over the segment time DT_SEGMENT. The following code first attempts to create
|
||||||
a full segment based on the current ramp conditions. If the segment time is incomplete
|
a full segment based on the current ramp conditions. If the segment time is incomplete
|
||||||
when terminating at a ramp state change, the code will continue to loop through the
|
when terminating at a ramp state change, the code will continue to loop through the
|
||||||
progressing ramp states to fill the remaining segment execution time. However, if
|
progressing ramp states to fill the remaining segment execution time. However, if
|
||||||
an incomplete segment terminates at the end of the planner block, the segment is
|
an incomplete segment terminates at the end of the velocity profile, the segment is
|
||||||
considered completed despite having a truncated execution time less than DT_SEGMENT.
|
considered completed despite having a truncated execution time less than DT_SEGMENT.
|
||||||
|
The velocity profile is always assumed to progress through the ramp sequence:
|
||||||
|
acceleration ramp, cruising state, and deceleration ramp. Each ramp's travel distance
|
||||||
|
may range from zero to the length of the block. Velocity profiles can end either at
|
||||||
|
the end of planner block (typical) or mid-block at the end of a forced deceleration,
|
||||||
|
such as from a feed hold.
|
||||||
*/
|
*/
|
||||||
float dt = 0.0;
|
float dt = 0.0;
|
||||||
float mm_remaining = pl_block->millimeters;
|
float mm_remaining = pl_block->millimeters;
|
||||||
float time_var = DT_SEGMENT; // Time worker variable
|
float time_var = DT_SEGMENT; // Time worker variable
|
||||||
float mm_var; // mm distance worker variable
|
float mm_var; // mm-Distance worker variable
|
||||||
|
float speed_var; // Speed work variable.
|
||||||
do {
|
do {
|
||||||
switch (prep.ramp_type) {
|
switch (prep.ramp_type) {
|
||||||
case RAMP_ACCEL:
|
case RAMP_ACCEL:
|
||||||
// NOTE: Acceleration ramp only computes during first do-while loop.
|
// NOTE: Acceleration ramp only computes during first do-while loop.
|
||||||
mm_remaining -= DT_SEGMENT*(prep.current_speed + pl_block->acceleration*(0.5*DT_SEGMENT));
|
speed_var = pl_block->acceleration*DT_SEGMENT;
|
||||||
|
mm_remaining -= DT_SEGMENT*(prep.current_speed + 0.5*speed_var);
|
||||||
if (mm_remaining < prep.accelerate_until) { // End of acceleration ramp.
|
if (mm_remaining < prep.accelerate_until) { // End of acceleration ramp.
|
||||||
// Acceleration-cruise, acceleration-deceleration ramp junction, or end of block.
|
// Acceleration-cruise, acceleration-deceleration ramp junction, or end of block.
|
||||||
mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB
|
mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB
|
||||||
@ -576,7 +588,7 @@ void st_prep_buffer()
|
|||||||
else { prep.ramp_type = RAMP_CRUISE; }
|
else { prep.ramp_type = RAMP_CRUISE; }
|
||||||
prep.current_speed = prep.maximum_speed;
|
prep.current_speed = prep.maximum_speed;
|
||||||
} else { // Acceleration only.
|
} else { // Acceleration only.
|
||||||
prep.current_speed += pl_block->acceleration*time_var;
|
prep.current_speed += speed_var;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RAMP_CRUISE:
|
case RAMP_CRUISE:
|
||||||
@ -592,23 +604,24 @@ void st_prep_buffer()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // case RAMP_DECEL:
|
default: // case RAMP_DECEL:
|
||||||
// NOTE: mm_var used to catch negative decelerate distance values near zero speed.
|
// NOTE: mm_var used as a misc worker variable to prevent errors when near zero speed.
|
||||||
mm_var = time_var*(prep.current_speed - 0.5*pl_block->acceleration*time_var);
|
speed_var = pl_block->acceleration*time_var; // Used as delta speed (mm/min)
|
||||||
if ((mm_var > prep.mm_eob) && (mm_var < mm_remaining)) { // Deceleration only.
|
if (prep.current_speed > speed_var) { // Check if at or below zero speed.
|
||||||
prep.current_speed -= pl_block->acceleration*time_var;
|
// Compute distance from end of segment to end of block.
|
||||||
// Check for near-zero speed and prevent divide by zero in rare scenarios.
|
mm_var = mm_remaining - time_var*(prep.current_speed - 0.5*speed_var); // (mm)
|
||||||
if (prep.current_speed > prep.exit_speed) { mm_remaining -= mm_var; }
|
if (mm_var > prep.mm_complete) { // Deceleration only.
|
||||||
else { mm_remaining = prep.mm_eob; } // NOTE: Force EOB for now. May or may not be needed.
|
mm_remaining = mm_var;
|
||||||
} else { // End of block.
|
prep.current_speed -= speed_var;
|
||||||
time_var = 2.0*(mm_remaining-prep.mm_eob)/(prep.current_speed+prep.exit_speed);
|
break; // Segment complete. Exit switch-case statement.
|
||||||
mm_remaining = prep.mm_eob;
|
|
||||||
// prep.current_speed = prep.exit_speed; // !! May be needed for feed hold reinitialization.
|
|
||||||
}
|
}
|
||||||
|
} // End of block or end of forced-deceleration.
|
||||||
|
time_var = 2.0*(mm_remaining-prep.mm_complete)/(prep.current_speed+prep.exit_speed);
|
||||||
|
mm_remaining = prep.mm_complete;
|
||||||
}
|
}
|
||||||
dt += time_var; // Add computed ramp time to total segment time.
|
dt += time_var; // Add computed ramp time to total segment time.
|
||||||
if (dt < DT_SEGMENT) { time_var = DT_SEGMENT - dt; } // **Incomplete** At ramp junction.
|
if (dt < DT_SEGMENT) { time_var = DT_SEGMENT - dt; } // **Incomplete** At ramp junction.
|
||||||
else { break; } // **Complete** Exit loop. Segment execution time maxed.
|
else { break; } // **Complete** Exit loop. Segment execution time maxed.
|
||||||
} while (mm_remaining > prep.mm_eob); // **Complete** Exit loop. End of planner block.
|
} while (mm_remaining > prep.mm_complete); // **Complete** Exit loop. Profile complete.
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------------
|
||||||
Compute segment step rate, steps to execute, and step phase correction parameters.
|
Compute segment step rate, steps to execute, and step phase correction parameters.
|
||||||
@ -622,7 +635,7 @@ void st_prep_buffer()
|
|||||||
*/
|
*/
|
||||||
// Use time_var to pre-compute dt inversion with integer multiplier.
|
// Use time_var to pre-compute dt inversion with integer multiplier.
|
||||||
time_var = (INV_TIME_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))/dt; // (mult/isr_tic)
|
time_var = (INV_TIME_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))/dt; // (mult/isr_tic)
|
||||||
if (mm_remaining > 0.0) {
|
if (mm_remaining > 0.0) { // Block still incomplete. Distance remaining to be executed.
|
||||||
float steps_remaining = prep.step_per_mm*mm_remaining;
|
float steps_remaining = prep.step_per_mm*mm_remaining;
|
||||||
prep_segment->dist_per_tick = ceil( (prep.steps_remaining-steps_remaining)*time_var ); // (mult*step/isr_tic)
|
prep_segment->dist_per_tick = ceil( (prep.steps_remaining-steps_remaining)*time_var ); // (mult*step/isr_tic)
|
||||||
|
|
||||||
@ -631,7 +644,7 @@ void st_prep_buffer()
|
|||||||
prep_segment->n_step = ceil(prep.steps_remaining)-ceil(steps_remaining);
|
prep_segment->n_step = ceil(prep.steps_remaining)-ceil(steps_remaining);
|
||||||
|
|
||||||
// Update step execution variables.
|
// Update step execution variables.
|
||||||
if (mm_remaining == prep.mm_eob) {
|
if (mm_remaining == prep.mm_complete) {
|
||||||
// NOTE: Currently only feed holds qualify for this scenario. May change with overrides.
|
// NOTE: Currently only feed holds qualify for this scenario. May change with overrides.
|
||||||
prep.current_speed = 0.0;
|
prep.current_speed = 0.0;
|
||||||
prep.steps_remaining = ceil(steps_remaining);
|
prep.steps_remaining = ceil(steps_remaining);
|
||||||
|
Loading…
Reference in New Issue
Block a user