From 9b9abf1b2f109b705ec4caf1ce31c4e8675d2262 Mon Sep 17 00:00:00 2001 From: Sonny Jeon Date: Tue, 5 Aug 2014 16:17:45 -0600 Subject: [PATCH] Fixed bug related to very very low feed rates. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - A very very low feed rate command like `G1 X100 F0.01` would cause some floating-point round-off error and freeze Grbl into an infinite loop. To fix it, introduced a MINIMUM_FEED_RATE parameter in config.h to ensure motions always complete. - MINIMUM_FEED_RATE is set at 1.0 mm/min by default. It’s recommended that no rates are below this value, but 0.1mm/min may be ok in some situations. --- config.h | 5 +++++ planner.c | 1 + settings.h | 2 +- stepper.c | 30 ++---------------------------- 4 files changed, 9 insertions(+), 29 deletions(-) diff --git a/config.h b/config.h index 4630aa5..4f8385e 100644 --- a/config.h +++ b/config.h @@ -167,6 +167,11 @@ // should not be much greater than zero or to the minimum value necessary for the machine to work. #define MINIMUM_JUNCTION_SPEED 0.0 // (mm/min) +// Sets the minimum feed rate the planner will allow. Any value below it will be set to this minimum +// value. This also ensures that a planned motion always completes and accounts for any floating-point +// round-off errors. Recommend a value no lower than 1.0. +#define MINIMUM_FEED_RATE 1.0 // (mm/min) + // Number of arc generation iterations by small angle approximation before exact arc trajectory // correction with expensive sin() and cos() calcualtions. This parameter maybe decreased if there // are issues with the accuracy of the arc generations, or increased if arc execution is getting diff --git a/planner.c b/planner.c index 16b5c2a..c324376 100644 --- a/planner.c +++ b/planner.c @@ -309,6 +309,7 @@ uint8_t plan_check_full_buffer() // TODO: Need to distinguish a rapids vs feed move for overrides. Some flag of some sort. if (feed_rate < 0) { feed_rate = SOME_LARGE_VALUE; } // Scaled down to absolute max/rapids rate later else if (invert_feed_rate) { feed_rate = block->millimeters/feed_rate; } + if (feed_rate < MINIMUM_FEED_RATE) { feed_rate = MINIMUM_FEED_RATE; } // Prevents step generation round-off condition. // Calculate the unit vector of the line move and the block maximum feed rate and acceleration scaled // down such that no individual axes maximum values are exceeded with respect to the line direction. diff --git a/settings.h b/settings.h index 50cfceb..f8d7dce 100644 --- a/settings.h +++ b/settings.h @@ -24,7 +24,7 @@ #define GRBL_VERSION "0.9g" -#define GRBL_VERSION_BUILD "20140804" +#define GRBL_VERSION_BUILD "20140805" // 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/stepper.c b/stepper.c index 0ca2850..21e23e6 100644 --- a/stepper.c +++ b/stepper.c @@ -637,7 +637,6 @@ void st_prep_buffer() prep.maximum_speed = prep.exit_speed; } } - } // Initialize new segment @@ -688,6 +687,8 @@ void st_prep_buffer() break; case RAMP_CRUISE: // NOTE: mm_var used to retain the last mm_remaining for incomplete segment time_var calculations. + // NOTE: If maximum_speed*time_var value is too low, round-off can cause mm_var to not change. To + // prevent this, simply enforce a minimum speed threshold in the planner. mm_var = mm_remaining - prep.maximum_speed*time_var; if (mm_var < prep.decelerate_after) { // End of cruise. // Cruise-deceleration junction or end of block. @@ -853,30 +854,3 @@ void st_prep_buffer() return 0.0f; } #endif - -/* - TODO: With feedrate overrides, increases to the override value will not significantly - 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 - a feasible plan at its current operating speed and decelerate down to zero at the end of - the buffer. We first have to enforce a deceleration to meet and intersect with the reduced - feedrate override plan. For example, if the current block is cruising at a nominal rate - and the feedrate override is reduced, the new nominal rate will now be lower. The velocity - profile must first decelerate to the new nominal rate and then follow on the new plan. - Another issue is whether or not a feedrate override reduction causes a deceleration - that acts over several planner blocks. For example, say that the plan is already heavily - decelerating throughout it, reducing the feedrate override will not do much to it. So, - how do we determine when to resume the new plan? One solution is to tie into the feed hold - handling code to enforce a deceleration, but check when the current speed is less than or - 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? -*/