From b5482e455f1b6f2cc6785caac32cfae4653c7c55 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Sun, 25 Sep 2022 01:07:25 +0100 Subject: [PATCH 1/2] added new planner options - new planner option ENABLE_PLANNER_SPEED_OVERSHOOT. This will do a single pass in speed ramp profile calculations. This will not take in account the current travel speed (that may not allow the calculated speed to be hit). This saves some calculation cycles -new planner option ENABLE_PLANNER_NOACCEL_ON_SLOWER_EXIT and minimal distance threshold ENABLE_PLANNER_NOACCEL_MAX_SETP_DISTANCE. This prevents short length segments to accelerate and then deaccelerate again to give a smoother motion. --- uCNC/cnc_config.h | 17 +++++++++++++++++ uCNC/src/core/planner.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/uCNC/cnc_config.h b/uCNC/cnc_config.h index ff0d33a81..ba60f4e3c 100644 --- a/uCNC/cnc_config.h +++ b/uCNC/cnc_config.h @@ -285,6 +285,23 @@ extern "C" // #define ENABLE_BACKLASH_COMPENSATION + /** + * By enabling this option the planner will only care about the exit speed. + * This will make the planner not perform the forward pass to adjust entry speeds. + * The adjustment of the next planner block is made on the fly when the block is loaded. + * */ + // #define ENABLE_PLANNER_SPEED_OVERSHOOT + + /** + * By enabling this option the planner will only perform acceleration if the exit speed is higher + * then the current speed and the distance travelled is lower then a give threshold + * This will prevent sucessive ramp up and down speed profiles a produce more continuous speed motions + * */ + // #define ENABLE_PLANNER_NOACCEL_ON_SLOWER_EXIT + #ifdef ENABLE_PLANNER_NOACCEL_ON_SLOWER_EXIT + #define ENABLE_PLANNER_NOACCEL_MAX_SETP_DISTANCE 5 + #endif + /** * Uncomment these to enable step ISR calculation strategies (uses more * memory) STEP_ISR_SKIP_MAIN - carries the information about the main diff --git a/uCNC/src/core/planner.c b/uCNC/src/core/planner.c index 576a9ad4a..eda6ea182 100644 --- a/uCNC/src/core/planner.c +++ b/uCNC/src/core/planner.c @@ -279,6 +279,9 @@ void planner_discard_block(void) } uint8_t index = planner_data_read; +#ifdef ENABLE_PLANNER_SPEED_OVERSHOOT + float last_speed = planner_data[index].entry_feed_sqr; +#endif if (++index == PLANNER_BUFFER_SIZE) { @@ -295,6 +298,9 @@ void planner_discard_block(void) #endif planner_data_blocks = blocks; +#ifdef ENABLE_PLANNER_SPEED_OVERSHOOT + planner_data[index].entry_feed_sqr = last_speed; +#endif planner_data_read = index; } @@ -417,10 +423,26 @@ float planner_get_block_top_speed(float exit_speed_sqr) v_max^2 = (v_exit^2 + 2 * acceleration * distance + v_entry)/2 */ + // calculates the difference between the entry speed and the exit speed uint8_t index = planner_data_read; float speed_delta = exit_speed_sqr - planner_data[index].entry_feed_sqr; - // caclculates the speed increase/decrease for the given distance + +#ifdef ENABLE_PLANNER_NOACCEL_ON_SLOWER_EXIT + // exit speed is lower then entry speed + if (speed_delta < 0) + { + uint8_t i = planner_data[index].main_stepper; + // is short distance? + if (planner_data[index].total_steps < (planner_data[index].steps[i] * g_settings.step_per_mm[i])) + { + // keep speed (avoid accel on short motion that will have to deaccel after) + return planner_data[index].entry_feed_sqr; + } + } +#endif + + // calculates the speed increase/decrease for the given distance float junction_speed_sqr = planner_data[index].acceleration * (float)(planner_data[index].total_steps); junction_speed_sqr = fast_flt_mul2(junction_speed_sqr); // if there is enough space to accelerate computes the junction speed @@ -524,9 +546,10 @@ static void planner_recalculate(void) while (!planner_data[block].planner_flags.bit.optimal && block != first) { - if ((planner_data[block].entry_feed_sqr >= planner_data[block].entry_max_feed_sqr) || planner_data[block].planner_flags.bit.optimal) + if ((planner_data[block].entry_feed_sqr >= planner_data[block].entry_max_feed_sqr)) { // found optimal + planner_data[block].planner_flags.bit.optimal = true; break; } speedchange = ((float)(planner_data[block].total_steps << 1)) * planner_data[block].acceleration; @@ -537,6 +560,7 @@ static void planner_recalculate(void) block = planner_buffer_prev(block); } +#ifndef ENABLE_PLANNER_SPEED_OVERSHOOT // optimizes exit speeds (forward pass) while (block != last) { @@ -564,6 +588,7 @@ static void planner_recalculate(void) block = next; next = planner_buffer_next(block); } +#endif } void planner_sync_tools(motion_data_t *block_data) From 5dbd9358d4cd55aff4bccf4bec0ac1b04c333bb0 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Wed, 5 Oct 2022 15:52:36 +0100 Subject: [PATCH 2/2] modified planner modes and added new mode --- uCNC/cnc_config.h | 13 ++++++++++--- uCNC/src/core/interpolator.c | 6 +++++- uCNC/src/core/planner.c | 18 +++++++++++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/uCNC/cnc_config.h b/uCNC/cnc_config.h index ba60f4e3c..ac948e9b0 100644 --- a/uCNC/cnc_config.h +++ b/uCNC/cnc_config.h @@ -290,16 +290,23 @@ extern "C" * This will make the planner not perform the forward pass to adjust entry speeds. * The adjustment of the next planner block is made on the fly when the block is loaded. * */ - // #define ENABLE_PLANNER_SPEED_OVERSHOOT + // #define ENABLE_PLANNER_SPEED_OVERSHOOT + + /** + * By enabling this option the planner will junction speed based on accel only if need + * meaning that the junction speed will only be the maximum value between current and exit speed + * This will eliminate ramp up and down completly and over-simplify calculations + * */ + // #define ENABLE_PLANNER_ACCEL_NONOPTIMAL /** * By enabling this option the planner will only perform acceleration if the exit speed is higher - * then the current speed and the distance travelled is lower then a give threshold + * then the current speed and the distance travelled is lower then a give threshold (in steps) * This will prevent sucessive ramp up and down speed profiles a produce more continuous speed motions * */ // #define ENABLE_PLANNER_NOACCEL_ON_SLOWER_EXIT #ifdef ENABLE_PLANNER_NOACCEL_ON_SLOWER_EXIT - #define ENABLE_PLANNER_NOACCEL_MAX_SETP_DISTANCE 5 + #define ENABLE_PLANNER_NOACCEL_MAX_STEP_DISTANCE 200 #endif /** diff --git a/uCNC/src/core/interpolator.c b/uCNC/src/core/interpolator.c index 9e38fbfbe..96ffee827 100644 --- a/uCNC/src/core/interpolator.c +++ b/uCNC/src/core/interpolator.c @@ -741,6 +741,9 @@ void itp_run(void) float accel_dist = ABS(junction_speed_sqr - itp_cur_plan_block->entry_feed_sqr) / itp_cur_plan_block->acceleration; accel_dist = fast_flt_div2(accel_dist); accel_until -= floorf(accel_dist); +#ifdef ENABLE_PLANNER_ACCEL_NONOPTIMAL + accel_until = MIN(accel_until, remaining_steps); +#endif initial_accel_negative = (junction_speed_sqr < itp_cur_plan_block->entry_feed_sqr); } @@ -899,11 +902,12 @@ void itp_run(void) } #endif remaining_steps -= segm_steps; - +#ifndef ENABLE_PLANNER_ACCEL_NONOPTIMAL if (remaining_steps == accel_until) // resets float additions error { itp_cur_plan_block->entry_feed_sqr = junction_speed_sqr; } +#endif itp_cur_plan_block->total_steps = remaining_steps; diff --git a/uCNC/src/core/planner.c b/uCNC/src/core/planner.c index eda6ea182..790ea17a0 100644 --- a/uCNC/src/core/planner.c +++ b/uCNC/src/core/planner.c @@ -426,6 +426,21 @@ float planner_get_block_top_speed(float exit_speed_sqr) // calculates the difference between the entry speed and the exit speed uint8_t index = planner_data_read; + +#ifdef ENABLE_PLANNER_ACCEL_NONOPTIMAL + // just computes half way accel + float junction_speed_sqr = planner_data[index].acceleration * (float)(planner_data[index].total_steps); + if (planner_data[index].entry_feed_sqr > exit_speed_sqr) + { + junction_speed_sqr += exit_speed_sqr; + } + else + { + junction_speed_sqr += planner_data[index].entry_feed_sqr; + junction_speed_sqr = MAX(junction_speed_sqr, exit_speed_sqr); + } +#else + float speed_delta = exit_speed_sqr - planner_data[index].entry_feed_sqr; #ifdef ENABLE_PLANNER_NOACCEL_ON_SLOWER_EXIT @@ -434,7 +449,7 @@ float planner_get_block_top_speed(float exit_speed_sqr) { uint8_t i = planner_data[index].main_stepper; // is short distance? - if (planner_data[index].total_steps < (planner_data[index].steps[i] * g_settings.step_per_mm[i])) + if (ENABLE_PLANNER_NOACCEL_MAX_STEP_DISTANCE > planner_data[index].steps[i]) { // keep speed (avoid accel on short motion that will have to deaccel after) return planner_data[index].entry_feed_sqr; @@ -461,6 +476,7 @@ float planner_get_block_top_speed(float exit_speed_sqr) // will overshoot the desired exit speed even deaccelerating all the way junction_speed_sqr = planner_data[index].entry_feed_sqr; } +#endif float rapid_feed_sqr = planner_data[index].rapid_feed_sqr; float target_speed_sqr = planner_data[index].feed_sqr;