From 3df61e0ec5f7cb0b4c09a847558ecf14a8697802 Mon Sep 17 00:00:00 2001 From: Sonny Jeon Date: Sat, 15 Feb 2014 13:13:46 -0700 Subject: [PATCH] Homing and feed hold bug fixes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- limits.c | 13 ++++++------- protocol.c | 5 ++--- settings.h | 2 +- spindle_control.c | 8 ++++---- stepper.c | 39 ++++++++++++++++++++------------------- 5 files changed, 33 insertions(+), 34 deletions(-) diff --git a/limits.c b/limits.c index 82a9e57..9016e8a 100644 --- a/limits.c +++ b/limits.c @@ -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. if (sys.execute & EXEC_RESET) { protocol_execute_runtime(); return; } } 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. 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); // 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. // TODO : Clean up state routines so that this motion still shows homing state. sys.state = STATE_QUEUED; -// protocol_cycle_start(); sys.execute |= EXEC_CYCLE_START; protocol_execute_runtime(); protocol_buffer_synchronize(); // Complete pull-off motion. diff --git a/protocol.c b/protocol.c index 7c7ae2c..c8406d0 100644 --- a/protocol.c +++ b/protocol.c @@ -242,9 +242,8 @@ void protocol_execute_runtime() // 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. if (rt_exec & EXEC_CYCLE_STOP) { - if (sys.state != STATE_QUEUED) { - sys.state = STATE_IDLE; - } + if ( plan_get_current_block() ) { sys.state = STATE_QUEUED; } + else { sys.state = STATE_IDLE; } bit_false(sys.execute,EXEC_CYCLE_STOP); } diff --git a/settings.h b/settings.h index 6ff54be..3551ec2 100644 --- a/settings.h +++ b/settings.h @@ -26,7 +26,7 @@ #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 // when firmware is upgraded. Always stored in byte 0 of eeprom diff --git a/spindle_control.c b/spindle_control.c index ad3efc9..16034b0 100644 --- a/spindle_control.c +++ b/spindle_control.c @@ -61,11 +61,11 @@ void spindle_run(uint8_t direction, float rpm) // Halt or set spindle direction and rpm. if (direction == SPINDLE_DISABLE) { - + spindle_stop(); - + } else { - + if (direction == SPINDLE_ENABLE_CW) { SPINDLE_DIRECTION_PORT &= ~(1< SPINDLE_RPM_RANGE ) { rpm = SPINDLE_RPM_RANGE; } // Prevent uint8 overflow uint8_t current_pwm = floor( rpm*(255.0/SPINDLE_RPM_RANGE) + 0.5); OCR_REGISTER = current_pwm; - + #ifndef CPU_MAP_ATMEGA328P // On the Uno, spindle enable and PWM are shared. SPINDLE_ENABLE_PORT |= (1<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 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 time_var = dt_max; // Time 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 { switch (prep.ramp_type) { case RAMP_ACCEL: @@ -728,6 +714,21 @@ void st_prep_buffer() 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 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, // the end of every segment can have a partial step of varying magnitudes that are not