Homing and feed hold bug fixes.

WARNING: Bugs may still exist. This branch is a work in progress and
will be pushed to the edge branch when at beta stability. Use at your
own risk.

- Homing freezing issue fixed. Had to do with the cycle stop flag being
set incorrectly after the homing cycles and before the pull-off
maneuver. Now resets the stepper motors before this can happen.

- Fixed an issue with a rare feed hold failure. Had to do with feed
hold ending exactly at the end of a block. The runtime protocol now
sets the QUEUED and IDLE states appropriately when this occurs. Still
need to clean this code up however, as it’s patched rather than written
well.

- Updated version build via $I command.

- Forgot to comment on a new feature for the last commit. Since steps
are integers and millimeters traveled are floats, the old step segment
generator ignored the step fraction differences in generating the
segment velocities. Didn’t see like it would be much of a big deal, but
there were instances that this would be a problem, especially for very
slow feed rates. The stepper algorithm now micro-adjusts the segment
velocities based on the step fractions not executed from the previous
segment. This ensures that Grbl generates the velocity profiles EXACTLY
and noticeably improves overall acceleration performance.
This commit is contained in:
Sonny Jeon 2014-02-15 13:13:46 -07:00
parent 50fbc6e297
commit 3df61e0ec5
5 changed files with 33 additions and 34 deletions

View File

@ -189,16 +189,16 @@ void limits_go_home(uint8_t cycle_mask)
// Check only for user reset. No time to run protocol_execute_runtime() in this loop. // Check only for user reset. No time to run protocol_execute_runtime() in this loop.
if (sys.execute & EXEC_RESET) { protocol_execute_runtime(); return; } if (sys.execute & EXEC_RESET) { protocol_execute_runtime(); return; }
} while (STEP_MASK & axislock); } while (STEP_MASK & axislock);
delay_ms(settings.homing_debounce_delay); // Delay to allow transient dynamics to dissipate.
// Reverse direction and reset homing rate for locate cycle(s).
homing_rate = settings.homing_feed_rate;
approach = !approach;
st_reset(); // Force disable steppers and reset step segment buffer. Ensure homing motion is cleared. st_reset(); // Force disable steppers and reset step segment buffer. Ensure homing motion is cleared.
plan_reset(); // Reset planner buffer. Zero planner positions. Ensure homing motion is cleared. plan_reset(); // Reset planner buffer. Zero planner positions. Ensure homing motion is cleared.
delay_ms(settings.homing_debounce_delay); // Delay to allow transient dynamics to dissipate.
// Reverse direction and reset homing rate for locate cycle(s).
homing_rate = settings.homing_feed_rate;
approach = !approach;
} while (n_cycle-- > 0); } while (n_cycle-- > 0);
// The active cycle axes should now be homed and machine limits have been located. By // The active cycle axes should now be homed and machine limits have been located. By
@ -230,7 +230,6 @@ void limits_go_home(uint8_t cycle_mask)
// Initiate pull-off using main motion control routines. // Initiate pull-off using main motion control routines.
// TODO : Clean up state routines so that this motion still shows homing state. // TODO : Clean up state routines so that this motion still shows homing state.
sys.state = STATE_QUEUED; sys.state = STATE_QUEUED;
// protocol_cycle_start();
sys.execute |= EXEC_CYCLE_START; sys.execute |= EXEC_CYCLE_START;
protocol_execute_runtime(); protocol_execute_runtime();
protocol_buffer_synchronize(); // Complete pull-off motion. protocol_buffer_synchronize(); // Complete pull-off motion.

View File

@ -242,9 +242,8 @@ void protocol_execute_runtime()
// cycle reinitializations. The stepper path should continue exactly as if nothing has happened. // cycle reinitializations. The stepper path should continue exactly as if nothing has happened.
// NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes. // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.
if (rt_exec & EXEC_CYCLE_STOP) { if (rt_exec & EXEC_CYCLE_STOP) {
if (sys.state != STATE_QUEUED) { if ( plan_get_current_block() ) { sys.state = STATE_QUEUED; }
sys.state = STATE_IDLE; else { sys.state = STATE_IDLE; }
}
bit_false(sys.execute,EXEC_CYCLE_STOP); bit_false(sys.execute,EXEC_CYCLE_STOP);
} }

View File

@ -26,7 +26,7 @@
#define GRBL_VERSION "0.9c" #define GRBL_VERSION "0.9c"
#define GRBL_VERSION_BUILD "20140110" #define GRBL_VERSION_BUILD "20140215"
// Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl // Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl
// when firmware is upgraded. Always stored in byte 0 of eeprom // when firmware is upgraded. Always stored in byte 0 of eeprom

View File

