From a6bfdf351f241955519af675f5af9dd9dd9f3a52 Mon Sep 17 00:00:00 2001 From: Vovodroid Date: Sat, 31 May 2025 06:53:21 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20NONLINEAR=5FEXTRUSION=5FDEFAULT=5FO?= =?UTF-8?q?N=20(#27819)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Scott Lahteine --- Marlin/Configuration_adv.h | 3 ++ Marlin/src/gcode/feature/nonlinear/M592.cpp | 20 ++++++--- Marlin/src/lcd/language/language_en.h | 1 + Marlin/src/lcd/menu/menu_advanced.cpp | 4 ++ Marlin/src/lcd/menu/menu_tune.cpp | 7 +++ Marlin/src/module/planner.cpp | 4 +- Marlin/src/module/settings.cpp | 8 ++-- Marlin/src/module/stepper.cpp | 41 +++++++----------- Marlin/src/module/stepper.h | 48 ++++++++++++++------- buildroot/tests/STM32F103RC_btt | 2 +- 10 files changed, 83 insertions(+), 55 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 7939b5cc9b..f7ab7abd94 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -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 diff --git a/Marlin/src/gcode/feature/nonlinear/M592.cpp b/Marlin/src/gcode/feature/nonlinear/M592.cpp index 78c15443f8..b084e326f7 100644 --- a/Marlin/src/gcode/feature/nonlinear/M592.cpp +++ b/Marlin/src/gcode/feature/nonlinear/M592.cpp @@ -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 Enable / Disable Nonlinear Extrusion * A Quadratic coefficient (default 0.0) * B Linear coefficient (default 0.0) * C 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 } diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 90948d7865..be309f53d8 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -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)"); diff --git a/Marlin/src/lcd/menu/menu_advanced.cpp b/Marlin/src/lcd/menu/menu_advanced.cpp index b15a21fc7b..65d7a88f0d 100644 --- a/Marlin/src/lcd/menu/menu_advanced.cpp +++ b/Marlin/src/lcd/menu/menu_advanced.cpp @@ -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); diff --git a/Marlin/src/lcd/menu/menu_tune.cpp b/Marlin/src/lcd/menu/menu_tune.cpp index 7f4696a3f1..18d52bb640 100644 --- a/Marlin/src/lcd/menu/menu_tune.cpp +++ b/Marlin/src/lcd/menu/menu_tune.cpp @@ -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: diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 8678c82130..2e2b5798b7 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -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); diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index 2161be5abc..0d197b2d12 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -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 diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index edfed3b8e2..fd3d3bd800 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -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 diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index 73fd28fe85..90cbedc9fc 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -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; diff --git a/buildroot/tests/STM32F103RC_btt b/buildroot/tests/STM32F103RC_btt index 2b05d42922..97339d7750 100755 --- a/buildroot/tests/STM32F103RC_btt +++ b/buildroot/tests/STM32F103RC_btt @@ -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"