Nonlinear Extrusion Control (M592) (#26127)

This commit is contained in:
Andrew Bortz
2023-10-10 20:24:48 -07:00
committed by GitHub
parent 6d301a282e
commit e9b9d634c4
12 changed files with 190 additions and 8 deletions

View File

@@ -245,6 +245,13 @@ uint32_t Stepper::advance_divisor = 0,
bool Stepper::la_active = false;
#endif
#if ENABLED(NONLINEAR_EXTRUSION)
ne_coeff_t Stepper::ne;
ne_fix_t Stepper::ne_fix;
int32_t Stepper::ne_edividend;
uint32_t Stepper::ne_scale;
#endif
#if HAS_ZV_SHAPING
shaping_time_t ShapingQueue::now = 0;
#if ANY(MCU_LPC1768, MCU_LPC1769) && DISABLED(NO_LPC_ETHERNET_BUFFER)
@@ -2191,6 +2198,16 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
#endif // !CPU_32_BIT
}
#if ENABLED(NONLINEAR_EXTRUSION)
void Stepper::calc_nonlinear_e(uint32_t step_rate) {
const uint32_t velocity = ne_scale * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
int32_t vd = (((int64_t)ne_fix.A * velocity) >> 24) + (((((int64_t)ne_fix.B * velocity) >> 24) * velocity) >> 24);
NOLESS(vd, 0);
advance_dividend.e = (uint64_t(ne_fix.C + vd) * ne_edividend) >> 24;
}
#endif
// Get the timer interval and the number of loops to perform per tick
hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) {
@@ -2318,6 +2335,10 @@ hal_timer_t Stepper::block_phase_isr() {
interval = calc_multistep_timer_interval(acc_step_rate << oversampling_factor);
acceleration_time += interval;
#if ENABLED(NONLINEAR_EXTRUSION)
calc_nonlinear_e(acc_step_rate << oversampling_factor);
#endif
#if ENABLED(LIN_ADVANCE)
if (la_active) {
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
@@ -2388,6 +2409,10 @@ hal_timer_t Stepper::block_phase_isr() {
interval = calc_multistep_timer_interval(step_rate << oversampling_factor);
deceleration_time += interval;
#if ENABLED(NONLINEAR_EXTRUSION)
calc_nonlinear_e(step_rate << oversampling_factor);
#endif
#if ENABLED(LIN_ADVANCE)
if (la_active) {
const uint32_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0;
@@ -2436,6 +2461,10 @@ hal_timer_t Stepper::block_phase_isr() {
// step_rate to timer interval and loops for the nominal speed
ticks_nominal = calc_multistep_timer_interval(current_block->nominal_rate << oversampling_factor);
#if ENABLED(NONLINEAR_EXTRUSION)
calc_nonlinear_e(current_block->nominal_rate << oversampling_factor);
#endif
#if ENABLED(LIN_ADVANCE)
if (la_active)
la_interval = calc_timer_interval(current_block->nominal_rate >> current_block->la_scaling);
@@ -2636,10 +2665,13 @@ hal_timer_t Stepper::block_phase_isr() {
acceleration_time = deceleration_time = 0;
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
oversampling_factor = 0; // Assume no axis smoothing (via oversampling)
// Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate
// Otherwise assume no axis smoothing (via oversampling)
oversampling_factor = TERN(NONLINEAR_EXTRUSION, 1, 0);
// Decide if axis smoothing is possible
uint32_t max_rate = current_block->nominal_rate; // Get the step event rate
if (TERN1(DWIN_LCD_PROUI, hmiData.adaptiveStepSmoothing)) {
uint32_t max_rate = current_block->nominal_rate; // Get the step event rate
while (max_rate < MIN_STEP_ISR_FREQUENCY) { // As long as more ISRs are possible...
max_rate <<= 1; // Try to double the rate
if (max_rate < MIN_STEP_ISR_FREQUENCY) // Don't exceed the estimated ISR limit
@@ -2755,10 +2787,29 @@ hal_timer_t Stepper::block_phase_isr() {
acc_step_rate = current_block->initial_rate;
#endif
#if ENABLED(NONLINEAR_EXTRUSION)
ne_edividend = advance_dividend.e;
const float scale = (float(ne_edividend) / advance_divisor) * planner.mm_per_step[E_AXIS_N(current_block->extruder)];
ne_scale = (1L << 24) * scale;
if (current_block->direction_bits.e) {
ne_fix.A = (1L << 24) * ne.A;
ne_fix.B = (1L << 24) * ne.B;
ne_fix.C = (1L << 24) * ne.C;
}
else {
ne_fix.A = ne_fix.B = 0;
ne_fix.C = (1L << 24);
}
#endif
// Calculate the initial timer interval
interval = calc_multistep_timer_interval(current_block->initial_rate << oversampling_factor);
acceleration_time += interval;
#if ENABLED(NONLINEAR_EXTRUSION)
calc_nonlinear_e(current_block->initial_rate << oversampling_factor);
#endif
#if ENABLED(LIN_ADVANCE)
if (la_active) {
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;