Remove cumulative error in segments without cruising (take 1)

PR #2591 made LA compression always account for retractions instead of
discarding the current compression steps. While this fixed overextrusion
in short segments followed by wipes, it uncovered another issue in how
the compression steps are spread during the trapezoid calculations
leading to gaps in segments followed by retractions (as highlighted by
/some/ prints in #2693).

LA1.5 always computes the required target compression steps for a
segment at nominal speed. Because of how the extra steps are allocated
using multiples of the accelerating frequency, if the segment is
truncated before cruising is reached, an additional cycle of steps can
be inserted before deceleration starts. Deceleration is also not
guaranteed to be symmetric where up to _two_ cycles can be skipped
depending on the stepping cycle, leading to a situation where a
symmetric acceleration/deceleration block will lead up to a cycle of
accumulated compression.

While forcing an the extra step during deceleration is possible by
tweaking the error term (eISR_Err), this doesn't guarantee balance in
all cases. The underlying issue is that the function is aiming a
compression which cannot be reached (nominal speed), and not at the
effective max speed reached in the trapezoid, thus moving the average
result higher over time.

We fix this by calculating the effective maximum speed (and compression)
reached during the trapezoid, which stops compression on the required
cycle irregardless of the error term, balancing the result.

This is the first unoptimized POC: this is not for production: a lot of
calculations are redundand and could work directly in steps/s^2.
This commit is contained in:
Yuri D'Elia 2020-06-21 15:19:31 +02:00
parent 45e182911d
commit 15548958e9

View File

@ -225,12 +225,15 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
uint32_t accel_decel_steps = accelerate_steps + decelerate_steps; uint32_t accel_decel_steps = accelerate_steps + decelerate_steps;
// Size of Plateau of Nominal Rate. // Size of Plateau of Nominal Rate.
uint32_t plateau_steps = 0; uint32_t plateau_steps = 0;
// Maximum effective speed reached in the trapezoid (mm/s)
float max_speed;
// Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will
// have to use intersection_distance() to calculate when to abort acceleration and start braking // have to use intersection_distance() to calculate when to abort acceleration and start braking
// in order to reach the final_rate exactly at the end of this block. // in order to reach the final_rate exactly at the end of this block.
if (accel_decel_steps < block->step_event_count.wide) { if (accel_decel_steps < block->step_event_count.wide) {
plateau_steps = block->step_event_count.wide - accel_decel_steps; plateau_steps = block->step_event_count.wide - accel_decel_steps;
max_speed = block->nominal_speed;
} else { } else {
uint32_t acceleration_x4 = acceleration << 2; uint32_t acceleration_x4 = acceleration << 2;
// Avoid negative numbers // Avoid negative numbers
@ -263,12 +266,18 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
decelerate_steps = block->step_event_count.wide; decelerate_steps = block->step_event_count.wide;
accelerate_steps = block->step_event_count.wide - decelerate_steps; accelerate_steps = block->step_event_count.wide - decelerate_steps;
} }
// TODO: not for production
float dist = intersection_distance(entry_speed, exit_speed, block->acceleration, block->millimeters);
max_speed = sqrt(2 * block->acceleration * dist + entry_speed*entry_speed);
} }
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
uint16_t final_adv_steps = 0; uint16_t final_adv_steps = 0;
uint16_t max_adv_steps = 0;
if (block->use_advance_lead) { if (block->use_advance_lead) {
final_adv_steps = exit_speed * block->adv_comp; final_adv_steps = exit_speed * block->adv_comp;
max_adv_steps = max_speed * block->adv_comp;
} }
#endif #endif
@ -284,6 +293,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
block->final_rate = final_rate; block->final_rate = final_rate;
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
block->final_adv_steps = final_adv_steps; block->final_adv_steps = final_adv_steps;
block->max_adv_steps = max_adv_steps;
#endif #endif
} }
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
@ -1137,9 +1147,8 @@ Having the real displacement of the head, we can calculate the total movement le
#ifdef LIN_ADVANCE #ifdef LIN_ADVANCE
if (block->use_advance_lead) { if (block->use_advance_lead) {
// the nominal speed doesn't change past this point: calculate the compression ratio for the // the nominal speed doesn't change past this point: calculate the compression ratio for the
// segment and the required advance steps // segment (the required advance steps are computed during trapezoid planning)
block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS];
block->max_adv_steps = block->nominal_speed * block->adv_comp;
float advance_speed; float advance_speed;
if (e_D_ratio > 0) if (e_D_ratio > 0)