Revamped homing cycle. Axis limits and max travel bug fixes. Build info. Refactored config.h.
- Revamped and improved homing cycle. Now tied directly into the main planner and stepper code, which enables much faster homing seek rates. Also dropped the compiled flash size by almost 1KB, meaning 1KB more for other features. - Refactored config.h. Removed obsolete defines and configuration options. Moved lots of “advanced” options into the advanced area of the file. - Updated defaults.h with the new homing cycle. Also updated the Sherline 5400 defaults and added the ShapeOko2 defaults per user submissions. - Fixed a bug where the individual axes limits on velocity and acceleration were not working correctly. Caused by abs() returning a int, rather than a float. Corrected with fabs(). Duh. - Added build version/date to the Grbl welcome message to help indicate which version a user is operating on. - Max travel settings were not being defaulted into the settings EEPROM correctly. Fixed. - To stop a single axis during a multi-axes homing move, the stepper algorithm now has a simple axis lock mask which inhibits the desired axes from moving. Meaning, if one of the limit switches engages before the other, we stop that one axes and keep moving the other.
This commit is contained in:
48
stepper.c
48
stepper.c
@ -26,11 +26,12 @@
|
||||
#include "planner.h"
|
||||
#include "nuts_bolts.h"
|
||||
|
||||
|
||||
// Some useful constants
|
||||
// Some useful constants.
|
||||
#define TICKS_PER_MICROSECOND (F_CPU/1000000)
|
||||
#define DT_SEGMENT (1.0/(ACCELERATION_TICKS_PER_SECOND*60.0)) // min/segment
|
||||
|
||||
#define STEP_FTOL_MULTIPLIER 100000 // Multiplier converts floating point step rate to long
|
||||
// integer for stepper algorithm step-distance counter.
|
||||
|
||||
#define RAMP_ACCEL 0
|
||||
#define RAMP_CRUISE 1
|
||||
#define RAMP_DECEL 2
|
||||
@ -107,7 +108,7 @@ typedef struct {
|
||||
float steps_remaining;
|
||||
|
||||
uint8_t ramp_type; // Current segment ramp state
|
||||
float mm_complete;
|
||||
float mm_complete; // End of velocity profile from end of current planner block in (mm).
|
||||
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 exit_speed; // Exit speed of executing block (mm/min)
|
||||
@ -165,7 +166,7 @@ void st_wake_up()
|
||||
} else {
|
||||
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT);
|
||||
}
|
||||
if (sys.state == STATE_CYCLE) {
|
||||
if ((sys.state == STATE_CYCLE) || (sys.state == STATE_HOMING)){
|
||||
// Initialize stepper output bits
|
||||
st.out_bits = settings.invert_mask;
|
||||
// Initialize step pulse timing from settings.
|
||||
@ -282,14 +283,14 @@ ISR(TIMER2_COMPA_vect)
|
||||
st.counter_dist += st.exec_segment->dist_per_tick;
|
||||
|
||||
// Execute Bresenham step event, when it's time to do so.
|
||||
if (st.counter_dist > INV_TIME_MULTIPLIER) {
|
||||
if (st.counter_dist > STEP_FTOL_MULTIPLIER) {
|
||||
if (st.step_count > 0) { // Block phase correction from executing step.
|
||||
st.counter_dist -= INV_TIME_MULTIPLIER; // Reload inverse time counter
|
||||
st.counter_dist -= STEP_FTOL_MULTIPLIER; // Reload inverse time counter
|
||||
st.step_count--; // Decrement step events count
|
||||
|
||||
// Execute step displacement profile by Bresenham line algorithm
|
||||
st.execute_step = true;
|
||||
st.out_bits = st.exec_block->direction_bits; // Reset out_bits and reload direction bits
|
||||
st.out_bits = st.exec_block->direction_bits; // Reset out_bits and reload direction bits
|
||||
st.counter_x -= st.exec_block->steps[X_AXIS];
|
||||
if (st.counter_x < 0) {
|
||||
st.out_bits |= (1<<X_STEP_BIT);
|
||||
@ -311,6 +312,10 @@ ISR(TIMER2_COMPA_vect)
|
||||
if (st.out_bits & (1<<Z_DIRECTION_BIT)) { sys.position[Z_AXIS]--; }
|
||||
else { sys.position[Z_AXIS]++; }
|
||||
}
|
||||
|
||||
// Block any axis with limit switch active from moving.
|
||||
if (sys.state == STATE_HOMING) { st.out_bits &= sys.homing_axis_lock; }
|
||||
|
||||
st.out_bits ^= settings.invert_mask; // Apply step port invert mask
|
||||
}
|
||||
}
|
||||
@ -455,8 +460,8 @@ void st_update_plan_block_parameters()
|
||||
*/
|
||||
void st_prep_buffer()
|
||||
{
|
||||
if (sys.state == STATE_QUEUED) { return; } // Block until a motion state is issued
|
||||
while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer.
|
||||
if (sys.state == STATE_QUEUED) { return; } // Block until a motion state is issued
|
||||
|
||||
// Determine if we need to load a new planner block or if the block remainder is replanned.
|
||||
if (pl_block == NULL) {
|
||||
@ -484,7 +489,8 @@ void st_prep_buffer()
|
||||
prep.steps_remaining = st_prep_block->step_event_count;
|
||||
prep.step_per_mm = prep.steps_remaining/pl_block->millimeters;
|
||||
|
||||
if (sys.state == STATE_HOLD) {
|
||||
if (sys.state == STATE_HOLD) {
|
||||
// Override planner block entry speed and enforce deceleration during feed hold.
|
||||
prep.current_speed = prep.exit_speed;
|
||||
pl_block->entry_speed_sqr = prep.exit_speed*prep.exit_speed;
|
||||
}
|
||||
@ -497,7 +503,7 @@ void st_prep_buffer()
|
||||
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;
|
||||
prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block.
|
||||
float inv_2_accel = 0.5/pl_block->acceleration;
|
||||
if (sys.state == STATE_HOLD) {
|
||||
// Compute velocity profile parameters for a feed hold in-progress. This profile overrides
|
||||
@ -506,7 +512,7 @@ void st_prep_buffer()
|
||||
float decel_dist = inv_2_accel*pl_block->entry_speed_sqr;
|
||||
if (decel_dist < pl_block->millimeters) {
|
||||
prep.exit_speed = 0.0;
|
||||
prep.mm_complete = pl_block->millimeters-decel_dist;
|
||||
prep.mm_complete = pl_block->millimeters-decel_dist; // End of feed hold.
|
||||
} else {
|
||||
prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters);
|
||||
}
|
||||
@ -634,13 +640,13 @@ void st_prep_buffer()
|
||||
supported by Grbl (i.e. exceeding 10 meters axis travel at 200 step/mm).
|
||||
*/
|
||||
// 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 = (STEP_FTOL_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))/dt; // (ftol_mult/isr_tic)
|
||||
if (mm_remaining > 0.0) { // Block still incomplete. Distance remaining to be executed.
|
||||
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 ); // (ftol_mult*step/isr_tic)
|
||||
|
||||
// Compute number of steps to execute and segment step phase correction.
|
||||
prep_segment->phase_dist = ceil(INV_TIME_MULTIPLIER*(ceil(steps_remaining)-steps_remaining));
|
||||
prep_segment->phase_dist = ceil(STEP_FTOL_MULTIPLIER*(ceil(steps_remaining)-steps_remaining));
|
||||
prep_segment->n_step = ceil(prep.steps_remaining)-ceil(steps_remaining);
|
||||
|
||||
// Update step execution variables.
|
||||
@ -648,7 +654,7 @@ void st_prep_buffer()
|
||||
// NOTE: Currently only feed holds qualify for this scenario. May change with overrides.
|
||||
prep.current_speed = 0.0;
|
||||
prep.steps_remaining = ceil(steps_remaining);
|
||||
pl_block->millimeters = prep.steps_remaining/prep.step_per_mm;
|
||||
pl_block->millimeters = prep.steps_remaining/prep.step_per_mm; // Update with full steps.
|
||||
plan_cycle_reinitialize();
|
||||
sys.state = STATE_QUEUED; // End cycle.
|
||||
} else {
|
||||
@ -682,12 +688,14 @@ void st_prep_buffer()
|
||||
// int32_t blength = segment_buffer_head - segment_buffer_tail;
|
||||
// if (blength < 0) { blength += SEGMENT_BUFFER_SIZE; }
|
||||
// printInteger(blength);
|
||||
|
||||
if ((sys.state == STATE_HOMING) || (sys.state == STATE_QUEUED)) { return; } // Force only one prepped segment.
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: With feedrate overrides, increases to the override value will not significantly
|
||||
change the planner and stepper current operation. When the value increases, we simply
|
||||
change the current planner and stepper operation. When the value increases, we simply
|
||||
need to recompute the block plan with new nominal speeds and maximum junction velocities.
|
||||
However with a decreasing feedrate override, this gets a little tricky. The current block
|
||||
plan is optimal, so if we try to reduce the feed rates, it may be impossible to create
|
||||
@ -704,4 +712,10 @@ void st_prep_buffer()
|
||||
equal to the block maximum speed and is in an acceleration or cruising ramp. At this
|
||||
point, we know that we can recompute the block velocity profile to meet and continue onto
|
||||
the new block plan.
|
||||
One "easy" way to do this is to have the step segment buffer enforce a deceleration and
|
||||
continually re-plan the planner buffer until the plan becomes feasible. This can work
|
||||
and may be easy to implement, but it expends a lot of CPU cycles and may block out the
|
||||
rest of the functions from operating at peak efficiency. Still the question is how do
|
||||
we know when the plan is feasible in the context of what's already in the code and not
|
||||
require too much more code?
|
||||
*/
|
||||
|
Reference in New Issue
Block a user