Add files via upload

This commit is contained in:
rtorchia
2024-10-14 09:02:09 -04:00
committed by GitHub
parent c7364fb91b
commit 6d7fb46487
4 changed files with 229 additions and 275 deletions
+35 -36
View File
@@ -784,7 +784,7 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE)); NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE));
NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE)); NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE));
#if ENABLED(S_CURVE_ACCELERATION) #if EITHER(S_CURVE_ACCELERATION, LIN_ADVANCE)
uint32_t cruise_rate = initial_rate; uint32_t cruise_rate = initial_rate;
#endif #endif
@@ -805,7 +805,7 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
accelerate_steps = _MIN(uint32_t(_MAX(accelerate_steps_float, 0)), block->step_event_count); accelerate_steps = _MIN(uint32_t(_MAX(accelerate_steps_float, 0)), block->step_event_count);
plateau_steps = 0; plateau_steps = 0;
#if ENABLED(S_CURVE_ACCELERATION) #if EITHER(S_CURVE_ACCELERATION, LIN_ADVANCE)
// We won't reach the cruising rate. Let's calculate the speed we will reach // We won't reach the cruising rate. Let's calculate the speed we will reach
cruise_rate = final_speed(initial_rate, accel, accelerate_steps); cruise_rate = final_speed(initial_rate, accel, accelerate_steps);
#endif #endif
@@ -837,6 +837,14 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
#endif #endif
block->final_rate = final_rate; block->final_rate = final_rate;
#if ENABLED(LIN_ADVANCE)
if (block->la_advance_rate) {
const float comp = extruder_advance_K[block->extruder] * block->steps.e / block->step_event_count;
block->max_adv_steps = cruise_rate * comp;
block->final_adv_steps = final_rate * comp;
}
#endif
/** /**
* Laser trapezoid calculations * Laser trapezoid calculations
* *
@@ -1183,13 +1191,6 @@ void Planner::recalculate_trapezoids() {
const float current_nominal_speed = SQRT(block->nominal_speed_sqr), const float current_nominal_speed = SQRT(block->nominal_speed_sqr),
nomr = 1.0f / current_nominal_speed; nomr = 1.0f / current_nominal_speed;
calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr); calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
#if ENABLED(LIN_ADVANCE)
if (block->use_advance_lead) {
const float comp = block->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm[E_AXIS];
block->max_adv_steps = current_nominal_speed * comp;
block->final_adv_steps = next_entry_speed * comp;
}
#endif
} }
// Reset current only to ensure next trapezoid is computed - The // Reset current only to ensure next trapezoid is computed - The
@@ -1222,13 +1223,6 @@ void Planner::recalculate_trapezoids() {
const float next_nominal_speed = SQRT(next->nominal_speed_sqr), const float next_nominal_speed = SQRT(next->nominal_speed_sqr),
nomr = 1.0f / next_nominal_speed; nomr = 1.0f / next_nominal_speed;
calculate_trapezoid_for_block(next, next_entry_speed * nomr, float(MINIMUM_PLANNER_SPEED) * nomr); calculate_trapezoid_for_block(next, next_entry_speed * nomr, float(MINIMUM_PLANNER_SPEED) * nomr);
#if ENABLED(LIN_ADVANCE)
if (next->use_advance_lead) {
const float comp = next->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm[E_AXIS];
next->max_adv_steps = next_nominal_speed * comp;
next->final_adv_steps = (MINIMUM_PLANNER_SPEED) * comp;
}
#endif
} }
// Reset next only to ensure its trapezoid is computed - The stepper is free to use // Reset next only to ensure its trapezoid is computed - The stepper is free to use
@@ -2282,9 +2276,11 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
// Compute and limit the acceleration rate for the trapezoid generator. // Compute and limit the acceleration rate for the trapezoid generator.
const float steps_per_mm = block->step_event_count * inverse_millimeters; const float steps_per_mm = block->step_event_count * inverse_millimeters;
uint32_t accel; uint32_t accel;
#if ENABLED(LIN_ADVANCE)
bool use_advance_lead = false;
#endif
if (!block->steps.a && !block->steps.b && !block->steps.c) { // Is this a retract / recover move? if (!block->steps.a && !block->steps.b && !block->steps.c) { // Is this a retract / recover move?
accel = CEIL(settings.retract_acceleration * steps_per_mm); // Convert to: acceleration steps/sec^2 accel = CEIL(settings.retract_acceleration * steps_per_mm); // Convert to: acceleration steps/sec^2
TERN_(LIN_ADVANCE, block->use_advance_lead = false); // No linear advance for simple retract/recover
} }
else { else {
#define LIMIT_ACCEL_LONG(AXIS,INDX) do{ \ #define LIMIT_ACCEL_LONG(AXIS,INDX) do{ \
@@ -2317,27 +2313,23 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
* *
* de > 0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves) * de > 0 : Extruder is running forward (e.g., for "Wipe while retracting" (Slic3r) or "Combing" (Cura) moves)
*/ */
block->use_advance_lead = esteps use_advance_lead = esteps && extruder_advance_K[extruder] && de > 0;
&& extruder_advance_K[active_extruder]
&& de > 0;
if (block->use_advance_lead) { if (use_advance_lead) {
block->e_D_ratio = (target_float.e - position_float.e) / float e_D_ratio = (target_float.e - position_float.e) /
#if IS_KINEMATIC TERN(IS_KINEMATIC, block->millimeters,
block->millimeters
#else
SQRT(sq(target_float.x - position_float.x) SQRT(sq(target_float.x - position_float.x)
+ sq(target_float.y - position_float.y) + sq(target_float.y - position_float.y)
+ sq(target_float.z - position_float.z)) + sq(target_float.z - position_float.z))
#endif );
;
// Check for unusual high e_D ratio to detect if a retract move was combined with the last print move due to min. steps per segment. Never execute this with advance! // Check for unusual high e_D ratio to detect if a retract move was combined with the last 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. // 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.0f) if (e_D_ratio > 3.0f)
block->use_advance_lead = false; use_advance_lead = false;
else { else {
const uint32_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[active_extruder] * block->e_D_ratio) * steps_per_mm; // Scale E acceleration so that it will be possible to jump to the advance speed.
const uint32_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[extruder] * e_D_ratio) * steps_per_mm;
if (TERN0(LA_DEBUG, accel > max_accel_steps_per_s2)) if (TERN0(LA_DEBUG, accel > max_accel_steps_per_s2))
SERIAL_ECHOLNPGM("Acceleration limited."); SERIAL_ECHOLNPGM("Acceleration limited.");
NOMORE(accel, max_accel_steps_per_s2); NOMORE(accel, max_accel_steps_per_s2);
@@ -2365,13 +2357,20 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
block->acceleration_rate = (uint32_t)(accel * (sq(4096.0f) / (STEPPER_TIMER_RATE))); block->acceleration_rate = (uint32_t)(accel * (sq(4096.0f) / (STEPPER_TIMER_RATE)));
#endif #endif
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
if (block->use_advance_lead) { block->la_advance_rate = 0;
block->advance_speed = (STEPPER_TIMER_RATE) / (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * settings.axis_steps_per_mm[E_AXIS_N(extruder)]); block->la_scaling = 0;
if (use_advance_lead) {
// the Bresenham algorithm will convert this step rate into extruder steps
block->la_advance_rate = extruder_advance_K[extruder] * block->acceleration_steps_per_s2;
// reduce LA ISR frequency by calling it only often enough to ensure that there will
// never be more than four extruder steps per call
for (uint32_t dividend = block->steps.e << 1; dividend <= (block->step_event_count >> 2); dividend <<= 1)
block->la_scaling++;
#if ENABLED(LA_DEBUG) #if ENABLED(LA_DEBUG)
if (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * 2 < SQRT(block->nominal_speed_sqr) * block->e_D_ratio) if (block->la_advance_rate >> block->la_scaling > 10000)
SERIAL_ECHOLNPGM("More than 2 steps per eISR loop executed."); SERIAL_ECHOLNPGM("eISR running at > 10kHz: ", block->la_advance_rate);
if (block->advance_speed < 200)
SERIAL_ECHOLNPGM("eISR running at > 10kHz.");
#endif #endif
} }
#endif #endif
+5 -6
View File
@@ -210,11 +210,10 @@ typedef struct block_t {
// Advance extrusion // Advance extrusion
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
bool use_advance_lead; uint32_t la_advance_rate; // The rate at which steps are added whilst accelerating
uint16_t advance_speed, // STEP timer value for extruder speed offset ISR uint8_t la_scaling; // Scale ISR frequency down and step frequency up by 2 ^ la_scaling
max_adv_steps, // max. advance steps to get cruising speed pressure (not always nominal_speed!) uint16_t max_adv_steps, // Max advance steps to get cruising speed pressure
final_adv_steps; // advance steps due to exit speed final_adv_steps; // Advance steps for exit speed pressure
float e_D_ratio;
#endif #endif
uint32_t nominal_rate, // The nominal step rate for this block in step_events/sec uint32_t nominal_rate, // The nominal step rate for this block in step_events/sec
@@ -977,7 +976,7 @@ class Planner
return target_velocity_sqr - 2 * accel * distance; return target_velocity_sqr - 2 * accel * distance;
} }
#if ENABLED(S_CURVE_ACCELERATION) #if EITHER(S_CURVE_ACCELERATION, LIN_ADVANCE)
/** /**
* Calculate the speed reached given initial speed, acceleration and distance * Calculate the speed reached given initial speed, acceleration and distance
*/ */
+179 -168
View File
@@ -215,16 +215,11 @@ uint32_t Stepper::advance_divisor = 0,
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
uint32_t Stepper::nextAdvanceISR = LA_ADV_NEVER, uint32_t Stepper::nextAdvanceISR = LA_ADV_NEVER,
Stepper::LA_isr_rate = LA_ADV_NEVER; Stepper::la_interval = LA_ADV_NEVER;
uint16_t Stepper::LA_current_adv_steps = 0, int32_t Stepper::la_delta_error = 0,
Stepper::LA_final_adv_steps, Stepper::la_dividend = 0,
Stepper::LA_max_adv_steps; Stepper::la_advance_steps = 0;
#endif
int8_t Stepper::LA_steps = 0;
bool Stepper::LA_use_advance_lead;
#endif // LIN_ADVANCE
#if HAS_SHAPING #if HAS_SHAPING
shaping_time_t ShapingQueue::now = 0; shaping_time_t ShapingQueue::now = 0;
@@ -508,29 +503,27 @@ void Stepper::set_directions() {
SET_STEP_DIR(Z); // C SET_STEP_DIR(Z); // C
#endif #endif
#if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER)
#if ENABLED(MIXING_EXTRUDER) // Because this is valid for the whole block we don't know
// Because this is valid for the whole block we don't know // what E steppers will step. Likely all. Set all.
// what e-steppers will step. Likely all. Set all. if (motor_direction(E_AXIS)) {
if (motor_direction(E_AXIS)) { MIXER_STEPPER_LOOP(j) REV_E_DIR(j);
MIXER_STEPPER_LOOP(j) REV_E_DIR(j); count_direction.e = -1;
count_direction.e = -1; }
} else {
else { MIXER_STEPPER_LOOP(j) NORM_E_DIR(j);
MIXER_STEPPER_LOOP(j) NORM_E_DIR(j); count_direction.e = 1;
count_direction.e = 1; }
} #elif HAS_EXTRUDERS
#else if (motor_direction(E_AXIS)) {
if (motor_direction(E_AXIS)) { REV_E_DIR(stepper_extruder);
REV_E_DIR(stepper_extruder); count_direction.e = -1;
count_direction.e = -1; }
} else {
else { NORM_E_DIR(stepper_extruder);
NORM_E_DIR(stepper_extruder); count_direction.e = 1;
count_direction.e = 1; }
} #endif
#endif
#endif // !LIN_ADVANCE
#if HAS_L64XX #if HAS_L64XX
if (L64XX_OK_to_power_up) { // OK to send the direction commands (which powers up the L64XX steppers) if (L64XX_OK_to_power_up) { // OK to send the direction commands (which powers up the L64XX steppers)
@@ -1413,7 +1406,12 @@ void Stepper::isr() {
TERN_(HAS_SHAPING, shaping_isr()); TERN_(HAS_SHAPING, shaping_isr());
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
if (!nextAdvanceISR) nextAdvanceISR = advance_isr(); // 0 = Do Linear Advance E Stepper pulses if (!nextAdvanceISR) { // 0 = Do Linear Advance E Stepper pulses
advance_isr();
nextAdvanceISR = la_interval;
}
else if (nextAdvanceISR == LA_ADV_NEVER) // Start LA steps if necessary
nextAdvanceISR = la_interval;
#endif #endif
#if ENABLED(INTEGRATED_BABYSTEPPING) #if ENABLED(INTEGRATED_BABYSTEPPING)
@@ -1649,7 +1647,7 @@ void Stepper::pulse_phase_isr() {
// Start an active pulse if needed // Start an active pulse if needed
#define PULSE_START(AXIS) do{ \ #define PULSE_START(AXIS) do{ \
if (step_needed[_AXIS(AXIS)]) { \ if (step_needed[_AXIS(AXIS)]) { \
count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \ count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \
_APPLY_STEP(AXIS, !_INVERT_STEP_PIN(AXIS), 0); \ _APPLY_STEP(AXIS, !_INVERT_STEP_PIN(AXIS), 0); \
} \ } \
}while(0) }while(0)
@@ -1789,20 +1787,17 @@ void Stepper::pulse_phase_isr() {
PULSE_PREP(Z); PULSE_PREP(Z);
#endif #endif
#if EITHER(LIN_ADVANCE, MIXING_EXTRUDER) #if EITHER(HAS_E0_STEP, MIXING_EXTRUDER)
delta_error.e += advance_dividend.e;
if (delta_error.e >= 0) {
#if ENABLED(LIN_ADVANCE)
delta_error.e -= advance_divisor;
// Don't step E here - But remember the number of steps to perform
motor_direction(E_AXIS) ? --LA_steps : ++LA_steps;
#else
count_position.e += count_direction.e;
step_needed.e = true;
#endif
}
#elif HAS_E0_STEP
PULSE_PREP(E); PULSE_PREP(E);
#if ENABLED(LIN_ADVANCE)
if (step_needed.e && current_block->la_advance_rate) {
// don't actually step here, but do subtract movements steps
// from the linear advance step count
step_needed.e = false;
count_position.e -= count_direction.e;
la_advance_steps--;
}
#endif
#endif #endif
#if HAS_SHAPING #if HAS_SHAPING
@@ -1842,12 +1837,10 @@ void Stepper::pulse_phase_isr() {
PULSE_START(Z); PULSE_START(Z);
#endif #endif
#if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER)
#if ENABLED(MIXING_EXTRUDER) if (step_needed.e) E_STEP_WRITE(mixer.get_next_stepper(), !INVERT_E_STEP_PIN);
if (step_needed.e) E_STEP_WRITE(mixer.get_next_stepper(), !INVERT_E_STEP_PIN); #elif HAS_E0_STEP
#elif HAS_E0_STEP PULSE_START(E);
PULSE_START(E);
#endif
#endif #endif
#if ENABLED(I2S_STEPPER_STREAM) #if ENABLED(I2S_STEPPER_STREAM)
@@ -1871,15 +1864,10 @@ void Stepper::pulse_phase_isr() {
PULSE_STOP(Z); PULSE_STOP(Z);
#endif #endif
#if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER)
#if ENABLED(MIXING_EXTRUDER) if (step_needed.e) E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN);
if (delta_error.e >= 0) { #elif HAS_E0_STEP
delta_error.e -= advance_divisor; PULSE_STOP(E);
E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN);
}
#elif HAS_E0_STEP
PULSE_STOP(E);
#endif
#endif #endif
#if ISR_MULTI_STEPS #if ISR_MULTI_STEPS
@@ -1945,6 +1933,70 @@ void Stepper::pulse_phase_isr() {
// properly schedules blocks from the planner. This is executed after creating // properly schedules blocks from the planner. This is executed after creating
// the step pulses, so it is not time critical, as pulses are already done. // the step pulses, so it is not time critical, as pulses are already done.
// Calculate timer interval, with all limits applied.
uint32_t Stepper::calc_timer_interval(uint32_t step_rate) {
#ifdef CPU_32_BIT
// In case of high-performance processor, it is able to calculate in real-time
return uint32_t(STEPPER_TIMER_RATE) / step_rate;
#else
// AVR is able to keep up at 30khz Stepping ISR rate.
constexpr uint32_t min_step_rate = (F_CPU) / 500000U;
if (step_rate <= min_step_rate) {
step_rate = 0;
uintptr_t table_address = (uintptr_t)&speed_lookuptable_slow[0][0];
return uint16_t(pgm_read_word(table_address));
}
else {
step_rate -= min_step_rate; // Correct for minimal speed
if (step_rate >= 0x0800) { // higher step rate
const uint8_t rate_mod_256 = (step_rate & 0x00FF);
const uintptr_t table_address = uintptr_t(&speed_lookuptable_fast[uint8_t(step_rate >> 8)][0]),
gain = uint16_t(pgm_read_word(table_address + 2));
return uint16_t(pgm_read_word(table_address)) - MultiU16X8toH16(rate_mod_256, gain);
}
else { // lower step rates
uintptr_t table_address = uintptr_t(&speed_lookuptable_slow[0][0]);
table_address += (step_rate >> 1) & 0xFFFC;
return uint16_t(pgm_read_word(table_address))
- ((uint16_t(pgm_read_word(table_address + 2)) * uint8_t(step_rate & 0x0007)) >> 3);
}
}
#endif
}
// Get the timer interval and the number of loops to perform per tick
uint32_t Stepper::calc_timer_interval(uint32_t step_rate, uint8_t &loops) {
uint8_t multistep = 1;
#if DISABLED(DISABLE_MULTI_STEPPING)
// The stepping frequency limits for each multistepping rate
static const uint32_t limit[] PROGMEM = {
( MAX_STEP_ISR_FREQUENCY_1X ),
( MAX_STEP_ISR_FREQUENCY_2X >> 1),
( MAX_STEP_ISR_FREQUENCY_4X >> 2),
( MAX_STEP_ISR_FREQUENCY_8X >> 3),
( MAX_STEP_ISR_FREQUENCY_16X >> 4),
( MAX_STEP_ISR_FREQUENCY_32X >> 5),
( MAX_STEP_ISR_FREQUENCY_64X >> 6),
(MAX_STEP_ISR_FREQUENCY_128X >> 7)
};
// Select the proper multistepping
uint8_t idx = 0;
while (idx < 7 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) {
step_rate >>= 1;
multistep <<= 1;
++idx;
};
#else
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
#endif
loops = multistep;
return calc_timer_interval(step_rate);
}
uint32_t Stepper::block_phase_isr() { uint32_t Stepper::block_phase_isr() {
// If no queued movements, just wait 1ms for the next block // If no queued movements, just wait 1ms for the next block
@@ -1993,15 +2045,14 @@ uint32_t Stepper::block_phase_isr() {
// acc_step_rate is in steps/second // acc_step_rate is in steps/second
// step_rate to timer interval and steps per stepper isr // step_rate to timer interval and steps per stepper isr
interval = calc_timer_interval(acc_step_rate, &steps_per_isr); interval = calc_timer_interval(acc_step_rate << oversampling_factor, steps_per_isr);
acceleration_time += interval; acceleration_time += interval;
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
if (LA_use_advance_lead) { if (current_block->la_advance_rate) {
// Fire ISR if final adv_rate is reached const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
if (LA_steps && LA_isr_rate != current_block->advance_speed) nextAdvanceISR = 0; la_interval = calc_timer_interval(acc_step_rate + la_step_rate) << current_block->la_scaling;
} }
else if (LA_steps) nextAdvanceISR = 0;
#endif #endif
// Update laser - Accelerating // Update laser - Accelerating
@@ -2067,18 +2118,41 @@ uint32_t Stepper::block_phase_isr() {
// step_rate is in steps/second // step_rate is in steps/second
// step_rate to timer interval and steps per stepper isr // step_rate to timer interval and steps per stepper isr
interval = calc_timer_interval(step_rate, &steps_per_isr); interval = calc_timer_interval(step_rate << oversampling_factor, steps_per_isr);
deceleration_time += interval; deceleration_time += interval;
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
if (LA_use_advance_lead) { if (current_block->la_advance_rate) {
// Wake up eISR on first deceleration loop and fire ISR if final adv_rate is reached const uint32_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0;
if (step_events_completed <= decelerate_after + steps_per_isr || (LA_steps && LA_isr_rate != current_block->advance_speed)) { if (la_step_rate != step_rate) {
initiateLA(); bool reverse_e = la_step_rate > step_rate;
LA_isr_rate = current_block->advance_speed; la_interval = calc_timer_interval(reverse_e ? la_step_rate - step_rate : step_rate - la_step_rate) << current_block->la_scaling;
if (reverse_e != motor_direction(E_AXIS)) {
TBI(last_direction_bits, E_AXIS);
count_direction.e = -count_direction.e;
DIR_WAIT_BEFORE();
if (reverse_e) {
#if ENABLED(MIXING_EXTRUDER)
MIXER_STEPPER_LOOP(j) REV_E_DIR(j);
#else
REV_E_DIR(stepper_extruder);
#endif
}
else {
#if ENABLED(MIXING_EXTRUDER)
MIXER_STEPPER_LOOP(j) NORM_E_DIR(j);
#else
NORM_E_DIR(stepper_extruder);
#endif
}
DIR_WAIT_AFTER();
}
} }
} }
else if (LA_steps) nextAdvanceISR = 0;
#endif // LIN_ADVANCE #endif // LIN_ADVANCE
// Update laser - Decelerating // Update laser - Decelerating
@@ -2112,16 +2186,15 @@ uint32_t Stepper::block_phase_isr() {
} }
// Must be in cruise phase otherwise // Must be in cruise phase otherwise
else { else {
#if ENABLED(LIN_ADVANCE)
// If there are any esteps, fire the next advance_isr "now"
if (LA_steps && LA_isr_rate != current_block->advance_speed) initiateLA();
#endif
// Calculate the ticks_nominal for this nominal speed, if not done yet // Calculate the ticks_nominal for this nominal speed, if not done yet
if (ticks_nominal < 0) { if (ticks_nominal < 0) {
// step_rate to timer interval and loops for the nominal speed // step_rate to timer interval and loops for the nominal speed
ticks_nominal = calc_timer_interval(current_block->nominal_rate, &steps_per_isr); ticks_nominal = calc_timer_interval(current_block->nominal_rate << oversampling_factor, steps_per_isr);
#if ENABLED(LIN_ADVANCE)
if (current_block->la_advance_rate)
la_interval = calc_timer_interval(current_block->nominal_rate) << current_block->la_scaling;
#endif
} }
// The timer interval is just the nominal value for the nominal speed // The timer interval is just the nominal value for the nominal speed
@@ -2291,7 +2364,7 @@ uint32_t Stepper::block_phase_isr() {
step_event_count = current_block->step_event_count << oversampling; step_event_count = current_block->step_event_count << oversampling;
// Initialize Bresenham delta errors to 1/2 // Initialize Bresenham delta errors to 1/2
delta_error = -int32_t(step_event_count); delta_error = TERN_(LIN_ADVANCE, la_delta_error =) -int32_t(step_event_count);
// Calculate Bresenham dividends and divisors // Calculate Bresenham dividends and divisors
advance_dividend = current_block->steps << 1; advance_dividend = current_block->steps << 1;
@@ -2335,16 +2408,13 @@ uint32_t Stepper::block_phase_isr() {
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
#if DISABLED(MIXING_EXTRUDER) && E_STEPPERS > 1 #if DISABLED(MIXING_EXTRUDER) && E_STEPPERS > 1
// If the now active extruder wasn't in use during the last move, its pressure is most likely gone. // If the now active extruder wasn't in use during the last move, its pressure is most likely gone.
if (stepper_extruder != last_moved_extruder) LA_current_adv_steps = 0; if (stepper_extruder != last_moved_extruder) la_advance_steps = 0;
#endif #endif
if ((LA_use_advance_lead = current_block->use_advance_lead)) { if (current_block->la_advance_rate) {
LA_final_adv_steps = current_block->final_adv_steps; // apply LA scaling and discount the effect of frequency scaling
LA_max_adv_steps = current_block->max_adv_steps; la_dividend = (advance_dividend.e << current_block->la_scaling) << oversampling;
initiateLA(); // Start the ISR
LA_isr_rate = current_block->advance_speed;
} }
else LA_isr_rate = LA_ADV_NEVER;
#endif #endif
if ( ENABLED(HAS_L64XX) // Always set direction for L64xx (Also enables the chips) if ( ENABLED(HAS_L64XX) // Always set direction for L64xx (Also enables the chips)
@@ -2418,7 +2488,15 @@ uint32_t Stepper::block_phase_isr() {
#endif #endif
// Calculate the initial timer interval // Calculate the initial timer interval
interval = calc_timer_interval(current_block->initial_rate, &steps_per_isr); interval = calc_timer_interval(current_block->initial_rate << oversampling_factor, steps_per_isr);
acceleration_time += interval;
#if ENABLED(LIN_ADVANCE)
if (current_block->la_advance_rate) {
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
la_interval = calc_timer_interval(current_block->initial_rate + la_step_rate) << current_block->la_scaling;
}
#endif
} }
#if ENABLED(LASER_POWER_INLINE_CONTINUOUS) #if ENABLED(LASER_POWER_INLINE_CONTINUOUS)
else { // No new block found; so apply inline laser parameters else { // No new block found; so apply inline laser parameters
@@ -2444,71 +2522,16 @@ uint32_t Stepper::block_phase_isr() {
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
// Timer interrupt for E. LA_steps is set in the main routine // Timer interrupt for E. LA_steps is set in the main routine
uint32_t Stepper::advance_isr() { void Stepper::advance_isr() {
uint32_t interval; // Apply Bresenham algorithm so that linear advance can piggy back on
// the acceleration and speed values calculated in block_phase_isr().
if (LA_use_advance_lead) { // This helps keep LA in sync with, for example, S_CURVE_ACCELERATION.
if (step_events_completed > decelerate_after && LA_current_adv_steps > LA_final_adv_steps) { la_delta_error += la_dividend;
LA_steps--; if (la_delta_error >= 0) {
LA_current_adv_steps--;
interval = LA_isr_rate;
}
else if (step_events_completed < decelerate_after && LA_current_adv_steps < LA_max_adv_steps) {
LA_steps++;
LA_current_adv_steps++;
interval = LA_isr_rate;
}
else
interval = LA_isr_rate = LA_ADV_NEVER;
}
else
interval = LA_ADV_NEVER;
if (!LA_steps) return interval; // Leave pins alone if there are no steps!
DIR_WAIT_BEFORE();
#if ENABLED(MIXING_EXTRUDER)
// We don't know which steppers will be stepped because LA loop follows,
// with potentially multiple steps. Set all.
if (LA_steps > 0) {
MIXER_STEPPER_LOOP(j) NORM_E_DIR(j);
count_direction.e = 1;
}
else if (LA_steps < 0) {
MIXER_STEPPER_LOOP(j) REV_E_DIR(j);
count_direction.e = -1;
}
#else
if (LA_steps > 0) {
NORM_E_DIR(stepper_extruder);
count_direction.e = 1;
}
else if (LA_steps < 0) {
REV_E_DIR(stepper_extruder);
count_direction.e = -1;
}
#endif
DIR_WAIT_AFTER();
//const hal_timer_t added_step_ticks = hal_timer_t(ADDED_STEP_TICKS);
// Step E stepper if we have steps
#if ISR_MULTI_STEPS
bool firstStep = true;
USING_TIMED_PULSE();
#endif
while (LA_steps) {
#if ISR_MULTI_STEPS
if (firstStep)
firstStep = false;
else
AWAIT_LOW_PULSE();
#endif
count_position.e += count_direction.e; count_position.e += count_direction.e;
la_advance_steps += count_direction.e;
la_delta_error -= advance_divisor;
// Set the STEP pulse ON // Set the STEP pulse ON
#if ENABLED(MIXING_EXTRUDER) #if ENABLED(MIXING_EXTRUDER)
@@ -2519,12 +2542,8 @@ uint32_t Stepper::block_phase_isr() {
// Enforce a minimum duration for STEP pulse ON // Enforce a minimum duration for STEP pulse ON
#if ISR_PULSE_CONTROL #if ISR_PULSE_CONTROL
USING_TIMED_PULSE();
START_HIGH_PULSE(); START_HIGH_PULSE();
#endif
LA_steps < 0 ? ++LA_steps : --LA_steps;
#if ISR_PULSE_CONTROL
AWAIT_HIGH_PULSE(); AWAIT_HIGH_PULSE();
#endif #endif
@@ -2534,15 +2553,7 @@ uint32_t Stepper::block_phase_isr() {
#else #else
E_STEP_WRITE(stepper_extruder, INVERT_E_STEP_PIN); E_STEP_WRITE(stepper_extruder, INVERT_E_STEP_PIN);
#endif #endif
}
// For minimum pulse time wait before looping
// Just wait for the requested pulse duration
#if ISR_PULSE_CONTROL
if (LA_steps) START_LOW_PULSE();
#endif
} // LA_steps
return interval;
} }
#endif // LIN_ADVANCE #endif // LIN_ADVANCE
+10 -65
View File
@@ -485,10 +485,11 @@ class Stepper {
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
static constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF; static constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF;
static uint32_t nextAdvanceISR, LA_isr_rate; static uint32_t nextAdvanceISR,
static uint16_t LA_current_adv_steps, LA_final_adv_steps, LA_max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early". la_interval; // Interval between ISR calls for LA
static int8_t LA_steps; static int32_t la_delta_error, // Analogue of delta_error.e for E steps in LA ISR
static bool LA_use_advance_lead; la_dividend, // Analogue of advance_dividend.e for E steps in LA ISR
la_advance_steps; // Count of steps added to increase nozzle pressure
#endif #endif
#if ENABLED(INTEGRATED_BABYSTEPPING) #if ENABLED(INTEGRATED_BABYSTEPPING)
@@ -566,8 +567,7 @@ class Stepper {
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
// The Linear advance ISR phase // The Linear advance ISR phase
static uint32_t advance_isr(); static void advance_isr();
FORCE_INLINE static void initiateLA() { nextAdvanceISR = 0; }
#endif #endif
#if ENABLED(INTEGRATED_BABYSTEPPING) #if ENABLED(INTEGRATED_BABYSTEPPING)
@@ -619,6 +619,7 @@ class Stepper {
current_block = nullptr; current_block = nullptr;
axis_did_move = 0; axis_did_move = 0;
planner.release_current_block(); planner.release_current_block();
TERN_(LIN_ADVANCE, la_interval = nextAdvanceISR = LA_ADV_NEVER);
} }
// Quickly stop all steppers // Quickly stop all steppers
@@ -709,65 +710,9 @@ class Stepper {
static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e); static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
FORCE_INLINE static void _set_position(const abce_long_t &spos) { _set_position(spos.a, spos.b, spos.c, spos.e); } FORCE_INLINE static void _set_position(const abce_long_t &spos) { _set_position(spos.a, spos.b, spos.c, spos.e); }
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t *loops) { // Calculate timing interval for the given step rate
uint32_t timer; static uint32_t calc_timer_interval(uint32_t step_rate);
static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t &loops);
// Scale the frequency, as requested by the caller
step_rate <<= oversampling_factor;
uint8_t multistep = 1;
#if DISABLED(DISABLE_MULTI_STEPPING)
// The stepping frequency limits for each multistepping rate
static const uint32_t limit[] PROGMEM = {
( MAX_STEP_ISR_FREQUENCY_1X ),
( MAX_STEP_ISR_FREQUENCY_2X >> 1),
( MAX_STEP_ISR_FREQUENCY_4X >> 2),
( MAX_STEP_ISR_FREQUENCY_8X >> 3),
( MAX_STEP_ISR_FREQUENCY_16X >> 4),
( MAX_STEP_ISR_FREQUENCY_32X >> 5),
( MAX_STEP_ISR_FREQUENCY_64X >> 6),
(MAX_STEP_ISR_FREQUENCY_128X >> 7)
};
// Select the proper multistepping
uint8_t idx = 0;
while (idx < 7 && step_rate > (uint32_t)pgm_read_dword(&limit[idx])) {
step_rate >>= 1;
multistep <<= 1;
++idx;
};
#else
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
#endif
*loops = multistep;
#ifdef CPU_32_BIT
// In case of high-performance processor, it is able to calculate in real-time
timer = uint32_t(STEPPER_TIMER_RATE) / step_rate;
#else
constexpr uint32_t min_step_rate = (F_CPU) / 500000U;
NOLESS(step_rate, min_step_rate);
step_rate -= min_step_rate; // Correct for minimal speed
if (step_rate >= (8 * 256)) { // higher step rate
const uint8_t tmp_step_rate = (step_rate & 0x00FF);
const uint16_t table_address = (uint16_t)&speed_lookuptable_fast[(uint8_t)(step_rate >> 8)][0],
gain = (uint16_t)pgm_read_word(table_address + 2);
timer = MultiU16X8toH16(tmp_step_rate, gain);
timer = (uint16_t)pgm_read_word(table_address) - timer;
}
else { // lower step rates
uint16_t table_address = (uint16_t)&speed_lookuptable_slow[0][0];
table_address += ((step_rate) >> 1) & 0xFFFC;
timer = (uint16_t)pgm_read_word(table_address)
- (((uint16_t)pgm_read_word(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3);
}
// (there is no need to limit the timer value here. All limits have been
// applied above, and AVR is able to keep up at 30khz Stepping ISR rate)
#endif
return timer;
}
#if ENABLED(S_CURVE_ACCELERATION) #if ENABLED(S_CURVE_ACCELERATION)
static void _calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av); static void _calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av);