Update/compute advance steps inside calculate_trapezoid_for_block

Do not store the block e_D ratio, store directly the computed
compression factor so that we can recompute the advance steps
quickly and update them in sync with the acceleration rates.
This commit is contained in:
Yuri D'Elia 2019-06-05 15:10:31 +02:00
parent 048628083a
commit 0239f4bce1
3 changed files with 33 additions and 31 deletions

View File

@ -261,6 +261,13 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
}
}
#ifdef LIN_ADVANCE
uint16_t final_adv_steps = 0;
if (block->use_advance_lead) {
final_adv_steps = exit_speed * block->adv_comp;
}
#endif
CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section
// This block locks the interrupts globally for 4.38 us,
// which corresponds to a maximum repeat frequency of 228.57 kHz.
@ -271,6 +278,9 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
block->decelerate_after = accelerate_steps+plateau_steps;
block->initial_rate = initial_rate;
block->final_rate = final_rate;
#ifdef LIN_ADVANCE
block->final_adv_steps = final_adv_steps;
#endif
}
CRITICAL_SECTION_END;
}
@ -399,18 +409,8 @@ void planner_recalculate(const float &safe_final_speed)
}
// Recalculate if current block entry or exit junction speed has changed.
if ((prev->flag | current->flag) & BLOCK_FLAG_RECALCULATE) {
// @wavexx: FIXME: the following check is not really enough. calculate_trapezoid does block
// the isr to update the rates, but we don't. we should update atomically
if (!prev->busy) {
// NOTE: Entry and exit factors always > 0 by all previous logic operations.
calculate_trapezoid_for_block(prev, prev->entry_speed, current->entry_speed);
#ifdef LIN_ADVANCE
if (prev->use_advance_lead) {
const float comp = prev->e_D_ratio * extruder_advance_K * cs.axis_steps_per_unit[E_AXIS];
prev->final_adv_steps = current->entry_speed * comp;
}
#endif
}
// Reset current only to ensure next trapezoid is computed.
prev->flag &= ~BLOCK_FLAG_RECALCULATE;
}
@ -424,13 +424,6 @@ void planner_recalculate(const float &safe_final_speed)
// Last/newest block in buffer. Exit speed is set with safe_final_speed. Always recalculated.
current = block_buffer + prev_block_index(block_buffer_head);
calculate_trapezoid_for_block(current, current->entry_speed, safe_final_speed);
#ifdef LIN_ADVANCE
if (current->use_advance_lead) {
const float comp = current->e_D_ratio * extruder_advance_K * cs.axis_steps_per_unit[E_AXIS];
current->max_adv_steps = current->nominal_speed * comp;
current->final_adv_steps = safe_final_speed * comp;
}
#endif
current->flag &= ~BLOCK_FLAG_RECALCULATE;
// SERIAL_ECHOLNPGM("planner_recalculate - 4");
@ -1005,6 +998,9 @@ Having the real displacement of the head, we can calculate the total movement le
block->nominal_rate *= speed_factor;
}
#ifdef LIN_ADVANCE
float e_D_ratio = 0;
#endif
// Compute and limit the acceleration rate for the trapezoid generator.
// block->step_event_count ... event count of the fastest axis
// block->millimeters ... Euclidian length of the XYZ movement or the E length, if no XYZ movement.
@ -1022,7 +1018,7 @@ Having the real displacement of the head, we can calculate the total movement le
#ifdef LIN_ADVANCE
/**
* Use LIN_ADVANCE for blocks if all these are true:
* Use LIN_ADVANCE within this block if all these are true:
*
* block->steps_e : This is a print move, because we checked for X, Y, Z steps before.
* extruder_advance_K : There is an advance factor set.
@ -1034,7 +1030,7 @@ Having the real displacement of the head, we can calculate the total movement le
&& delta_mm[E_AXIS] > 0
&& abs(delta_mm[Z_AXIS]) < 0.5;
if (block->use_advance_lead) {
block->e_D_ratio = (e - position_float[E_AXIS]) /
e_D_ratio = (e - position_float[E_AXIS]) /
sqrt(sq(x - position_float[X_AXIS])
+ sq(y - position_float[Y_AXIS])
+ sq(z - position_float[Z_AXIS]));
@ -1043,10 +1039,10 @@ Having the real displacement of the head, we can calculate the total movement le
// print move due to min. steps per segment. Never execute this with advance! This assumes
// no one will use a retract length of 0mm < retr_length < ~0.2mm and no one will print
// 100mm wide lines using 3mm filament or 35mm wide lines using 1.75mm filament.
if (block->e_D_ratio > 3.0)
if (e_D_ratio > 3.0)
block->use_advance_lead = false;
else {
const uint32_t max_accel_steps_per_s2 = cs.max_jerk[E_AXIS] / (extruder_advance_K * block->e_D_ratio) * steps_per_mm;
const uint32_t max_accel_steps_per_s2 = cs.max_jerk[E_AXIS] / (extruder_advance_K * e_D_ratio) * steps_per_mm;
if (block->acceleration_st > max_accel_steps_per_s2) {
block->acceleration_st = max_accel_steps_per_s2;
#ifdef LA_DEBUG
@ -1089,11 +1085,16 @@ Having the real displacement of the head, we can calculate the total movement le
block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
#ifdef LIN_ADVANCE
#ifdef LIN_ADVANCE
if (block->use_advance_lead) {
// the nominal speed doesn't change past this point: calculate the compression ratio for the
// segment and the required advance steps
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;
// to save more space we avoid another copy of calc_timer and go through slow division, but we
// still need to replicate the *exact* same step grouping policy (see below)
float advance_speed = (extruder_advance_K * block->e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
float advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY;
block->advance_rate = (F_CPU / 8.0) / advance_speed;
if (block->advance_rate > 20000) {
@ -1116,7 +1117,7 @@ Having the real displacement of the head, we can calculate the total movement le
SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed.");
#endif
}
#endif
#endif
// Start with a safe speed.
// Safe speed is the speed, from which the machine may halt to stop immediately.

View File

@ -117,7 +117,7 @@ typedef struct {
max_adv_steps, // max. advance steps to get cruising speed pressure (not always nominal_speed!)
final_adv_steps; // advance steps due to exit speed
uint8_t advance_step_loops; // Number of stepper ticks for each advance isr
float e_D_ratio;
float adv_comp; // Precomputed E compression factor
#endif
uint16_t sdlen;

View File

@ -430,7 +430,8 @@ FORCE_INLINE void stepper_next_block()
nextAdvanceISR = ADV_NEVER;
e_steps = 0;
// incrementally lose pressure
// incrementally lose pressure to give a chance for
// a new LA block to be scheduled and recover
if(current_adv_steps)
--current_adv_steps;
#endif