@ -61,11 +61,11 @@ void spindle_run(uint8_t direction, float rpm)
// Halt or set spindle direction and rpm. // Halt or set spindle direction and rpm.
if (direction == SPINDLE_DISABLE) { if (direction == SPINDLE_DISABLE) {
spindle_stop(); spindle_stop();
} else { } else {
if (direction == SPINDLE_ENABLE_CW) { if (direction == SPINDLE_ENABLE_CW) {
SPINDLE_DIRECTION_PORT &= ~(1<<SPINDLE_DIRECTION_BIT); SPINDLE_DIRECTION_PORT &= ~(1<<SPINDLE_DIRECTION_BIT);
} else { } else {
@ -80,7 +80,7 @@ void spindle_run(uint8_t direction, float rpm)
if ( rpm > SPINDLE_RPM_RANGE ) { rpm = SPINDLE_RPM_RANGE; } // Prevent uint8 overflow if ( rpm > SPINDLE_RPM_RANGE ) { rpm = SPINDLE_RPM_RANGE; } // Prevent uint8 overflow
uint8_t current_pwm = floor( rpm*(255.0/SPINDLE_RPM_RANGE) + 0.5); uint8_t current_pwm = floor( rpm*(255.0/SPINDLE_RPM_RANGE) + 0.5);
OCR_REGISTER = current_pwm; OCR_REGISTER = current_pwm;
#ifndef CPU_MAP_ATMEGA328P // On the Uno, spindle enable and PWM are shared. #ifndef CPU_MAP_ATMEGA328P // On the Uno, spindle enable and PWM are shared.
SPINDLE_ENABLE_PORT |= (1<<SPINDLE_ENABLE_BIT); SPINDLE_ENABLE_PORT |= (1<<SPINDLE_ENABLE_BIT);
#endif #endif

View File

@ -620,24 +620,6 @@ 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;
float mm_remaining = pl_block->millimeters;
float minimum_mm = pl_block->millimeters-prep.req_mm_increment;
if (minimum_mm < 0.0) { minimum_mm = 0.0; }
if (sys.state == STATE_HOLD) {
if (minimum_mm < prep.mm_complete) { // NOTE: Exit condition
// Less than one step to decelerate to zero speed, but already very close. AMASS
// requires full steps to execute. So, just bail.
prep.current_speed = 0.0;
prep.dt_remainder = 0.0;
prep.steps_remaining = ceil(pl_block->millimeters * 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;
return; // Segment not generated, but current step data still retained.
}
}
/*------------------------------------------------------------------------------------ /*------------------------------------------------------------------------------------
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
@ -656,7 +638,11 @@ void st_prep_buffer()
float dt = 0.0; // Initialize segment time float dt = 0.0; // Initialize segment time
float time_var = dt_max; // Time worker variable float time_var = dt_max; // Time worker variable
float mm_var; // mm-Distance worker variable float mm_var; // mm-Distance worker variable
float speed_var; // Speed worker variable float speed_var; // Speed worker variable
float mm_remaining = pl_block->millimeters;
float minimum_mm = pl_block->millimeters-prep.req_mm_increment;
if (minimum_mm < 0.0) { minimum_mm = 0.0; }
do { do {
switch (prep.ramp_type) { switch (prep.ramp_type) {
case RAMP_ACCEL: case RAMP_ACCEL:
@ -728,6 +714,21 @@ void st_prep_buffer()
float n_steps_remaining = ceil(steps_remaining); // Round-up current steps remaining float n_steps_remaining = ceil(steps_remaining); // Round-up current steps remaining
float last_n_steps_remaining = ceil(prep.steps_remaining); // Round-up last steps remaining float last_n_steps_remaining = ceil(prep.steps_remaining); // Round-up last steps remaining
prep_segment->n_step = last_n_steps_remaining-n_steps_remaining; // Compute number of steps to execute. prep_segment->n_step = last_n_steps_remaining-n_steps_remaining; // Compute number of steps to execute.
// Bail if we are at the end of a feed hold and don't have a step to execute.
if (sys.state == STATE_HOLD) {
if (prep_segment->n_step == 0) {
// Less than one step to decelerate to zero speed, but already very close. AMASS
// requires full steps to execute. So, just bail.
prep.current_speed = 0.0;
prep.dt_remainder = 0.0;
prep.steps_remaining = n_steps_remaining;
pl_block->millimeters = prep.steps_remaining/prep.step_per_mm; // Update with full steps.
plan_cycle_reinitialize();
sys.state = STATE_QUEUED;
return; // Segment not generated, but current step data still retained.
}
}
// Compute segment step rate. Since steps are integers and mm distances traveled are not, // Compute segment step rate. Since steps are integers and mm distances traveled are not,
// the end of every segment can have a partial step of varying magnitudes that are not // the end of every segment can have a partial step of varying magnitudes that are not