Input Shaping Calib: Types, RepRap + Improvements (#10913)
Some checks are pending
Build all / Build All (push) Waiting to run
Build all / Flatpak (push) Waiting to run
Publish docs to Wiki / Publish docs to Wiki (push) Waiting to run

* IS Freq duplicated as Base

* IS jerk to 5

* JD jerk to 0

* Base 1 layer + MINIMUM_CRUISE_RATIO=0

* Tab

* Remove IS BASE

* Update Plater.cpp

* Klipper Jerk 5, Others 10

* JD in Marlin2

* Types

* Horizontal

* Different lists

* RepRap IS writer

* Smart Flavors and axis

* RepRap values lowercase

* Hide Y axix for RepRap

* Max Jerk or JD

* Reorder

* Removed dual list + Default

* RepRap show UpperCase use LowerCase

* RepRap P"type" Type of input shaping to use, not case sensitive.

* RepRap DAA

* Reorder Klipper

* Custom Firmware Note

* Better Display

Co-Authored-By: yw4z <28517890+yw4z@users.noreply.github.com>

* Better notes

* Update + Clean Wiki

Co-Authored-By: gregmatic <60957555+gregmatic@users.noreply.github.com>

* Wiki Update

Update Images
Improve guide

Co-Authored-By: Cameron D <30559428+cdunn95@users.noreply.github.com>

* Fix G-code generation issue and refine input shaping calibration documentation

---------

Co-authored-by: yw4z <28517890+yw4z@users.noreply.github.com>
Co-authored-by: gregmatic <60957555+gregmatic@users.noreply.github.com>
Co-authored-by: Cameron D <30559428+cdunn95@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Ian Bassi 2025-10-19 13:31:51 -03:00 committed by GitHub
parent a754387566
commit d786aec255
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 384 additions and 138 deletions

View file

@ -2,130 +2,124 @@
During high-speed movements, vibrations can cause a phenomenon called "ringing," where periodic ripples appear on the print surface. Input Shaping provides an effective solution by counteracting these vibrations, improving print quality and reducing wear on components without needing to significantly lower print speeds.
- [Klipper](#klipper)
- [Resonance Compensation](#resonance-compensation)
- [Marlin](#marlin)
- [ZV Input Shaping](#zv-input-shaping)
> [!IMPORTANT]
> RepRap can only set one frequency for both X and Y axes so you will need to select a frequency that works well for both axes.
- [Types](#types)
- [Default](#default)
- [Version Table](#version-table)
- [Calibration Steps](#calibration-steps)
- [Fixed-Time Motion](#fixed-time-motion)
- [Credits](#credits)
## Klipper
## Types
### Resonance Compensation
It is usually recommended to use MZV, EI (specially for Delta printers) or ZV as a simple and effective solution.
Not all Input Shaping types are available in all firmware and their performance may vary depending on the firmware implementation and the printer's mechanics.
The Klipper Resonance Compensation is a set of Input Shaping modes that can be used to reduce ringing and improve print quality.
Ussualy the recommended values modes are `MZV` or `EI` for Delta printers.
### Default
1. Pre-requisites:
1. In OrcaSlicer, set:
1. Acceleration high enough to trigger ringing (e.g., 2000 mm/s²).
2. Speed high enough to trigger ringing (e.g., 100 mm/s).
When "Default" is selected, the firmware's default input shaper will be used.
Every firmware and even its version may have a different default type but usually are:
> [!NOTE]
> These settings depend on your printer's motion ability and the filament's max volumetric speed. If you can't reach speeds that cause ringing, try increasing the filament's max volumetric speed (avoid materials below 10 mm³/s).
3. Jerk [Klipper Square Corner Velocity](https://www.klipper3d.org/Kinematics.html?h=square+corner+velocity#look-ahead) to 5 or a high value (e.g., 20).
- Klipper: MZV
- Marlin: ZV
- RepRap:
- Version >= 3.4: MZV
- Version < 3.4: DAA
- Version < 3.2: DAA (without damping option)
2. In printer settigs:
1. Set the Shaper Type to `MZV` or `EI`.
```gcode
SET_INPUT_SHAPER SHAPER_TYPE=MZV
```
2. Disable [Minimun Cruise Ratio](https://www.klipper3d.org/Kinematics.html#minimum-cruise-ratio) with:
```gcode
SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0
```
3. Use an opaque, high-gloss filament to make the ringing more visible.
2. Print the Input Shaping Frequency test with a range of frequencies.
### Version Table
![IS_freq_menu](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_menu.png?raw=true)
| Type | Name | [Klipper](https://www.klipper3d.org/Resonance_Compensation.html#technical-details) | [RepRap](https://docs.duet3d.com/User_manual/Reference/Gcodes#m593-configure-input-shaping) | [Marlin 2](https://marlinfw.org/docs/features/ft_motion.html#more-complexity-zv-input-shaper) | Marlin Legacy |
|---|---|---|---|---|---|
| MZV | Modified Zero Vibration | >=0.9.0 | >=3.4 | - | - |
| ZV | Zero Vibration | >=0.9.0 | = 3.5 | >2.1.2 | - |
| ZVD | Zero Vibration Derivative | >=0.9.0 | >=3.4 | - | - |
| ZVDD | Zero Vibration Double Derivative | - | >=3.4 | - | - |
| ZVDDD | Zero Vibration Triple Derivative | - | >=3.4 | - | - |
| EI | Extra Insensitive | >=0.9.0 | - | - | - |
| 2HUMP_EI / EI2 | Two-Hump Extra Insensitive | >=0.9.0 | >=3.4 | - | - |
| 3HUMP_EI / EI3 | Three-Hump Extra Insensitive | >=0.9.0 | >=3.4 | - | - |
| [FT_MOTION](https://marlinfw.org/docs/features/ft_motion.html#fixed-time-motion-by-ulendo) | Fixed-Time Motion | - | - | >2.1.3 | - |
| DAA | Damped Anti-Resonance | - | < 3.4 | - | - |
1. Measure the X and Y heights and read the frequency set at that point in OrcaSlicer.
## Calibration Steps
![IS_damp_klipper_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_klipper_print_measure.jpg?raw=true)
![IS_freq_klipper_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_klipper_slicer_measure.png?raw=true)
2. If not a clear result, you can measure a X and Y min and max acceptable heights and repeat the test with that min and max value.
> [!WARNING]
> There is a chance you will need to set higher than 60Hz frequencies. Some printers with very rigid frames and excellent mechanics may exhibit frequencies exceeding 100Hz.
3. Print the Damping test setting your X and Y frequency to the value you found in the previous step.
![IS_damp_menu](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_menu.png?raw=true)
1. Measure the X and Y heights and read the damping set at that point in OrcaSlicer.
![IS_damp_klipper_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_klipper_print_measure.jpg?raw=true)
![IS_damp_klipper_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_klipper_slicer_measure.png?raw=true)
0. Pre-requisites:
1. Use an opaque, high-gloss filament to make the ringing more visible.
2. In OrcaSlicer, set:
1. Acceleration high enough to trigger ringing (e.g., 20000 mm/s²).
2. Speed high enough to trigger ringing (e.g., 200 mm/s).
> [!IMPORTANT]
> Not all Resonance Compensation modes support damping.
4. Restore your 3D Printer settings to avoid keep using high acceleration and jerk values.
5. Save the settings
1. You need to go to the printer settings and set the X and Y frequency and damp to the value you found in the previous step.
## Marlin
### ZV Input Shaping
ZV Input Shaping introduces an anti-vibration signal into the stepper motion for the X and Y axes. It works by splitting the step count into two halves: the first at half the frequency and the second as an "echo," delayed by half the ringing interval. This simple approach effectively reduces vibrations, improving print quality and allowing for higher speeds.
1. Pre-requisites:
1. In OrcaSlicer, set:
1. Acceleration high enough to trigger ringing (e.g., 2000 mm/s²).
2. Speed high enough to trigger ringing (e.g., 100 mm/s).
> [!NOTE]
> These settings depend on your printer's motion ability and the filament's max volumetric speed. If you can't reach speeds that cause ringing, try increasing the filament's max volumetric speed (avoid materials below 10 mm³/s).
3. Jerk
1. If using [Classic Jerk](https://marlinfw.org/docs/configuration/configuration.html#jerk-) use a high value (e.g., 20).
2. If using [Junction Deviation](https://marlinfw.org/docs/features/junction_deviation.html) (new Marlin default mode) this test will use 0.25 (high enough to most printers).
2. Use an opaque, high-gloss filament to make the ringing more visible.
2. Print the Input Shaping Frequency test with a range of frequencies.
> It's recommended to use the fastest [acceleration](speed_settings_acceleration), [speed](speed_settings_other_layers_speed) and [Jerk/Junction Deviation](speed_settings_jerk_xy) your printer can handle without losing steps.
> This test **will set the values to high values** limited by your printer's motion ability and the filament's max volumetric speed (avoid materials below 10 mm³/s).
1. Select the Test Model ´Ringing Tower´ (Recommended) or ´Fast Tower´ (Reduced version useful for printers with high ringing).
2. Select the [Input Shaper Type](#types) you want to test. Each firmware has different types available and each type has different performance.
3. Select a range of frequencies to test. The Default 15hz to 110hz range is usually a good start.
4. Select your damping. Usually, a value between 0.1 and 0.2 is a good start but you can change it to 0 and your printer will use the firmware default value (if available).
![IS_freq_menu](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_menu.png?raw=true)
1. Measure the X and Y heights and read the frequency set at that point in OrcaSlicer.
![IS_freq_marlin_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_marlin_print_measure.jpg?raw=true)
![IS_freq_marlin_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_marlin_slicer_measure.png?raw=true)
1. Measure the X and Y heights and read the frequency set at that point in OrcaSlicer.
![IS_freq_marlin_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_marlin_print_measure.jpg?raw=true)
- Marlin:
![IS_freq_marlin_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_marlin_slicer_measure.png?raw=true)
- Klipper:
![IS_freq_klipper_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_freq_klipper_slicer_measure.png?raw=true)
2. If not a clear result, you can measure a X and Y min and max acceptable heights and repeat the test with that min and max value.
> [!WARNING]
> There is a chance you will need to set higher than 60Hz frequencies. Some printers with very rigid frames and excellent mechanics may exhibit frequencies exceeding 100Hz.
3. Print the Damping test setting your X and Y frequency to the value you found in the previous step.
5. Print the Damping test setting your X and Y frequency to the value you found in the previous step.
![IS_damp_menu](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_menu.png?raw=true)
1. Measure the X and Y heights and read the damping set at that point in OrcaSlicer.
![IS_damp_marlin_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_marlin_print_measure.jpg?raw=true)
- Marlin:
![IS_damp_marlin_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_marlin_slicer_measure.png?raw=true)
- Klipper:
![IS_damp_klipper_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_klipper_slicer_measure.png?raw=true)
1. Measure the X and Y heights and read the damping set at that point in OrcaSlicer.
![IS_damp_marlin_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_marlin_print_measure.jpg?raw=true)
![IS_damp_marlin_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/InputShaping/IS_damp_marlin_slicer_measure.png?raw=true)
4. Restore your 3D Printer settings to avoid keep using high acceleration and jerk values.
1. Reboot your printer.
2. Use the following G-code to restore your printer settings:
```gcode
M501
```
5. Save the settings
1. You need to go to the printer settings and set the X and Y frequency and damp to the value you found in the previous step.
2. Use the following G-code to set the frequency:
```gcode
M593 X F#Xfrequency D#XDamping
M593 Y F#Yfrequency D#YDamping
M500
```
Example
```gcode
M593 X F37.25 D0.16
M593 Y F37.5 D0.06
M500
```
6. **Restore your 3D Printer settings to avoid keep using high acceleration and jerk values.**
7. Save the settings
- Into your printer firmware settings save the values you found (Type, frequency/cies and damp)
- Save it into Orca's printer profile settings in Printer settings/ Machine G-code/ Machine start G-code using the following G-code:
- Klipper:
- Skeleton
```gcode
SET_INPUT_SHAPER SHAPER_TYPE=TYPE SHAPER_FREQ_X=#Xfrequency DAMPING_RATIO_X=#XDamping SHAPER_FREQ_Y=#Yfrequency DAMPING_RATIO_Y=#YDamping
```
Example
```gcode
SET_INPUT_SHAPER SHAPER_TYPE=MZV SHAPER_FREQ_X=37.25 DAMPING_RATIO_X=0.16 SHAPER_FREQ_Y=37.5 DAMPING_RATIO_Y=0.06
```
- Marlin:
- Skeleton
```gcode
M593 X F#Xfrequency D#XDamping
M593 Y F#Yfrequency D#YDamping
M500
```
Example
```gcode
M593 X F37.25 D0.16
M593 Y F37.5 D0.06
M500
```
- RepRap:
- Skeleton for RepRap 3.3 and later
```gcode
M593 P#Type F#frequency S#Damping
```
Example RepRap 3.4 and later
```gcode
M593 P"ZVD" F37.25 S0.16
```
- Skeleton for RepRap 3.2 and earlier
```gcode
M593 F#frequency
```
Example Legacy (RepRap 3.2 and earlier)
```gcode
M593 F37.25
```
### Fixed-Time Motion

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before After
Before After

View file

@ -3788,23 +3788,31 @@ LayerResult GCode::process_layer(
}
case CalibMode::Calib_Input_shaping_freq: {
if (m_layer_index == 1){
gcode += writer().set_input_shaping('A', print.calib_params().start, 0.f);
gcode += writer().set_input_shaping('A', print.calib_params().start, 0.f, print.calib_params().shaper_type);
if (m_writer.get_gcode_flavor() == gcfKlipper) {
// Disable minimum cruise ratio to ensure consistent motion for calibration
gcode += "SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0\n";
}
} else {
if (print.calib_params().freqStartX == print.calib_params().freqStartY && print.calib_params().freqEndX == print.calib_params().freqEndY) {
gcode += writer().set_input_shaping('A', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3));
gcode += writer().set_input_shaping('A', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3), "");
} else {
gcode += writer().set_input_shaping('X', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3));
gcode += writer().set_input_shaping('Y', 0.f, (print.calib_params().freqStartY) + ((print.calib_params().freqEndY)-(print.calib_params().freqStartY)) * (m_layer_index - 2) / (m_layer_count - 3));
gcode += writer().set_input_shaping('X', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3), "");
gcode += writer().set_input_shaping('Y', 0.f, (print.calib_params().freqStartY) + ((print.calib_params().freqEndY)-(print.calib_params().freqStartY)) * (m_layer_index - 2) / (m_layer_count - 3), "");
}
}
break;
}
case CalibMode::Calib_Input_shaping_damp: {
if (m_layer_index == 1){
gcode += writer().set_input_shaping('X', 0.f, print.calib_params().freqStartX);
gcode += writer().set_input_shaping('Y', 0.f, print.calib_params().freqStartY);
if (m_writer.get_gcode_flavor() == gcfKlipper) {
// Disable minimum cruise ratio to ensure consistent motion for calibration
gcode += "SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0\n";
}
gcode += writer().set_input_shaping('X', 0.f, print.calib_params().freqStartX, print.calib_params().shaper_type);
gcode += writer().set_input_shaping('Y', 0.f, print.calib_params().freqStartY, print.calib_params().shaper_type);
} else {
gcode += writer().set_input_shaping('A', print.calib_params().start + ((print.calib_params().end)-(print.calib_params().start)) * (m_layer_index) / (m_layer_count), 0.f);
gcode += writer().set_input_shaping('A', print.calib_params().start + ((print.calib_params().end)-(print.calib_params().start)) * (m_layer_index) / (m_layer_count), 0.f, "");
}
break;
}

View file

@ -352,8 +352,10 @@ std::string GCodeWriter::set_pressure_advance(double pa) const
return gcode.str();
}
std::string GCodeWriter::set_input_shaping(char axis, float damp, float freq) const
std::string GCodeWriter::set_input_shaping(char axis, float damp, float freq, std::string type) const
{
if (FLAVOR_IS(gcfMarlinLegacy))
throw std::runtime_error("Input shaping is not supported by Marlin < 2.1.2.\nCheck your firmware version and update your G-code flavor to ´Marlin 2´");
if (freq < 0.0f || damp < 0.f || damp > 1.0f || (axis != 'X' && axis != 'Y' && axis != 'Z' && axis != 'A'))// A = all axis
{
throw std::runtime_error("Invalid input shaping parameters: freq=" + std::to_string(freq) + ", damp=" + std::to_string(damp));
@ -361,14 +363,17 @@ std::string GCodeWriter::set_input_shaping(char axis, float damp, float freq) co
std::ostringstream gcode;
if (FLAVOR_IS(gcfKlipper)) {
gcode << "SET_INPUT_SHAPER";
if (!type.empty() && type != "Default") {
gcode << " SHAPER_TYPE=" << type;
}
if (axis != 'A')
{
if (freq > 0.0f) {
gcode << " SHAPER_FREQ_" << axis << "=" << std::fixed << std::setprecision(2) << freq;
}
if (damp > 0.0f){
gcode << " DAMPING_RATIO_" << axis << "=" << damp;
}
gcode << " DAMPING_RATIO_" << axis << "=" << std::fixed << std::setprecision(3) << damp;
}
} else {
if (freq > 0.0f) {
gcode << " SHAPER_FREQ_X=" << std::fixed << std::setprecision(2) << freq << " SHAPER_FREQ_Y=" << std::fixed << std::setprecision(2) << freq;
@ -377,7 +382,18 @@ std::string GCodeWriter::set_input_shaping(char axis, float damp, float freq) co
gcode << " DAMPING_RATIO_X=" << std::fixed << std::setprecision(3) << damp << " DAMPING_RATIO_Y=" << std::fixed << std::setprecision(3) << damp;
}
}
} else {
} else if (FLAVOR_IS(gcfRepRapFirmware)) {
gcode << "M593";
if (!type.empty() && type != "Default" && type != "DAA") {
gcode << " P\"" << type << "\"";
}
if (freq > 0.0f) {
gcode << " F" << std::fixed << std::setprecision(2) << freq;
}
if (damp > 0.0f){
gcode << " S" << std::fixed << std::setprecision(3) << damp;
}
} else if (FLAVOR_IS(gcfMarlinFirmware)) {
gcode << "M593";
if (axis != 'A')
{
@ -391,6 +407,8 @@ std::string GCodeWriter::set_input_shaping(char axis, float damp, float freq) co
{
gcode << " D" << std::fixed << std::setprecision(3) << damp;
}
} else {
throw std::runtime_error("Input shaping is only supported by Klipper, RepRapFirmware and Marlin 2");
}
if (GCodeWriter::full_gcode_comment){
gcode << " ; Override input shaping";

View file

@ -55,7 +55,7 @@ public:
std::string set_accel_and_jerk(unsigned int acceleration, double jerk);
std::string set_junction_deviation(double junction_deviation);
std::string set_pressure_advance(double pa) const;
std::string set_input_shaping(char axis, float damp, float freq) const;
std::string set_input_shaping(char axis, float damp, float freq, std::string type) const;
std::string reset_e(bool force = false);
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
// return false if this extruder was already selected

View file

@ -37,6 +37,7 @@ struct Calib_Params
bool print_numbers;
double freqStartX, freqEndX, freqStartY, freqEndY;
int test_model;
std::string shaper_type;
std::vector<double> accelerations;
std::vector<double> speeds;

View file

@ -10241,7 +10241,28 @@ void Plater::calib_input_shaping_freq(const Calib_Params& params)
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config;
auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats {0.3});
const auto gcode_flavor_option = printer_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor");
float junction_deviation_value = 0.f;
if (gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfMarlinFirmware) {
const auto machine_junction_option = printer_config->option<ConfigOptionFloats>("machine_max_junction_deviation");
const float current = (machine_junction_option && !machine_junction_option->values.empty())
? machine_junction_option->values.front()
: 0.f;
junction_deviation_value = std::max(current, 0.25f);
}
float machine_max_jerk_x = 0.f;
if (const auto option = printer_config->option<ConfigOptionFloats>("machine_max_jerk_x");
option != nullptr && !option->values.empty()) {
machine_max_jerk_x = option->values.front();
}
float machine_max_jerk_y = 0.f;
if (const auto option = printer_config->option<ConfigOptionFloats>("machine_max_jerk_y");
option != nullptr && !option->values.empty()) {
machine_max_jerk_y = option->values.front();
}
const float jerk_value = std::max((gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfKlipper) ? 5.f : 10.f,
std::min(machine_max_jerk_x, machine_max_jerk_y));
printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats {junction_deviation_value});
printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false});
filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 0.0 });
filament_config->set_key_value("slow_down_min_speed", new ConfigOptionFloats { 0.0 });
@ -10261,9 +10282,11 @@ void Plater::calib_input_shaping_freq(const Calib_Params& params)
print_config->set_key_value("spiral_mode_smooth", new ConfigOptionBool(false));
print_config->set_key_value("bottom_surface_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(0.25));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("default_jerk", new ConfigOptionFloat(jerk_value));
print_config->set_key_value("outer_wall_jerk", new ConfigOptionFloat(jerk_value));
print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(junction_deviation_value));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
@ -10289,7 +10312,28 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params)
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config;
auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats{0.3});
const auto gcode_flavor_option = printer_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor");
float junction_deviation_value = 0.f;
if (gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfMarlinFirmware) {
const auto machine_junction_option = printer_config->option<ConfigOptionFloats>("machine_max_junction_deviation");
const float current = (machine_junction_option && !machine_junction_option->values.empty())
? machine_junction_option->values.front()
: 0.f;
junction_deviation_value = std::max(current, 0.25f);
}
float machine_max_jerk_x = 0.f;
if (const auto option = printer_config->option<ConfigOptionFloats>("machine_max_jerk_x");
option != nullptr && !option->values.empty()) {
machine_max_jerk_x = option->values.front();
}
float machine_max_jerk_y = 0.f;
if (const auto option = printer_config->option<ConfigOptionFloats>("machine_max_jerk_y");
option != nullptr && !option->values.empty()) {
machine_max_jerk_y = option->values.front();
}
const float jerk_value = std::max((gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfKlipper) ? 5.f : 10.f,
std::min(machine_max_jerk_x, machine_max_jerk_y));
printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats{junction_deviation_value});
printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false});
filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 0.0 });
filament_config->set_key_value("slow_down_min_speed", new ConfigOptionFloats { 0.0 });
@ -10309,9 +10353,11 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params)
print_config->set_key_value("spiral_mode_smooth", new ConfigOptionBool(false));
print_config->set_key_value("bottom_surface_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(0.25));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(20000));
print_config->set_key_value("default_jerk", new ConfigOptionFloat(jerk_value));
print_config->set_key_value("outer_wall_jerk", new ConfigOptionFloat(jerk_value));
print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(junction_deviation_value));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
@ -10360,6 +10406,7 @@ void Plater::calib_junction_deviation(const Calib_Params& params)
print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200));
print_config->set_key_value("default_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(2000));
print_config->set_key_value("default_jerk", new ConfigOptionFloat(0));
print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(0.0));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));

