Skip to content

Commit 57f6c93

Browse files
tombrazierthinkyhead
authored andcommitted
⚡️ Input Shaping improvements (MarlinFirmware#24951)
1 parent d2ece1e commit 57f6c93

File tree

15 files changed

+472
-371
lines changed

15 files changed

+472
-371
lines changed

Marlin/Configuration_adv.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,12 +1062,14 @@
10621062
*
10631063
* Zero Vibration (ZV) Input Shaping for X and/or Y movements.
10641064
*
1065-
* This option uses a lot of SRAM for the step buffer, which is proportional
1066-
* to the largest step rate possible for any axis. If the build fails due to
1065+
* This option uses a lot of SRAM for the step buffer, which is related to the
1066+
* largest step rate possible for the shaped axes. If the build fails due to
10671067
* low SRAM the buffer size may be reduced by setting smaller values for
1068-
* DEFAULT_AXIS_STEPS_PER_UNIT and/or DEFAULT_MAX_FEEDRATE. Runtime editing
1069-
* of max feedrate (M203) or resonant frequency (M593) may result feedrate
1070-
* being capped to prevent buffer overruns.
1068+
* DEFAULT_AXIS_STEPS_PER_UNIT and/or DEFAULT_MAX_FEEDRATE. Disabling
1069+
* ADAPTIVE_STEP_SMOOTHING and reducing the step rate for non-shaped axes may
1070+
* also reduce the buffer sizes. Runtime editing of max feedrate (M203) or
1071+
* resonant frequency (M593) may result in input shaping losing effectiveness
1072+
* during high speed movements to prevent buffer overruns.
10711073
*
10721074
* Tune with M593 D<factor> F<frequency>:
10731075
*
@@ -1077,13 +1079,18 @@
10771079
* X<1> Set the given parameters only for the X axis.
10781080
* Y<1> Set the given parameters only for the Y axis.
10791081
*/
1080-
//#define INPUT_SHAPING
1081-
#if ENABLED(INPUT_SHAPING)
1082-
#define SHAPING_FREQ_X 40 // (Hz) The dominant resonant frequency of the X axis.
1083-
#define SHAPING_FREQ_Y 40 // (Hz) The dominant resonant frequency of the Y axis.
1084-
#define SHAPING_ZETA_X 0.3f // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
1085-
#define SHAPING_ZETA_Y 0.3f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
1086-
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
1082+
//#define INPUT_SHAPING_X
1083+
//#define INPUT_SHAPING_Y
1084+
#if EITHER(INPUT_SHAPING_X, INPUT_SHAPING_Y)
1085+
#if ENABLED(INPUT_SHAPING_X)
1086+
#define SHAPING_FREQ_X 40 // (Hz) The default dominant resonant frequency on the X axis.
1087+
#define SHAPING_ZETA_X 0.15f // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
1088+
#endif
1089+
#if ENABLED(INPUT_SHAPING_Y)
1090+
#define SHAPING_FREQ_Y 40 // (Hz) The default dominant resonant frequency on the Y axis.
1091+
#define SHAPING_ZETA_Y 0.15f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
1092+
#endif
1093+
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
10871094
#endif
10881095

10891096
#define AXIS_RELATIVE_MODES { false, false, false, false }

Marlin/src/gcode/feature/input_shaping/M593.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,21 @@
2222

2323
#include "../../../inc/MarlinConfig.h"
2424

25-
#if ENABLED(INPUT_SHAPING)
25+
#if HAS_SHAPING
2626

2727
#include "../../gcode.h"
2828
#include "../../../module/stepper.h"
2929

3030
void GcodeSuite::M593_report(const bool forReplay/*=true*/) {
3131
report_heading_etc(forReplay, F("Input Shaping"));
32-
#if HAS_SHAPING_X
32+
#if ENABLED(INPUT_SHAPING_X)
3333
SERIAL_ECHOLNPGM(" M593 X"
3434
" F", stepper.get_shaping_frequency(X_AXIS),
3535
" D", stepper.get_shaping_damping_ratio(X_AXIS)
3636
);
3737
#endif
38-
#if HAS_SHAPING_Y
39-
TERN_(HAS_SHAPING_X, report_echo_start(forReplay));
38+
#if ENABLED(INPUT_SHAPING_Y)
39+
TERN_(INPUT_SHAPING_X, report_echo_start(forReplay));
4040
SERIAL_ECHOLNPGM(" M593 Y"
4141
" F", stepper.get_shaping_frequency(Y_AXIS),
4242
" D", stepper.get_shaping_damping_ratio(Y_AXIS)
@@ -55,10 +55,10 @@ void GcodeSuite::M593_report(const bool forReplay/*=true*/) {
5555
void GcodeSuite::M593() {
5656
if (!parser.seen_any()) return M593_report();
5757

58-
const bool seen_X = TERN0(HAS_SHAPING_X, parser.seen_test('X')),
59-
seen_Y = TERN0(HAS_SHAPING_Y, parser.seen_test('Y')),
60-
for_X = seen_X || TERN0(HAS_SHAPING_X, (!seen_X && !seen_Y)),
61-
for_Y = seen_Y || TERN0(HAS_SHAPING_Y, (!seen_X && !seen_Y));
58+
const bool seen_X = TERN0(INPUT_SHAPING_X, parser.seen_test('X')),
59+
seen_Y = TERN0(INPUT_SHAPING_Y, parser.seen_test('Y')),
60+
for_X = seen_X || TERN0(INPUT_SHAPING_X, (!seen_X && !seen_Y)),
61+
for_Y = seen_Y || TERN0(INPUT_SHAPING_Y, (!seen_X && !seen_Y));
6262

6363
if (parser.seen('D')) {
6464
const float zeta = parser.value_float();
@@ -72,12 +72,13 @@ void GcodeSuite::M593() {
7272

7373
if (parser.seen('F')) {
7474
const float freq = parser.value_float();
75-
if (freq > 0) {
75+
constexpr float max_freq = float(uint32_t(STEPPER_TIMER_RATE) / 2) / shaping_time_t(-2);
76+
if (freq == 0.0f || freq > max_freq) {
7677
if (for_X) stepper.set_shaping_frequency(X_AXIS, freq);
7778
if (for_Y) stepper.set_shaping_frequency(Y_AXIS, freq);
7879
}
7980
else
80-
SERIAL_ECHO_MSG("?Frequency (F) must be greater than 0");
81+
SERIAL_ECHOLNPGM("?Frequency (F) must be greater than ", max_freq, " or 0 to disable");
8182
}
8283
}
8384

Marlin/src/gcode/gcode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
933933
case 575: M575(); break; // M575: Set serial baudrate
934934
#endif
935935

936-
#if ENABLED(INPUT_SHAPING)
936+
#if HAS_SHAPING
937937
case 593: M593(); break; // M593: Set Input Shaping parameters
938938
#endif
939939

Marlin/src/gcode/gcode.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@
259259
* M554 - Get or set IP gateway. (Requires enabled Ethernet port)
260260
* M569 - Enable stealthChop on an axis. (Requires at least one _DRIVER_TYPE to be TMC2130/2160/2208/2209/5130/5160)
261261
* M575 - Change the serial baud rate. (Requires BAUD_RATE_GCODE)
262-
* M593 - Get or set input shaping parameters. (Requires INPUT_SHAPING)
262+
* M593 - Get or set input shaping parameters. (Requires INPUT_SHAPING_[XY])
263263
* M600 - Pause for filament change: "M600 X<pos> Y<pos> Z<raise> E<first_retract> L<later_retract>". (Requires ADVANCED_PAUSE_FEATURE)
264264
* M603 - Configure filament change: "M603 T<tool> U<unload_length> L<load_length>". (Requires ADVANCED_PAUSE_FEATURE)
265265
* M605 - Set Dual X-Carriage movement mode: "M605 S<mode> [X<x_offset>] [R<temp_offset>]". (Requires DUAL_X_CARRIAGE)
@@ -1081,7 +1081,7 @@ class GcodeSuite {
10811081
static void M575();
10821082
#endif
10831083

1084-
#if ENABLED(INPUT_SHAPING)
1084+
#if HAS_SHAPING
10851085
static void M593();
10861086
static void M593_report(const bool forReplay=true);
10871087
#endif

Marlin/src/inc/Conditionals_adv.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,15 +1120,11 @@
11201120
#endif
11211121

11221122
// Input shaping
1123-
#if ENABLED(INPUT_SHAPING)
1124-
#if !HAS_Y_AXIS
1125-
#undef SHAPING_FREQ_Y
1126-
#undef SHAPING_BUFFER_Y
1127-
#endif
1128-
#ifdef SHAPING_FREQ_X
1129-
#define HAS_SHAPING_X 1
1130-
#endif
1131-
#ifdef SHAPING_FREQ_Y
1132-
#define HAS_SHAPING_Y 1
1133-
#endif
1123+
#if !HAS_Y_AXIS
1124+
#undef INPUT_SHAPING_Y
1125+
#undef SHAPING_FREQ_Y
1126+
#undef SHAPING_BUFFER_Y
1127+
#endif
1128+
#if EITHER(INPUT_SHAPING_X, INPUT_SHAPING_Y)
1129+
#define HAS_SHAPING 1
11341130
#endif

Marlin/src/inc/SanityCheck.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4271,14 +4271,14 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
42714271
#endif
42724272

42734273
// Check requirements for Input Shaping
4274-
#if ENABLED(INPUT_SHAPING) && defined(__AVR__)
4275-
#if HAS_SHAPING_X
4274+
#if HAS_SHAPING && defined(__AVR__)
4275+
#if ENABLED(INPUT_SHAPING_X)
42764276
#if F_CPU > 16000000
42774277
static_assert((SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (20) for AVR 20MHz.");
42784278
#else
42794279
static_assert((SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (16) for AVR 16MHz.");
42804280
#endif
4281-
#elif HAS_SHAPING_Y
4281+
#elif ENABLED(INPUT_SHAPING_Y)
42824282
#if F_CPU > 16000000
42834283
static_assert((SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (20) for AVR 20MHz.");
42844284
#else
@@ -4287,12 +4287,8 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
42874287
#endif
42884288
#endif
42894289

4290-
#if ENABLED(INPUT_SHAPING)
4291-
#if ENABLED(DIRECT_STEPPING)
4292-
#error "INPUT_SHAPING cannot currently be used with DIRECT_STEPPING."
4293-
#elif ENABLED(LASER_FEATURE)
4294-
#error "INPUT_SHAPING cannot currently be used with LASER_FEATURE."
4295-
#endif
4290+
#if BOTH(HAS_SHAPING, DIRECT_STEPPING)
4291+
#error "INPUT_SHAPING_[XY] cannot currently be used with DIRECT_STEPPING."
42964292
#endif
42974293

42984294
// Misc. Cleanup

Marlin/src/lcd/language/language_en.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,10 @@ namespace Language_en {
403403
LSTR MSG_A_RETRACT = _UxGT("Retract Accel");
404404
LSTR MSG_A_TRAVEL = _UxGT("Travel Accel");
405405
LSTR MSG_INPUT_SHAPING = _UxGT("Input Shaping");
406-
LSTR MSG_SHAPING_X_FREQ = STR_X _UxGT(" frequency");
407-
LSTR MSG_SHAPING_Y_FREQ = STR_Y _UxGT(" frequency");
408-
LSTR MSG_SHAPING_X_ZETA = STR_X _UxGT(" damping");
409-
LSTR MSG_SHAPING_Y_ZETA = STR_Y _UxGT(" damping");
406+
LSTR MSG_SHAPING_ENABLE = _UxGT("Enable @ shaping");
407+
LSTR MSG_SHAPING_DISABLE = _UxGT("Disable @ shaping");
408+
LSTR MSG_SHAPING_FREQ = _UxGT("@ frequency");
409+
LSTR MSG_SHAPING_ZETA = _UxGT("@ damping");
410410
LSTR MSG_XY_FREQUENCY_LIMIT = _UxGT("XY Freq Limit");
411411
LSTR MSG_XY_FREQUENCY_FEEDRATE = _UxGT("Min FR Factor");
412412
LSTR MSG_STEPS_PER_MM = _UxGT("Steps/mm");

Marlin/src/lcd/menu/menu_advanced.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -545,24 +545,28 @@ void menu_backlash();
545545
START_MENU();
546546
BACK_ITEM(MSG_ADVANCED_SETTINGS);
547547

548-
// M593 F Frequency
549-
#if HAS_SHAPING_X
548+
// M593 F Frequency and D Damping ratio
549+
#if ENABLED(INPUT_SHAPING_X)
550550
editable.decimal = stepper.get_shaping_frequency(X_AXIS);
551-
EDIT_ITEM_FAST(float61, MSG_SHAPING_X_FREQ, &editable.decimal, min_frequency, 200.0f, []{ stepper.set_shaping_frequency(X_AXIS, editable.decimal); });
551+
if (editable.decimal) {
552+
ACTION_ITEM_N(X_AXIS, MSG_SHAPING_DISABLE, []{ stepper.set_shaping_frequency(X_AXIS, 0.0f); });
553+
EDIT_ITEM_FAST_N(float61, X_AXIS, MSG_SHAPING_FREQ, &editable.decimal, min_frequency, 200.0f, []{ stepper.set_shaping_frequency(X_AXIS, editable.decimal); });
554+
editable.decimal = stepper.get_shaping_damping_ratio(X_AXIS);
555+
EDIT_ITEM_FAST_N(float42_52, X_AXIS, MSG_SHAPING_ZETA, &editable.decimal, 0.0f, 1.0f, []{ stepper.set_shaping_damping_ratio(X_AXIS, editable.decimal); });
556+
}
557+
else
558+
ACTION_ITEM_N(X_AXIS, MSG_SHAPING_ENABLE, []{ stepper.set_shaping_frequency(X_AXIS, SHAPING_FREQ_X); });
552559
#endif
553-
#if HAS_SHAPING_Y
560+
#if ENABLED(INPUT_SHAPING_Y)
554561
editable.decimal = stepper.get_shaping_frequency(Y_AXIS);
555-
EDIT_ITEM_FAST(float61, MSG_SHAPING_Y_FREQ, &editable.decimal, min_frequency, 200.0f, []{ stepper.set_shaping_frequency(Y_AXIS, editable.decimal); });
556-
#endif
557-
558-
// M593 D Damping ratio
559-
#if HAS_SHAPING_X
560-
editable.decimal = stepper.get_shaping_damping_ratio(X_AXIS);
561-
EDIT_ITEM_FAST(float42_52, MSG_SHAPING_X_ZETA, &editable.decimal, 0.0f, 1.0f, []{ stepper.set_shaping_damping_ratio(X_AXIS, editable.decimal); });
562-
#endif
563-
#if HAS_SHAPING_Y
564-
editable.decimal = stepper.get_shaping_damping_ratio(Y_AXIS);
565-
EDIT_ITEM_FAST(float42_52, MSG_SHAPING_Y_ZETA, &editable.decimal, 0.0f, 1.0f, []{ stepper.set_shaping_damping_ratio(Y_AXIS, editable.decimal); });
562+
if (editable.decimal) {
563+
ACTION_ITEM_N(Y_AXIS, MSG_SHAPING_DISABLE, []{ stepper.set_shaping_frequency(Y_AXIS, 0.0f); });
564+
EDIT_ITEM_FAST_N(float61, Y_AXIS, MSG_SHAPING_FREQ, &editable.decimal, min_frequency, 200.0f, []{ stepper.set_shaping_frequency(Y_AXIS, editable.decimal); });
565+
editable.decimal = stepper.get_shaping_damping_ratio(Y_AXIS);
566+
EDIT_ITEM_FAST_N(float42_52, Y_AXIS, MSG_SHAPING_ZETA, &editable.decimal, 0.0f, 1.0f, []{ stepper.set_shaping_damping_ratio(Y_AXIS, editable.decimal); });
567+
}
568+
else
569+
ACTION_ITEM_N(Y_AXIS, MSG_SHAPING_ENABLE, []{ stepper.set_shaping_frequency(Y_AXIS, SHAPING_FREQ_Y); });
566570
#endif
567571

568572
END_MENU();

Marlin/src/module/planner.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,13 @@ float Planner::triggered_position_mm(const AxisEnum axis) {
17241724
return result * mm_per_step[axis];
17251725
}
17261726

1727+
bool Planner::busy() {
1728+
return (has_blocks_queued() || cleaning_buffer_counter
1729+
|| TERN0(EXTERNAL_CLOSED_LOOP_CONTROLLER, CLOSED_LOOP_WAITING())
1730+
|| TERN0(HAS_SHAPING, stepper.input_shaping_busy())
1731+
);
1732+
}
1733+
17271734
void Planner::finish_and_disable() {
17281735
while (has_blocks_queued() || cleaning_buffer_counter) idle();
17291736
stepper.disable_all_steppers();
@@ -2483,14 +2490,6 @@ bool Planner::_populate_block(
24832490

24842491
#endif // XY_FREQUENCY_LIMIT
24852492

2486-
#if ENABLED(INPUT_SHAPING)
2487-
const float top_freq = _MIN(float(0x7FFFFFFFL)
2488-
OPTARG(HAS_SHAPING_X, stepper.get_shaping_frequency(X_AXIS))
2489-
OPTARG(HAS_SHAPING_Y, stepper.get_shaping_frequency(Y_AXIS))),
2490-
max_factor = (top_freq * float(shaping_dividends - 3) * 2.0f) / block->nominal_rate;
2491-
NOMORE(speed_factor, max_factor);
2492-
#endif
2493-
24942493
// Correct the speed
24952494
if (speed_factor < 1.0f) {
24962495
current_speed *= speed_factor;

Marlin/src/module/planner.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -930,11 +930,7 @@ class Planner {
930930
static float triggered_position_mm(const AxisEnum axis);
931931

932932
// Blocks are queued, or we're running out moves, or the closed loop controller is waiting
933-
static bool busy() {
934-
return (has_blocks_queued() || cleaning_buffer_counter
935-
|| TERN0(EXTERNAL_CLOSED_LOOP_CONTROLLER, CLOSED_LOOP_WAITING())
936-
);
937-
}
933+
static bool busy();
938934

939935
// Block until all buffered steps are executed / cleaned
940936
static void synchronize();

0 commit comments

Comments
 (0)