NONLINEAR_EXTRUSION_DEFAULT_ON (#27819)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
Vovodroid 2025-05-31 06:53:21 +03:00 committed by GitHub
parent e8f2430dac
commit a6bfdf351f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 83 additions and 55 deletions

View file

@ -2384,6 +2384,9 @@
* For better results also enable ADAPTIVE_STEP_SMOOTHING.
*/
//#define NONLINEAR_EXTRUSION
#if ENABLED(NONLINEAR_EXTRUSION)
//#define NONLINEAR_EXTRUSION_DEFAULT_ON // Enable if NLE should be ON by default
#endif
// @section leveling

View file

@ -30,11 +30,13 @@
void GcodeSuite::M592_report(const bool forReplay/*=true*/) {
TERN_(MARLIN_SMALL_BUILD, return);
report_heading_etc(forReplay, F(STR_NONLINEAR_EXTRUSION));
SERIAL_ECHOLNPGM(" M592 A", stepper.ne.A, " B", stepper.ne.B, " C", stepper.ne.C);
const nonlinear_settings_t &sns = stepper.ne.settings;
SERIAL_ECHOLNPGM(" M592 S", sns.enabled, " A", sns.coeff.A, " B", sns.coeff.B, " C", sns.coeff.C);
}
/**
* M592: Get or set nonlinear extrusion parameters
* S<flag> Enable / Disable Nonlinear Extrusion
* A<factor> Quadratic coefficient (default 0.0)
* B<factor> Linear coefficient (default 0.0)
* C<factor> Constant coefficient (default 1.0)
@ -46,14 +48,18 @@ void GcodeSuite::M592_report(const bool forReplay/*=true*/) {
void GcodeSuite::M592() {
if (!parser.seen_any()) return M592_report();
if (parser.seenval('A')) stepper.ne.A = parser.value_float();
if (parser.seenval('B')) stepper.ne.B = parser.value_float();
if (parser.seenval('C')) stepper.ne.C = parser.value_float();
nonlinear_t &ne = stepper.ne;
nonlinear_settings_t &sns = ne.settings;
if (parser.seen('S')) sns.enabled = parser.value_bool();
if (parser.seenval('A')) sns.coeff.A = parser.value_float();
if (parser.seenval('B')) sns.coeff.B = parser.value_float();
if (parser.seenval('C')) sns.coeff.C = parser.value_float();
#if ENABLED(SMOOTH_LIN_ADVANCE)
stepper.ne_q30.A = _BV32(30) * (stepper.ne.A * planner.mm_per_step[E_AXIS_N(0)] * planner.mm_per_step[E_AXIS_N(0)]);
stepper.ne_q30.B = _BV32(30) * (stepper.ne.B * planner.mm_per_step[E_AXIS_N(0)]);
stepper.ne_q30.C = _BV32(30) * stepper.ne.C;
ne.q30.A = _BV32(30) * (sns.coeff.A * planner.mm_per_step[E_AXIS_N(0)] * planner.mm_per_step[E_AXIS_N(0)]);
ne.q30.B = _BV32(30) * (sns.coeff.B * planner.mm_per_step[E_AXIS_N(0)]);
ne.q30.C = _BV32(30) * sns.coeff.C;
#endif
}

View file

@ -509,6 +509,7 @@ namespace LanguageNarrow_en {
LSTR MSG_ADVANCE_TAU = _UxGT("Advance Tau");
LSTR MSG_ADVANCE_K_E = _UxGT("Advance K *");
LSTR MSG_ADVANCE_TAU_E = _UxGT("Advance Tau *");
LSTR MSG_NLE_ON = _UxGT("NLE enabled");
LSTR MSG_CONTRAST = _UxGT("LCD Contrast");
LSTR MSG_BRIGHTNESS = _UxGT("LCD Brightness");
LSTR MSG_SCREEN_TIMEOUT = _UxGT("LCD Timeout (m)");

View file

@ -138,6 +138,10 @@ void menu_backlash();
#endif
#endif // LIN_ADVANCE
#if ENABLED(NONLINEAR_EXTRUSION)
EDIT_ITEM(bool, MSG_NLE_ON, &stepper.ne.settings.enabled);
#endif
#if DISABLED(NO_VOLUMETRICS)
EDIT_ITEM(bool, MSG_VOLUMETRIC_ENABLED, &parser.volumetric_enabled, planner.calculate_volumetric_multipliers);

View file

@ -237,6 +237,13 @@ void menu_tune() {
#endif
#endif
//
// Nonlinear Extrusion state
//
#if ENABLED(NONLINEAR_EXTRUSION)
EDIT_ITEM(bool, MSG_NLE_ON, &stepper.ne.settings.enabled);
#endif
//
// Babystep X:
// Babystep Y:

View file

@ -3255,8 +3255,8 @@ void Planner::refresh_positioning() {
#if ENABLED(EDITABLE_STEPS_PER_UNIT)
LOOP_DISTINCT_AXES(i) mm_per_step[i] = 1.0f / settings.axis_steps_per_mm[i];
#if ALL(NONLINEAR_EXTRUSION, SMOOTH_LIN_ADVANCE)
stepper.ne_q30.A = _BV32(30) * (stepper.ne.A * mm_per_step[E_AXIS_N(0)] * mm_per_step[E_AXIS_N(0)]);
stepper.ne_q30.B = _BV32(30) * (stepper.ne.B * mm_per_step[E_AXIS_N(0)]);
stepper.ne.q30.A = _BV32(30) * (stepper.ne.settings.coeff.A * mm_per_step[E_AXIS_N(0)] * mm_per_step[E_AXIS_N(0)]);
stepper.ne.q30.B = _BV32(30) * (stepper.ne.settings.coeff.B * mm_per_step[E_AXIS_N(0)]);
#endif
#endif
set_position_mm(current_position);

View file

@ -685,7 +685,7 @@ typedef struct SettingsDataStruct {
// Nonlinear Extrusion
//
#if ENABLED(NONLINEAR_EXTRUSION)
ne_coeff_t stepper_ne; // M592 A B C
nonlinear_settings_t stepper_ne_settings; // M592 S A B C
#endif
//
@ -1798,7 +1798,7 @@ void MarlinSettings::postprocess() {
// Nonlinear Extrusion
//
#if ENABLED(NONLINEAR_EXTRUSION)
EEPROM_WRITE(stepper.ne);
EEPROM_WRITE(stepper.ne.settings);
#endif
//
@ -2933,7 +2933,7 @@ void MarlinSettings::postprocess() {
// Nonlinear Extrusion
//
#if ENABLED(NONLINEAR_EXTRUSION)
EEPROM_READ(stepper.ne);
EEPROM_READ(stepper.ne.settings);
#endif
//
@ -3747,7 +3747,7 @@ void MarlinSettings::reset() {
//
// Nonlinear Extrusion
//
TERN_(NONLINEAR_EXTRUSION, stepper.ne.reset());
TERN_(NONLINEAR_EXTRUSION, stepper.ne.settings.reset());
//
// Input Shaping

View file

@ -256,17 +256,7 @@ uint32_t Stepper::advance_divisor = 0,
#endif
#if ENABLED(NONLINEAR_EXTRUSION)
ne_coeff_t Stepper::ne;
#if NONLINEAR_EXTRUSION_Q24
ne_q24_t Stepper::ne_q24;
#else
ne_q30_t Stepper::ne_q30;
#endif
// private:
#if NONLINEAR_EXTRUSION_Q24
int32_t Stepper::ne_edividend;
uint32_t Stepper::ne_scale_q24;
#endif
nonlinear_t Stepper::ne; // Initialized by settings.load
#endif
#if HAS_ZV_SHAPING
@ -2247,11 +2237,11 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
#if NONLINEAR_EXTRUSION_Q24
void Stepper::calc_nonlinear_e(const uint32_t step_rate) {
const uint32_t velocity_q24 = ne_scale_q24 * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
int32_t vd_q24 = (((((int64_t)ne_q24.A * velocity_q24) >> 24) * velocity_q24) >> 24) + (((int64_t)ne_q24.B * velocity_q24) >> 24);
const uint32_t velocity_q24 = ne.scale_q24 * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
int32_t vd_q24 = ((((int64_t(ne.q24.A) * velocity_q24) >> 24) * velocity_q24) >> 24) + ((int64_t(ne.q24.B) * velocity_q24) >> 24);
NOLESS(vd_q24, 0);
advance_dividend.e = (uint64_t(ne_q24.C + vd_q24) * ne_edividend) >> 24;
advance_dividend.e = (uint64_t(ne.q24.C + vd_q24) * ne.edividend) >> 24;
}
#endif
@ -2834,18 +2824,19 @@ hal_timer_t Stepper::block_phase_isr() {
acc_step_rate = current_block->initial_rate;
#endif
// Calculate Nonlinear Extrusion fixed-point quotients
#if NONLINEAR_EXTRUSION_Q24
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_q24 = _BV32(24) * scale;
if (current_block->direction_bits.e && ANY_AXIS_MOVES(current_block)) {
ne_q24.A = _BV32(24) * ne.A;
ne_q24.B = _BV32(24) * ne.B;
ne_q24.C = _BV32(24) * ne.C;
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_q24 = _BV32(24) * scale;
if (ne.settings.enabled && current_block->direction_bits.e && ANY_AXIS_MOVES(current_block)) {
ne.q24.A = _BV32(24) * ne.settings.coeff.A;
ne.q24.B = _BV32(24) * ne.settings.coeff.B;
ne.q24.C = _BV32(24) * ne.settings.coeff.C;
}
else {
ne_q24.A = ne_q24.B = 0;
ne_q24.C = _BV32(24);
ne.q24.A = ne.q24.B = 0;
ne.q24.C = _BV32(24);
}
#endif
@ -2891,9 +2882,9 @@ hal_timer_t Stepper::block_phase_isr() {
#if ENABLED(NONLINEAR_EXTRUSION)
if (forward_e && ANY_AXIS_MOVES(current_block)) {
// Maximum polynomial value is just above 1, like 1.05..1.2, less than 2 anyway, so we can use 30 bits for fractional part
int32_t vd_q30 = ne_q30.A*step_rate*step_rate + ne_q30.B*step_rate;
int32_t vd_q30 = ne.q30.A * sq(step_rate) + ne.q30.B * step_rate;
NOLESS(vd_q30, 0);
step_rate = (int64_t(step_rate) * (ne_q30.C + vd_q30)) >> 30;
step_rate = (int64_t(step_rate) * (ne.q30.C + vd_q30)) >> 30;
}
#endif

View file

@ -283,15 +283,41 @@ constexpr ena_mask_t enable_overlap[] = {
#endif // HAS_ZV_SHAPING
//
// NonLinear Extrusion data
//
#if ENABLED(NONLINEAR_EXTRUSION)
typedef struct { float A, B, C; void reset() { A = B = 0.0f; C = 1.0f; } } ne_coeff_t;
#if DISABLED(SMOOTH_LIN_ADVANCE)
#define NONLINEAR_EXTRUSION_Q24 1
typedef struct { int32_t A, B, C; } ne_q24_t;
#else
typedef struct { int32_t A, B, C; } ne_q30_t;
#endif
#endif
typedef struct {
bool enabled;
struct {
float A, B, C;
void reset() { A = B = 0.0f; C = 1.0f; }
} coeff;
void reset() {
enabled = ENABLED(NONLINEAR_EXTRUSION_DEFAULT_ON);
coeff.reset();
}
} nonlinear_settings_t;
typedef struct {
nonlinear_settings_t settings;
union {
struct { int32_t A, B, C; } q24;
struct { int32_t A, B, C; } q30;
};
#if NONLINEAR_EXTRUSION_Q24
protected:
int32_t edividend;
uint32_t scale_q24;
#endif
} nonlinear_t;
#endif // NONLINEAR_EXTRUSION
//
// Stepper class definition
@ -347,12 +373,7 @@ class Stepper {
#endif
#if ENABLED(NONLINEAR_EXTRUSION)
static ne_coeff_t ne;
#if NONLINEAR_EXTRUSION_Q24
static ne_q24_t ne_q24;
#else
static ne_q30_t ne_q30;
#endif
static nonlinear_t ne;
#endif
#if ENABLED(ADAPTIVE_STEP_SMOOTHING_TOGGLE)
@ -477,11 +498,6 @@ class Stepper {
#endif
#endif
#if NONLINEAR_EXTRUSION_Q24
static int32_t ne_edividend;
static uint32_t ne_scale_q24;
#endif
#if ENABLED(BABYSTEPPING)
static constexpr hal_timer_t BABYSTEP_NEVER = HAL_TIMER_TYPE_MAX;
static hal_timer_t nextBabystepISR;

View file

@ -15,5 +15,5 @@ opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \
X_CURRENT_HOME X_CURRENT/2 Y_CURRENT_HOME Y_CURRENT/2 Z_CURRENT_HOME Y_CURRENT/2
opt_enable CR10_STOCKDISPLAY PINS_DEBUGGING Z_IDLE_HEIGHT EDITABLE_HOMING_CURRENT \
FT_MOTION FT_MOTION_MENU BIQU_MICROPROBE_V1 PROBE_ENABLE_DISABLE Z_SAFE_HOMING AUTO_BED_LEVELING_BILINEAR \
ADAPTIVE_STEP_SMOOTHING NONLINEAR_EXTRUSION
ADAPTIVE_STEP_SMOOTHING LIN_ADVANCE SMOOTH_LIN_ADVANCE NONLINEAR_EXTRUSION INPUT_SHAPING_X INPUT_SHAPING_Y
exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - TMC2209 HW Serial, FT_MOTION" "$3"