View file

@ -6,6 +6,8 @@
#include "MainFrame.hpp"
#include "Widgets/DialogButtons.hpp"
#include <string>
#include <vector>
#include "libslic3r/PrintConfig.hpp"
namespace Slic3r { namespace GUI {
@ -28,6 +30,39 @@ int GetTextMax(wxWindow* parent, const std::vector<wxString>& labels)
return text_size.x + parent->FromDIP(10);
}
std::vector<std::string> get_shaper_type_values()
{
if (auto* preset_bundle = wxGetApp().preset_bundle) {
auto printer_config = &preset_bundle->printers.get_edited_preset().config;
if (auto* gcode_flavor_option = printer_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")) {
switch (gcode_flavor_option->value) {
case GCodeFlavor::gcfKlipper:
return {"Default", "ZV", "MZV", "ZVD", "EI", "2HUMP_EI", "3HUMP_EI"};
case GCodeFlavor::gcfRepRapFirmware:
return {"Default", "MZV", "ZVD", "ZVDD", "ZVDDD", "EI2", "EI3", "DAA"};
case GCodeFlavor::gcfMarlinFirmware:
return {"ZV"};
default:
break;
}
}
}
return {"Default"};
}
std::vector<wxString> make_shaper_type_labels()
{
auto values = get_shaper_type_values();
if (values.empty())
values.emplace_back("");
std::vector<wxString> labels;
labels.reserve(values.size());
for (const auto& label : values)
labels.emplace_back(wxString::FromUTF8(label.c_str()));
return labels;
}
}
PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
@ -761,6 +796,12 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
SetForegroundColour(wxColour("#363636"));
SetFont(Label::Body_14);
const auto* preset_bundle = wxGetApp().preset_bundle;
const auto* gcode_flavor_option = (preset_bundle != nullptr)
? preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")
: nullptr;
const bool reprap_firmware = gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfRepRapFirmware;
wxBoxSizer* v_sizer = new wxBoxSizer(wxVERTICAL);
SetSizer(v_sizer);
@ -772,8 +813,41 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
model_box->Add(m_rbModel, 0, wxALL | wxEXPAND, FromDIP(4));
v_sizer->Add(model_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
// Input shaper type selection
auto labeled_box_type = new LabeledStaticBox(this, _L("Input shaper type"));
auto type_box = new wxStaticBoxSizer(labeled_box_type, wxVERTICAL);
auto type_labels = make_shaper_type_labels();
m_rbType = new RadioGroup(this, type_labels, wxVERTICAL, 3);
type_box->Add(m_rbType, 0, wxALL | wxEXPAND, FromDIP(4));
m_rbType->SetSelection(0);
// Determine firmware-specific note
wxString firmware_note = "Please ensure the selected type is compatible with your firmware version.";
if (gcode_flavor_option) {
switch (gcode_flavor_option->value) {
case GCodeFlavor::gcfMarlinFirmware:
case GCodeFlavor::gcfMarlinLegacy:
firmware_note = "Marlin version => 2.1.2\nFixed-Time motion not yet implemented.";
break;
case GCodeFlavor::gcfKlipper:
firmware_note = "Klipper version => 0.9.0";
break;
case GCodeFlavor::gcfRepRapFirmware:
firmware_note = "RepRap firmware version => 3.4.0\nCheck your firmware documentation for supported shaper types.";
break;
default:
break;
}
}
auto type_note = new wxStaticText(this, wxID_ANY, firmware_note, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
type_note->SetForegroundColour(wxColour(128, 128, 128));
type_box->Add(type_note, 0, wxALL, FromDIP(5));
v_sizer->Add(type_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
// Settings
wxString x_axis_str = "X " + _L("Start / End") + ": ";
wxString x_axis_str = reprap_firmware ? _L("Frequency (Start / End): ") : "X " + _L("Start / End") + ": ";
wxString y_axis_str = "Y " + _L("Start / End") + ": ";
int text_max = GetTextMax(this, std::vector<wxString>{x_axis_str, y_axis_str});
@ -805,12 +879,24 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
m_tiFreqStartY->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiFreqEndY = new TextInput(this, std::to_string(110), "Hz", "", wxDefaultPosition, ti_size);
m_tiFreqEndY->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
y_freq_sizer->Add(start_y_text , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
y_freq_sizer->Add(m_tiFreqStartY, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
y_freq_sizer->Add(m_tiFreqEndY , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(y_freq_sizer, 0, wxLEFT, FromDIP(3));
if (reprap_firmware) {
m_tiFreqStartY->GetTextCtrl()->SetValue(m_tiFreqStartX->GetTextCtrl()->GetValue());
m_tiFreqEndY->GetTextCtrl()->SetValue(m_tiFreqEndX->GetTextCtrl()->GetValue());
start_y_text->Hide();
m_tiFreqStartY->Hide();
m_tiFreqEndY->Hide();
settings_sizer->Hide(y_freq_sizer);
start_x_text->SetLabel(_L("Frequency (Start / End): "));
m_tiFreqStartX->GetTextCtrl()->SetToolTip(_L("RepRap firmware uses the same frequency range for both axes."));
m_tiFreqEndX->GetTextCtrl()->SetToolTip(_L("RepRap firmware uses the same frequency range for both axes."));
}
// Damping Factor
wxString damping_factor_str = _L("Damp: ");
auto damping_factor_sizer = new wxBoxSizer(wxHORIZONTAL);
@ -824,8 +910,7 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
settings_sizer->AddSpacer(FromDIP(5));
// Add a note explaining that 0 means use default value
auto note_text = new wxStaticText(this, wxID_ANY, _L("Recommended: Set Damp to 0.\nThis will use the printer's default or the last saved value."), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
auto note_text = new wxStaticText(this, wxID_ANY, _L("Recommended: Set Damp to 0.\nThis will use the printer's default or saved value."), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
note_text->SetForegroundColour(wxColour(128, 128, 128));
settings_sizer->Add(note_text, 0, wxALL, FromDIP(5));
@ -853,15 +938,29 @@ void Input_Shaping_Freq_Test_Dlg::on_start(wxCommandEvent& event) {
bool read_double = false;
read_double = m_tiFreqStartX->GetTextCtrl()->GetValue().ToDouble(&m_params.freqStartX);
read_double = read_double && m_tiFreqEndX->GetTextCtrl()->GetValue().ToDouble(&m_params.freqEndX);
read_double = read_double && m_tiFreqStartY->GetTextCtrl()->GetValue().ToDouble(&m_params.freqStartY);
read_double = read_double && m_tiFreqEndY->GetTextCtrl()->GetValue().ToDouble(&m_params.freqEndY);
const auto* preset_bundle = wxGetApp().preset_bundle;
const auto* gcode_flavor_option = (preset_bundle != nullptr)
? preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")
: nullptr;
const bool reprap_firmware = gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfRepRapFirmware;
if (!reprap_firmware) {
read_double = read_double && m_tiFreqStartY->GetTextCtrl()->GetValue().ToDouble(&m_params.freqStartY);
read_double = read_double && m_tiFreqEndY->GetTextCtrl()->GetValue().ToDouble(&m_params.freqEndY);
} else {
m_params.freqStartY = m_params.freqStartX;
m_params.freqEndY = m_params.freqEndX;
m_tiFreqStartY->GetTextCtrl()->SetValue(m_tiFreqStartX->GetTextCtrl()->GetValue());
m_tiFreqEndY->GetTextCtrl()->SetValue(m_tiFreqEndX->GetTextCtrl()->GetValue());
}
read_double = read_double && m_tiDampingFactor->GetTextCtrl()->GetValue().ToDouble(&m_params.start);
if (!read_double ||
m_params.freqStartX < 0 || m_params.freqEndX > 500 ||
m_params.freqStartY < 0 || m_params.freqEndX > 500 ||
(!reprap_firmware && (m_params.freqStartY < 0 || m_params.freqEndY > 500)) ||
m_params.freqStartX >= m_params.freqEndX ||
m_params.freqStartY >= m_params.freqEndY) {
(!reprap_firmware && m_params.freqStartY >= m_params.freqEndY)) {
MessageDialog msg_dlg(nullptr, _L("Please input valid values:\n(0 < FreqStart < FreqEnd < 500)"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
@ -873,6 +972,16 @@ void Input_Shaping_Freq_Test_Dlg::on_start(wxCommandEvent& event) {
return;
}
auto shaper_values = get_shaper_type_values();
int type_selection = m_rbType->GetSelection();
if (shaper_values.empty()) {
m_params.shaper_type.clear();
} else {
if (type_selection < 0 || type_selection >= static_cast<int>(shaper_values.size()))
type_selection = 0;
m_params.shaper_type = shaper_values[static_cast<size_t>(type_selection)];
}
m_params.mode = CalibMode::Calib_Input_shaping_freq;
// Set model type based on selection
@ -897,6 +1006,12 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin
SetForegroundColour(wxColour("#363636"));
SetFont(Label::Body_14);
const auto* preset_bundle = wxGetApp().preset_bundle;
const auto* gcode_flavor_option = (preset_bundle != nullptr)
? preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")
: nullptr;
const bool reprap_firmware = gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfRepRapFirmware;
wxBoxSizer* v_sizer = new wxBoxSizer(wxVERTICAL);
SetSizer(v_sizer);
@ -908,8 +1023,41 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin
model_box->Add(m_rbModel, 0, wxALL | wxEXPAND, FromDIP(4));
v_sizer->Add(model_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
// Input shaper type selection
auto labeled_box_type = new LabeledStaticBox(this, _L("Input shaper type"));
auto type_box = new wxStaticBoxSizer(labeled_box_type, wxVERTICAL);
auto type_labels = make_shaper_type_labels();
m_rbType = new RadioGroup(this, type_labels, wxVERTICAL, 3);
type_box->Add(m_rbType, 0, wxALL | wxEXPAND, FromDIP(4));
m_rbType->SetSelection(0);
// Determine firmware-specific note
wxString firmware_note = "Check firmware compatibility.";
if (gcode_flavor_option) {
switch (gcode_flavor_option->value) {
case GCodeFlavor::gcfMarlinFirmware:
case GCodeFlavor::gcfMarlinLegacy:
firmware_note = "Marlin version => 2.1.2\nFixed-Time motion not yet implemented.";
break;
case GCodeFlavor::gcfKlipper:
firmware_note = "Klipper version => 0.9.0";
break;
case GCodeFlavor::gcfRepRapFirmware:
firmware_note = "RepRap firmware version => 3.4.0\nCheck your firmware documentation for supported shaper types.";
break;
default:
break;
}
}
auto type_note = new wxStaticText(this, wxID_ANY, firmware_note, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
type_note->SetForegroundColour(wxColour(128, 128, 128));
type_box->Add(type_note, 0, wxALL, FromDIP(5));
v_sizer->Add(type_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
// Settings
wxString freq_str = _L("Frequency") + " X / Y: ";
wxString freq_str = reprap_firmware ? _L("Frequency: ") : _L("Frequency") + " X / Y: ";
wxString damp_str = _L("Damp") + " " + _L("Start / End") + ": ";
int text_max = GetTextMax(this, std::vector<wxString>{freq_str, damp_str});
@ -931,7 +1079,14 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin
freq_sizer->Add(m_tiFreqX, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
freq_sizer->Add(m_tiFreqY, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(freq_sizer, 0, wxLEFT, FromDIP(3));
if (reprap_firmware) {
m_tiFreqY->GetTextCtrl()->SetValue(m_tiFreqX->GetTextCtrl()->GetValue());
m_tiFreqY->Hide();
freq_text->SetLabel(freq_str);
m_tiFreqX->GetTextCtrl()->SetToolTip(_L("RepRap firmware uses the same frequency for both axes."));
}
// Damping Factor Start and End
auto damp_sizer = new wxBoxSizer(wxHORIZONTAL);
auto damp_text = new wxStaticText(this, wxID_ANY, damp_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
@ -974,13 +1129,24 @@ Input_Shaping_Damp_Test_Dlg::~Input_Shaping_Damp_Test_Dlg() {
void Input_Shaping_Damp_Test_Dlg::on_start(wxCommandEvent& event) {
bool read_double = false;
read_double = m_tiFreqX->GetTextCtrl()->GetValue().ToDouble(&m_params.freqStartX);
read_double = read_double && m_tiFreqY->GetTextCtrl()->GetValue().ToDouble(&m_params.freqStartY);
const auto* preset_bundle = wxGetApp().preset_bundle;
const auto* gcode_flavor_option = (preset_bundle != nullptr)
? preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")
: nullptr;
const bool reprap_firmware = gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfRepRapFirmware;
if (!reprap_firmware) {
read_double = read_double && m_tiFreqY->GetTextCtrl()->GetValue().ToDouble(&m_params.freqStartY);
} else {
m_params.freqStartY = m_params.freqStartX;
m_tiFreqY->GetTextCtrl()->SetValue(m_tiFreqX->GetTextCtrl()->GetValue());
}
read_double = read_double && m_tiDampingFactorStart->GetTextCtrl()->GetValue().ToDouble(&m_params.start);
read_double = read_double && m_tiDampingFactorEnd->GetTextCtrl()->GetValue().ToDouble(&m_params.end);
if (!read_double ||
m_params.freqStartX < 0 || m_params.freqStartX > 500 ||
m_params.freqStartY < 0 || m_params.freqStartY > 500 ) {
(!reprap_firmware && (m_params.freqStartY < 0 || m_params.freqStartY > 500))) {
MessageDialog msg_dlg(nullptr, _L("Please input valid values:\n(0 < Freq < 500)"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
@ -993,6 +1159,16 @@ void Input_Shaping_Damp_Test_Dlg::on_start(wxCommandEvent& event) {
return;
}
auto shaper_values = get_shaper_type_values();
int type_selection = m_rbType->GetSelection();
if (shaper_values.empty()) {
m_params.shaper_type.clear();
} else {
if (type_selection < 0 || type_selection >= static_cast<int>(shaper_values.size()))
type_selection = 0;
m_params.shaper_type = shaper_values[static_cast<size_t>(type_selection)];
}
m_params.mode = CalibMode::Calib_Input_shaping_damp;
// Set model type based on selection

View file

@ -134,6 +134,7 @@ protected:
Calib_Params m_params;
RadioGroup* m_rbModel;
RadioGroup* m_rbType;
TextInput* m_tiFreqStartX;
TextInput* m_tiFreqEndX;
TextInput* m_tiFreqStartY;
@ -155,6 +156,7 @@ protected:
Calib_Params m_params;
RadioGroup* m_rbModel;
RadioGroup* m_rbType;
TextInput* m_tiFreqX;
TextInput* m_tiFreqY;
TextInput* m_tiDampingFactorStart;