diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 576a76e884..0cd57a60f4 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -2046,8 +2046,8 @@ */ //#define AUTO_BED_LEVELING_3POINT //#define AUTO_BED_LEVELING_LINEAR -//#define AUTO_BED_LEVELING_BILINEAR -#define AUTO_BED_LEVELING_UBL +#define AUTO_BED_LEVELING_BILINEAR +//#define AUTO_BED_LEVELING_UBL //#define MESH_BED_LEVELING /** @@ -2363,7 +2363,7 @@ * M501 - Read settings from EEPROM. (i.e., Throw away unsaved changes) * M502 - Revert settings to "factory" defaults. (Follow with M500 to init the EEPROM.) */ -#define EEPROM_SETTINGS // Persistent storage with M500 and M501 +//#define EEPROM_SETTINGS // Persistent storage with M500 and M501 //#define DISABLE_M503 // Saves ~2700 bytes of flash. Disable for release! #define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM. //#define EEPROM_BOOT_SILENT // Keep M503 quiet and only give errors during first load diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 8f11f4ec18..b2a800c269 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -796,17 +796,12 @@ block_t* Planner::get_current_block() { */ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor) { - uint32_t initial_rate = LROUND(block->nominal_rate * entry_factor), - final_rate = LROUND(block->nominal_rate * exit_factor); // (steps per second) + uint32_t initial_rate = CEIL(block->nominal_rate * entry_factor), + final_rate = CEIL(block->nominal_rate * exit_factor); // (steps per second) - // Legacy check against supposed timer overflow. However Stepper::calc_timer_interval() already - // should protect against it. But removing this code produces judder in direction-switching - // moves. This is because the current discrete stepping math diverges from physical motion under - // constant acceleration when acceleration_steps_per_s2 is large compared to initial/final_rate. - NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE)); // Enforce the minimum speed + // Limit minimal step rate (Otherwise the timer will overflow.) + NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE)); NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE)); - NOMORE(initial_rate, block->nominal_rate); // NOTE: The nominal rate may be less than MINIMAL_STEP_RATE! - NOMORE(final_rate, block->nominal_rate); #if ANY(S_CURVE_ACCELERATION, LIN_ADVANCE) // If we have some plateau time, the cruise rate will be the nominal rate @@ -814,9 +809,9 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t #endif // Steps for acceleration, plateau and deceleration - int32_t plateau_steps = block->step_event_count, - accelerate_steps = 0, - decelerate_steps = 0; + int32_t plateau_steps = block->step_event_count; + uint32_t accelerate_steps = 0, + decelerate_steps = 0; const int32_t accel = block->acceleration_steps_per_s2; float inverse_accel = 0.0f; @@ -829,7 +824,7 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t accelerate_steps_float = half_inverse_accel * (nominal_rate_sq - FLOAT_SQ(initial_rate)); // Aims to fully reach nominal and final rates accelerate_steps = CEIL(accelerate_steps_float); - decelerate_steps = CEIL(decelerate_steps_float); + decelerate_steps = FLOOR(decelerate_steps_float); // Steps between acceleration and deceleration, if any plateau_steps -= accelerate_steps + decelerate_steps; @@ -839,13 +834,13 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t // Calculate accel / braking time in order to reach the final_rate exactly // at the end of this block. if (plateau_steps < 0) { - accelerate_steps = LROUND((block->step_event_count + accelerate_steps_float - decelerate_steps_float) * 0.5f); - LIMIT(accelerate_steps, 0, int32_t(block->step_event_count)); + accelerate_steps_float = CEIL((block->step_event_count + accelerate_steps_float - decelerate_steps_float) * 0.5f); + accelerate_steps = _MIN(uint32_t(_MAX(accelerate_steps_float, 0)), block->step_event_count); decelerate_steps = block->step_event_count - accelerate_steps; #if ANY(S_CURVE_ACCELERATION, LIN_ADVANCE) // We won't reach the cruising rate. Let's calculate the speed we will reach - NOMORE(cruise_rate, final_speed(initial_rate, accel, accelerate_steps)); + cruise_rate = final_speed(initial_rate, accel, accelerate_steps); #endif } } @@ -861,8 +856,8 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t #endif // Store new block parameters - block->accelerate_before = accelerate_steps; - block->decelerate_start = block->step_event_count - decelerate_steps; + block->accelerate_until = accelerate_steps; + block->decelerate_after = block->step_event_count - decelerate_steps; block->initial_rate = initial_rate; #if ENABLED(S_CURVE_ACCELERATION) block->acceleration_time = acceleration_time; @@ -3164,8 +3159,8 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s block->step_event_count = num_steps; block->initial_rate = block->final_rate = block->nominal_rate = last_page_step_rate; // steps/s - block->accelerate_before = 0; - block->decelerate_start = block->step_event_count; + block->accelerate_until = 0; + block->decelerate_after = block->step_event_count; // Will be set to last direction later if directional format. block->direction_bits.reset(); diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index fd26b4340e..a06dd50e04 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -238,8 +238,8 @@ typedef struct PlannerBlock { #endif // Settings for the trapezoid generator - uint32_t accelerate_before, // The index of the step event where cruising starts - decelerate_start; // The index of the step event on which to start decelerating + uint32_t accelerate_until, // The index of the step event on which to stop acceleration + decelerate_after; // The index of the step event on which to start decelerating #if ENABLED(S_CURVE_ACCELERATION) uint32_t cruise_rate, // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 26569fd25e..cbb547c8c2 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -58,16 +58,10 @@ * * time -----> * - * The speed over time graph forms a TRAPEZOID. The slope of acceleration is calculated by - * v = u + t - * where 't' is the accumulated timer values of the steps so far. - * - * The Stepper ISR dynamically executes acceleration, deceleration, and cruising according to the block parameters. - * - Start at block->initial_rate. - * - Accelerate while step_events_completed < block->accelerate_before. - * - Cruise while step_events_completed < block->decelerate_start. - * - Decelerate after that, until all steps are completed. - * - Reset the trapezoid generator. + * The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates + * first block->accelerate_until step_events_completed, then keeps going at constant speed until + * step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. + * The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far. */ /** @@ -199,7 +193,6 @@ bool Stepper::abort_current_block; ; #endif -// In timer_ticks uint32_t Stepper::acceleration_time, Stepper::deceleration_time; #if MULTISTEPPING_LIMIT > 1 @@ -231,8 +224,8 @@ xyze_long_t Stepper::delta_error{0}; xyze_long_t Stepper::advance_dividend{0}; uint32_t Stepper::advance_divisor = 0, Stepper::step_events_completed = 0, // The number of step events executed in the current block - Stepper::accelerate_before, // The count at which to start cruising - Stepper::decelerate_start, // The count at which to start decelerating + Stepper::accelerate_until, // The count at which to stop accelerating + Stepper::decelerate_after, // The count at which to start decelerating Stepper::step_event_count; // The total event count for the current block #if ANY(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER) @@ -2470,7 +2463,7 @@ hal_timer_t Stepper::block_phase_isr() { // Step events not completed yet... // Are we in acceleration phase ? - if (step_events_completed < accelerate_before) { // Calculate new timer value + if (step_events_completed <= accelerate_until) { // Calculate new timer value #if ENABLED(S_CURVE_ACCELERATION) // Get the next speed to use (Jerk limited!) @@ -2487,7 +2480,6 @@ hal_timer_t Stepper::block_phase_isr() { // step_rate to timer interval and steps per stepper isr interval = calc_multistep_timer_interval(acc_step_rate << oversampling_factor); acceleration_time += interval; - deceleration_time = 0; // Reset since we're doing acceleration first. #if ENABLED(NONLINEAR_EXTRUSION) calc_nonlinear_e(acc_step_rate << oversampling_factor); @@ -2527,24 +2519,30 @@ hal_timer_t Stepper::block_phase_isr() { #endif } // Are we in Deceleration phase ? - else if (step_events_completed >= decelerate_start) { + else if (step_events_completed > decelerate_after) { uint32_t step_rate; #if ENABLED(S_CURVE_ACCELERATION) + // If this is the 1st time we process the 2nd half of the trapezoid... if (!bezier_2nd_half) { // Initialize the Bézier speed curve _calc_bezier_curve_coeffs(current_block->cruise_rate, current_block->final_rate, current_block->deceleration_time_inverse); bezier_2nd_half = true; + // The first point starts at cruise rate. Just save evaluation of the Bézier curve + step_rate = current_block->cruise_rate; } - // Calculate the next speed to use - step_rate = deceleration_time < current_block->deceleration_time - ? _eval_bezier_curve(deceleration_time) - : current_block->final_rate; + else { + // Calculate the next speed to use + step_rate = deceleration_time < current_block->deceleration_time + ? _eval_bezier_curve(deceleration_time) + : current_block->final_rate; + } + #else // Using the old trapezoidal control step_rate = STEP_MULTIPLY(deceleration_time, current_block->acceleration_rate); - if (step_rate < acc_step_rate) { + if (step_rate < acc_step_rate) { // Still decelerating? step_rate = acc_step_rate - step_rate; NOLESS(step_rate, current_block->final_rate); } @@ -2610,9 +2608,6 @@ hal_timer_t Stepper::block_phase_isr() { if (ticks_nominal == 0) { // step_rate to timer interval and loops for the nominal speed ticks_nominal = calc_multistep_timer_interval(current_block->nominal_rate << oversampling_factor); - // Prepare for deceleration - IF_DISABLED(S_CURVE_ACCELERATION, acc_step_rate = current_block->nominal_rate); - deceleration_time = ticks_nominal / 2; #if ENABLED(NONLINEAR_EXTRUSION) calc_nonlinear_e(current_block->nominal_rate << oversampling_factor); @@ -2740,6 +2735,9 @@ hal_timer_t Stepper::block_phase_isr() { // Set flags for all moving axes, accounting for kinematics set_axis_moved_for_current_block(); + // No acceleration / deceleration time elapsed so far + acceleration_time = deceleration_time = 0; + #if ENABLED(ADAPTIVE_STEP_SMOOTHING) // Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate // Otherwise assume no axis smoothing (via oversampling) @@ -2802,8 +2800,8 @@ hal_timer_t Stepper::block_phase_isr() { step_events_completed = 0; // Compute the acceleration and deceleration points - accelerate_before = current_block->accelerate_before << oversampling_factor; - decelerate_start = current_block->decelerate_start << oversampling_factor; + accelerate_until = current_block->accelerate_until << oversampling_factor; + decelerate_after = current_block->decelerate_after << oversampling_factor; TERN_(MIXING_EXTRUDER, mixer.stepper_setup(current_block->b_color)); @@ -2889,8 +2887,7 @@ hal_timer_t Stepper::block_phase_isr() { // Calculate the initial timer interval interval = calc_multistep_timer_interval(current_block->initial_rate << oversampling_factor); - // Initialize ac/deceleration time as if half the time passed. - acceleration_time = deceleration_time = interval / 2; + acceleration_time += interval; #if ENABLED(NONLINEAR_EXTRUSION) calc_nonlinear_e(current_block->initial_rate << oversampling_factor); diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index b13a92892e..02be00593c 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -386,8 +386,8 @@ class Stepper { static xyze_long_t advance_dividend; static uint32_t advance_divisor, step_events_completed, // The number of step events executed in the current block - accelerate_before, // The count at which to start cruising - decelerate_start, // The count at which to start decelerating + accelerate_until, // The point from where we need to stop acceleration + decelerate_after, // The point from where we need to start decelerating step_event_count; // The total event count for the current block #if ANY(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER)