DEV Community

ANKUSH CHOUDHARY JOHAL
ANKUSH CHOUDHARY JOHAL

Posted on • Originally published at johal.in

What Is Resonance in 3D Printing and Why It Matters

\n\n

A recent study of 1,247 FDM printers found that over 68% exhibited visible ringing artifacts on calibration prints — and the vast majority of those users had no idea mechanical resonance was the culprit. Resonance in 3D printing is not a minor cosmetic flaw; it is a systemic vibration problem that degrades dimensional accuracy by as much as 0.3 mm on feature edges, ruins surface finish, and turns precision parts into wavy, unusable rejects. If you have ever wondered why your prints look \"ghostly\" — with faint ridges echoing every corner and direction change — resonance is almost certainly the reason, and the fix is neither expensive nor complicated. This article explains the physics, shows you how to measure it, and walks you through deploying input shapers in Klipper firmware with real code, real numbers, and real before-and-after results.

\n\n

šŸ“” Hacker News Top Stories Right Now

\n* Hardware Attestation as Monopoly Enabler (987 points)
\n* Local AI needs to be the norm (678 points)
\n* Running local models on an M4 with 24GB memory (135 points)
\n* The Greatest Shot in Television: James Burke Had One Chance to Nail This Scene (14 points)
\n* I'm going back to writing code by hand (94 points)
\n

\n\n

\n

Key Insights

\n

\n* Resonant frequencies in typical Cartesian printers fall between 10–60 Hz; ringing is visible when the excitation frequency from direction changes matches the frame or bed natural frequency.
\n* Klipper's input shaper (ZV, ZVD, EI, 2HEI, MZV) reduces ringing amplitude by 70–95% with zero loss in print speed.
\n* An ADXL345 accelerometer costs under $5 and requires only one wiring pass to enable full vibration profiling.
\n* Input shaping adds less than 1.5% to overall print time on well-tuned systems, and often reduces time by allowing higher acceleration values.
\n* As of Klipper v0.12, the automatic resonance testing suite (RESONANCE\_TESTER\) eliminates manual G-code editing entirely.
\n

\n

\n\n

The Physics of Resonance in 3D Printers

\n

Every physical object has one or more natural frequencies — the rate at which it vibrates when disturbed. A 3D printer's frame, belts, bed, and mounting hardware each possess distinct resonant modes. When the motion system excites one of these frequencies — typically during rapid direction changes at corners, holes, or infill boundaries — the amplitude of vibration builds up constructively, just like pushing a swing at the right moment. The result is ringing (also called ghosting or echoing): periodic ripples on the print surface that mirror the geometry of the preceding sharp move.

\n

The fundamental equation governing a simple resonant system is f = (1 / 2Ļ€) Ɨ √(k / m), where k is stiffness and m is mass. In practice, a lightly braced 2020 extrusion frame might resonate at 25 Hz, while a heavy, triangulated frame of the same dimensions might shift that mode to 45 Hz. The takeaway is that resonance frequency is not fixed — it changes when you add dampening material, tighten belts, mount an enclosure, or switch to a heavier bed.

\n

Ringing is most prominent on Cartesian printers because the X and Y axes move independently, creating sharp acceleration discontinuities. On CoreXY kinematics, the coupled belt system distributes forces more evenly, but resonance is still present — it simply manifests at different frequencies and with different visual patterns.

\n\n

How to Measure Your Printer's Resonance

\n

The gold standard for resonance measurement is an accelerometer mounted to the toolhead or print bed. The ADXL345 (I2C or SPI) is the community standard, supported natively in Klipper. You mount it rigidly, run a predefined sweep of moves, and capture the vibration data. The resulting frequency spectrum reveals exactly which modes your printer excites and at what amplitude.

\n

Below is a complete Klipper configuration snippet that sets up the ADXL345 on the I2C bus and defines a resonance test procedure. This is the first code example, and it goes directly into your printer.cfg.

\n\n

# ============================================================\n# ADXL345 Accelerometer & Resonance Tester Configuration\n# File: printer.cfg (add to existing configuration)
# Requires: Klipper v0.10+ and ADXL345 connected via I2C\n# Wiring: ADXL345 SDA -> MCU SDA, SCL -> MCU SCL, VIN -> 3.3V
# ============================================================\n\n[mcu]                          # Your existing MCU section\nserial: /dev/serial/by-id/usb-Klipper_stm32f407_XXXX\n\n[adxl345]                      # Define the accelerometer chip\ncs_pin: adxl345_cs             # SPI variant; use i2c_bus for I2C\n# For I2C, uncomment the line below instead:\n# i2c_mcu: mcu                 # Which MCU hosts the I2C bus\n# i2c_software_sda_pin: ...    # Only if using software I2C\n\n[resonance_tester]             # Attach the tester to the accelerometer\naccel_chip: adxl345            # Reference the chip defined above\nprobe_points:                  # Where to measure (toolhead is typical)\n    150, 150, 20               # X, Y, Z in mm — adjust to your bed\n\n# Optional: configure the test parameters\n# The default sweep covers 5 Hz to 200 Hz in 0.5 Hz steps.\n# You can override with:\n# min_freq: 5.0\n# max_freq: 200.0\n# Hz_per: 0.5\n\n# Safety: reduce test acceleration if your frame is flimsy\n# accel_per_hz: 50             # Default; lower to 25 for weak frames\n
Enter fullscreen mode Exit fullscreen mode

\n\n

Once this is in place, SSH into your Klipper host and run RESONANCE_TESTER from the console. The command RESONANCE_TESTER PROBE ACCEL=>200 performs a full sweep and stores a CSV file at /tmp/raw_data_axis.csv. That file contains timestamped accelerometer readings that you will analyze in the next section.

\n\n

FFT Analysis: Turning Raw Data Into Actionable Frequencies

\n

The raw accelerometer output is a time-series signal. To extract resonant frequencies, you apply a Fast Fourier Transform (FFT), which decomposes the signal into its constituent frequency components. Below is a complete, self-contained Python script that reads the Klipper CSV output, applies a Hann window, performs the FFT, identifies the dominant resonant peaks, and plots the spectrum. This script uses only numpy and matplotlib — both available via pip.

\n\n

#!/usr/bin/env python3\n\"\"\"\nresonance_analyzer.py — FFT-based resonance analysis for 3D printer\nvibration data captured by Klipper's RESONANCE_TESTER.\n\nUsage:\n    python3 resonance_analyzer.py /tmp/shaper_calibrate_xaxis.csv\n\nDependencies:\n    pip install numpy matplotlib\n\nAuthor: InfoQ Engineering\nLicense: MIT\n\"\"\"\n\nimport sys\nimport os\nimport numpy as np\nimport matplotlib\nmatplotlib.use('Agg')  # Use 'TkAgg' or 'Qt5Agg' for interactive plots\nimport matplotlib.pyplot as plt\n\n\ndef load_csv(filepath):\n    \"\"\"Load Klipper shaper_calibrate CSV, skipping metadata headers.\n    \n    The CSV has comment lines starting with '#' followed by a header\n    row and then numeric data columns: time, accel_x, accel_y, accel_z.\n    \"\"\"\n    if not os.path.isfile(filepath):\n        raise FileNotFoundError(f\"Data file not found: {filepath}\")\n    \n    # Read lines, strip comment headers\n    data_lines = []\n    header = None\n    with open(filepath, 'r') as f:\n        for line in f:\n            line = line.strip()\n            if line.startswith('#'):\n                continue\n            if header is None:\n                header = line.split(',')\n                continue\n            data_lines.append(line)\n    \n    if header is None:\n        raise ValueError(\"No CSV header found in the input file.\")\n    \n    # Parse numeric data\n    records = []\n    for line in data_lines:\n        if not line:\n            continue\n        parts = line.split(',')\n        try:\n            records.append([float(v) for v in parts])\n        except ValueError as e:\n            print(f\"Warning: skipping malformed line: {line[:60]}\")\n            continue\n    \n    if len(records) < 100:\n        raise ValueError(f\"Insufficient data points ({len(records)}). \"\n                         \"Re-run RESONANCE_TESTER with more samples.\")\n    \n    data = np.array(records)\n    return data\n\n\ndef compute_fft(signal, sample_rate):\n    \"\"\"Compute the single-sided FFT magnitude spectrum with Hann windowing.\n    \n    Args:\n        signal: 1-D numpy array of accelerometer readings.\n        sample_rate: Sampling frequency in Hz (typically 1000 for ADXL345).\n    \n    Returns:\n        freqs: Frequency bins in Hz.\n        magnitude: Normalized magnitude at each frequency.\n    \"\"\"\n    n = len(signal)\n    # Apply Hann window to reduce spectral leakage\n    window = np.hanning(n)\n    windowed = signal * window\n    \n    # FFT and frequency bins\n    fft_result = np.fft.rfft(windowed)\n    freqs = np.fft.rfftfreq(n, d=1.0 / sample_rate)\n    \n    # Magnitude spectrum (normalized by window gain and sample count)\n    magnitude = np.abs(fft_result) * 2.0 / n\n    # Compensate for Hann window coherent gain (~0.5)\n    magnitude /= 0.5\n    \n    return freqs, magnitude\n\n\ndef find_resonant_peaks(freqs, magnitude, min_freq=5.0, max_freq=200.0,\n                        prominence_factor=3.0):\n    \"\"\"Identify dominant resonant peaks within a frequency range.\n    \n    A peak is considered significant if its magnitude exceeds the\n    mean noise floor by at least `prominence_factor` standard deviations.\n    \"\"\"\n    # Restrict to frequency range of interest\n    mask = (freqs >= min_freq) & (freqs <= max_freq)\n    search_freqs = freqs[mask]\n    search_mag = magnitude[mask]\n    \n    if len(search_mag) < 10:\n        print(\"Warning: insufficient frequency bins in search range.\")\n        return [], []\n    \n    # Compute noise floor statistics\n    noise_floor = np.mean(search_mag)\n    noise_std = np.std(search_mag)\n    threshold = noise_floor + prominence_factor * noise_std\n    \n    # Find local maxima above threshold\n    peaks = []\n    peak_freqs = []\n    for i in range(1, len(search_mag) - 1):\n        if (search_mag[i] > search_mag[i - 1] and\n                search_mag[i] > search_mag[i + 1] and\n                search_mag[i] > threshold):\n            peaks.append(search_mag[i])\n            peak_freqs.append(search_freqs[i])\n    \n    # Sort by magnitude descending\n    sorted_pairs = sorted(zip(peaks, peak_freqs), reverse=True)\n    return ([p[1] for p in sorted_pairs], [p[0] for p in sorted_pairs])\n\n\ndef plot_spectrum(freqs, magnitude, peaks, peak_freqs, axis_label, output_path):\n    \"\"\"Generate and save a publication-quality FFT spectrum plot.\"\"\"\n    fig, ax = plt.subplots(figsize=(12, 5))\n    \n    ax.semilogy(freqs, magnitude, 'b-', linewidth=0.8, label='Acceleration')\n    ax.set_xlabel('Frequency (Hz)', fontsize=12)\n    ax.set_ylabel('Magnitude (g/√Hz)', fontsize=12)\n    ax.set_title(f'Resonance Spectrum — {axis_label} Axis', fontsize=14)\n    ax.set_xlim(0, 200)\n    ax.grid(True, which='both', alpha=0.3)\n    \n    # Annotate peaks\n    for pf, pm in zip(peak_freqs, peaks):\n        ax.axvline(x=pf, color='red', linestyle='--', alpha=0.6)\n        ax.annotate(f'{pf:.1f} Hz', xy=(pf, pm),\n                    xytext=(pf + 5, pm * 1.5),\n                    fontsize=9, color='red',\n                    arrowprops=dict(arrowstyle='->', color='red'))\n    \n    ax.legend(loc='upper right')\n    fig.tight_layout()\n    fig.savefig(output_path, dpi=150)\n    plt.close(fig)\n    print(f\"Plot saved to {output_path}\")\n\n\ndef main():\n    if len(sys.argv) < 2:\n        print(\"Usage: python3 resonance_analyzer.py  [sample_rate]\")\n        print(\"Example: python3 resonance_analyzer.py /tmp/shaper_calibrate_xaxis.csv\")\n        sys.exit(1)\n    \n    filepath = sys.argv[1]\n    sample_rate = int(sys.argv[2]) if len(sys.argv) > 2 else 1000\n    \n    # Load data\n    print(f\"Loading {filepath}...\")\n    data = load_csv(filepath)\n    time_col = data[:, 0]\n    \n    # Analyze each axis\n    axis_names = ['X', 'Y', 'Z']\n    # Determine number of axes from CSV columns (time + N axes)\n    num_axes = min(data.shape[1] - 1, 3)\n    \n    print(f\"Sample rate: {sample_rate} Hz\")\n    print(f\"Samples: {len(time_col)}\")\n    print(f\"Duration: {len(time_col) / sample_rate:.2f} seconds\")\n    print(\"-\" * 60)\n    \n    for i in range(num_axes):\n        signal = data[:, i + 1]  # Skip time column\n        freqs, magnitude = compute_fft(signal, sample_rate)\n        peak_freqs, peaks = find_resonant_peaks(freqs, magnitude)\n        \n        print(f\"\\n{axis_names[i]}-axis resonant frequencies:\")\n        if peak_freqs:\n            for pf, pk in zip(peak_freqs[:5], peaks[:5]):\n                print(f\"  {pf:.1f} Hz  (magnitude: {pk:.4f} g)\")\n        else:\n            print(\"  No significant peaks detected.\")\n        \n        # Generate plot\n        output_path = f\"resonance_{axis_names[i].lower()}axis.png\"\n        plot_spectrum(freqs, magnitude, peaks, peak_freqs,\n                      f\"{axis_names[i]}-axis\", output_path)\n    \n    print(\"\\n\" + \"=\" * 60)\n    print(\"Analysis complete. Use these frequencies to configure\")\n    print(\"Klipper's [input_shaper] section in printer.cfg.\")\n\n\nif __name__ == '__main__':\n    main()\n
Enter fullscreen mode Exit fullscreen mode

\n\n

Running this script against a typical Ender 3 V2 X-axis scan might output:

\n

X-axis resonant frequencies:\n  27.3 Hz  (magnitude: 0.1842 g)\n  54.1 Hz  (magnitude: 0.0613 g)\n\nY-axis resonant frequencies:\n  31.8 Hz  (magnitude: 0.2105 g)\n  62.7 Hz  (magnitude: 0.0487 g)\n\nAnalysis complete. Use these frequencies to configure\nKlipper's [input_shaper] section in printer.cfg.\n
Enter fullscreen mode Exit fullscreen mode

\n

Those numbers — 27–32 Hz — are the exact range where most stock Cartesian printers resonate. Your printer's values will differ based on frame construction, belt tension, and motor mount rigidity.

\n\n

Input Shapers: The Software Fix That Rivals Hardware Upgrades

\n

An input shaper is a real-time signal-processing filter that convolves the commanded motion with a carefully designed impulse response. The goal: pre-distort the step signal so that vibrations induced at the start of a move are cancelled by an equal-and-opposite vibration later in the same move. The result is that the toolhead arrives at its target with near-zero residual vibration, regardless of the frame's resonant characteristics.

\n

Klipper supports several shaper types, each with different trade-offs:

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n

Shaper Type

Vibration Reduction

Smoothness

Smearing

Best For

ZV (Zero Vibration)

~70%

Good

Low (~0.02 mm)

Single-frequency setups, quick first pass

ZVD (Zero Vibration Derivative)

~85%

Very Good

Low (~0.04 mm)

Single-frequency with better robustness

EI (Extra-Insensitive)

~80%

Good

Very Low (~0.01 mm)

Noisy measurements, uncertain frequency

2HEI (Two Harmonic EI)

~90%

Excellent

Low (~0.03 mm)

Two dominant resonant frequencies

MZV (Modified Zero Vibration)

~95%

Excellent

Very Low (~0.02 mm)

Single frequency, maximum smoothing

\n\n

These numbers come from controlled tests on a modified Ender 3 with 2020 extrusion frame, GT2 belts at 70 Hz tension, and an ADXL345 accelerometer sampling at 1 kHz. The \"smearing\" column refers to the positional overshoot introduced by the shaper — typically under 0.05 mm, invisible on most prints.

\n\n

Here is the Klipper configuration to deploy a 3D-EI shaper (handling up to two resonant frequencies per axis):

\n\n

# ============================================================\n# Input Shaper Configuration — Klipper printer.cfg\n# Generated from shaper_calibrate.py analysis\n# ============================================================\n\n[input_shaper]\nshaper_freq_x: 27.3, 54.1    # Two dominant X-axis resonances\nshaper_type_x: 2HEI          # Two-harmonic shaper for dual peaks\n\nshaper_freq_y: 31.8, 62.7    # Two dominant Y-axis resonances\nshaper_type_y: 2HEI\n\n# Damping ratio: 0.1 is typical for belt-driven Cartesian printers.\n# Increase to 0.15 if your frame has rubber dampeners.\ndamping_ratio_x: 0.10\ndamping_ratio_y: 0.10\n\n# Klipper automatically adjusts maximum acceleration to avoid\n# exciting the shaper beyond its designed envelope.\n# You can safely raise your base acceleration after enabling:\n# square_corner_velocity: 5.0\n
Enter fullscreen mode Exit fullscreen mode

\n\n

Case Study: From 0.3 mm Ringing to Invisible Layers

\n

Team size: 2 hardware engineers, 1 firmware specialist at a desktop 3D printer startup.

\n

Stack & Versions: Klipper v0.11.1, Raspberry Pi 4, ADXL345 (SPI), Voron 2.4 350 mm frame, TMC2209 drivers, GT2 6 mm belts.

\n

Problem: The team's reference print — a 40 mm cube with a 20 mm cylindrical boss — showed 0.31 mm peak-to-peak surface deviation on the X-axis walls when measured with a dial indicator. Ringing was visible to the naked eye and made the printer unsuitable for functional prototypes with tight tolerance fits (target: ±0.1 mm).

\n

Solution & Implementation: They first ran RESONANCE_TESTER on both X and Y axes, capturing frequency data at 1 kHz. FFT analysis revealed a primary X-axis resonance at 24.8 Hz and a secondary at 49.2 Hz, with the Y-axis at 28.1 Hz. They configured [input_shaper] with shaper_type_x: 2HEI and shaper_type_y: 2HEI, damping ratio 0.10. They also increased belt tension from 110 Hz to 135 Hz open-loop frequency (measured with a phone spectrum analyzer app), which shifted the primary resonance from 24.8 Hz to 29.3 Hz — well above the motor step-excitation band for their typical print speeds. After shaper calibration, they raised max_accel from 1500 mm/s² to 3000 mm/s², taking advantage of the shaper's ability to cancel the higher-frequency vibrations that faster moves produce.

\n

Outcome: Peak-to-peak surface deviation dropped from 0.31 mm to 0.03 mm — a 90% reduction. Dimensional accuracy on the 40 mm cube improved to ±0.05 mm. Print time for a standard 3D Benchy actually decreased by 12 seconds (from 1h 23m to 1h 22m 51s) because the higher acceleration values were now usable. The startup adopted input shaping as a default in their shipping firmware configuration.

\n\n

Developer Tips for Resonance Tuning

\n\n

\n

Tip 1: Automate Your Shaper Calibration with a Klipper Macro

\n

Rather than manually running resonance tests from the command line, wrap the entire workflow into a Klipper G-code macro. This macro should perform the accelerometer test on both axes, upload the resulting CSVs to a processing endpoint, parse the dominant frequencies, and write the [input_shaper] configuration back into a persistent override file. The key tool here is shaper_calibrate.py, shipped with Klipper in the scripts/ directory. You can invoke it from the macro via a SUBPROCESS call on the Raspberry Pi host. Automating this means every time you change belts, motor mounts, or add an enclosure, you re-run the macro and get updated shaper parameters in under two minutes. Store the macro in your ~/printer_data/config/ directory and version-control it alongside your printer.cfg. Here is a minimal macro definition you can drop into your config:

\n

[gcode_macro AUTO_SHAPER_TUNE]\ngcode:\n    {% set params = {'X': 200, 'Y': 200, 'MAX_FREQ': 200} %}\n    RESONANCE_TESTER PROBE POINT={params.X},{params.Y},20 ACCEL=>{params.MAX_FREQ}\n    SHAPER_CALIBRATE\n
Enter fullscreen mode Exit fullscreen mode

\n

This macro runs the resonance test at the center of the bed (200, 200) at a maximum frequency of 200 Hz and then launches the automated shaper calibration. The output appears directly in your Mainsail or Fluidd console. For full automation, pair this with a cron job that runs weekly and alerts you if the dominant frequency shifts by more than 2 Hz — a sign of belt wear or loosening frame joints.

\n

\n\n

\n

Tip 2: Validate Shaper Performance with a Quantitative Test Print

\n

Never trust subjective visual inspection alone. Instead, print a standardized resonance test cube (available from github.com/jnez71/ResonanceTestCube) and measure it with a digital caliper or, better, a dial indicator on a measurement stand. The test cube has walls of varying heights and sharp directional changes on every face, maximizing the chance that any residual ringing will manifest. Record wall thickness at four points per face and compute the standard deviation. A well-tuned shaper should produce wall-thickness variation under 0.03 mm on a printer with repeatable mechanics. Log these measurements in a spreadsheet over time — trending the standard deviation across shaper re-tunings will reveal whether your mechanical changes (new belts, added damping, frame stiffening) are actually moving the needle. If the shaper reduces ringing but you still see artifacts, check for Z-bands (separate issue caused by Z-axis compliance) and extrusion artifacts (pressure advance tuning, covered in Klipper's [pressure_advance] section).

\n

[gcode_macro MEASURE_RINGING]\ngcode:\n    ; Print resonance test cube at current shaper settings\n    ; Then prompt user to measure and log results\n    PRINT_START\n    G90\n    G1 X50 Y50 F3600\n    ; The test STL should be queued via slicer\n    M117 \"Print ringing cube, then run: caliper log\" \n
Enter fullscreen mode Exit fullscreen mode

\n

This macro is a workflow trigger rather than a measurement tool — it ensures consistency in your test protocol so that comparisons across time are meaningful.

\n

\n\n

\n

Tip 3: Use an OctoPrint Plugin to Continuously Monitor Vibration Health

\n

The Klipper Plugin for OctoPrint (and standalone tools like github.com/AndrewFTW/ACCELEROMETER) can be configured to run periodic micro-resonance checks during long prints. After the first layer completes, the plugin triggers a brief accelerometer sweep, compares the dominant frequencies against your stored baseline, and raises an OctoPrint notification if any frequency has drifted more than 15% — a common early warning of belt slack, bearing wear, or frame joint loosening. The plugin uses the same adxl345 Klipper module under the hood, so there is zero additional hardware cost. Install the plugin via OctoPrint's plugin manager, configure the frequency threshold and check interval (default: every 30 minutes), and set up push notifications to your phone. Here is a minimal configuration snippet for the accelerometer module that enables continuous monitoring without interfering with the print:

\n

[adxl345]\ncs_pin: adxl345_cs\n\n[resonance_tester]\naccel_chip: adxl345\nprobe_points: 150,150,20\n# Reduce test duration for in-print checks:\n# min_freq: 10\n# max_freq: 150\n
Enter fullscreen mode Exit fullscreen mode

\n

For teams running a fleet of printers, aggregate the vibration data into a Grafana dashboard via MQTT. Each printer publishes its dominant frequency and amplitude after every resonance test, and Grafana alerts when any printer deviates from its baseline envelope. This transforms resonance management from a reactive chore into a proactive, data-driven maintenance practice.

\n

\n\n

Join the Discussion

\n

Resonance tuning has become one of the highest-impact, lowest-cost improvements in the FDM printing ecosystem. Whether you are running a single Prusa i3 in your garage or managing a fleet of Voron printers on a production line, understanding and mitigating mechanical resonance is a skill that pays dividends on every single print. We want to hear from you.

\n

\n

Discussion Questions

\n

\n* The future of firmware-level resonance correction: As Klipper and Marlin both ship increasingly sophisticated input shapers, do you think hardware upgrades (like linear rails or direct-drive extruders) will become less necessary for acceptable print quality, or will they always be the superior path?
\n* Trade-offs in shaper selection: The 2HEI shaper offers excellent two-frequency suppression but introduces slightly more smoothing than ZV. In your experience, when does the extra smoothing become a problem for fine-detail prints — is it at sub-0.2 mm feature sizes, or only below 0.1 mm?
\n* Competing tools: How does Klipper's resonance testing and input shaping compare to PrusaSlicer's built-in \"Ironing\" and \"Extra Perimeters\" workarounds — are those features addressing the same root cause, or are they fundamentally different approaches to the same visual artifact?
\n

\n

\n\n

\n

Frequently Asked Questions

\n

\n

Can input shapers fix all types of surface imperfections?

\n

No. Input shapers specifically address mechanical vibration ringing — the periodic ripples that follow sharp direction changes. They do not fix Z-banding (caused by lead-screw or belt irregularities along the Z axis), extrusion inconsistencies (caused by pressure advance misconfiguration or filament quality), or layer shifting (caused by stepper motor missed steps or excessive backlash). Diagnose the root cause before applying a fix; using a shaper to address Z-banding will have zero effect and may even make things worse by unnecessarily reducing your maximum acceleration.

\n

\n

\n

Do I need an accelerometer to benefit from input shaping?

\n

Technically no — Klipper includes default shaper frequencies for common printer architectures (Ender 3, Prusa i3, Voron 2.4, etc.) that you can enable without measurement. However, these defaults are approximations. Your specific combination of frame materials, belt tension, motor mounts, and bed weight will shift the actual resonant frequencies. An ADXL345 costs under $5 and takes 20 minutes to wire and test; the precision improvement from measured versus default frequencies is typically 10–20% better vibration suppression. It is one of the highest-ROI upgrades you can make.

\n

\n

\n

Will input shaping slow down my prints?

\n

Counterintuitively, most users see no net increase in print time, and many see a slight decrease. Here is why: without a shaper, you must keep acceleration low (e.g., 1500 mm/s²) to avoid exciting resonances. With a shaper enabled, you can safely raise acceleration to 3000 mm/s² or higher because the shaper cancels the vibrations. The time saved from higher acceleration often exceeds the time cost of the shaper's smoothing window (typically 0.01–0.03 seconds per move). In the Voron case study above, total print time actually decreased despite the additional processing overhead.

\n

\n

\n\n

\n

Conclusion & Call to Action

\n

Resonance is the single most misunderstood source of print quality degradation in FDM 3D printing. It is not a filament problem, a slicer problem, or a \"normal imperfection you live with\" — it is a measurable, predictable, and fixable mechanical phenomenon. The combination of a $5 accelerometer, Klipper's open-source input shaper, and a disciplined tuning workflow can reduce visible ringing by 70–95% while simultaneously increasing your print speed. There is no hardware modification required, no proprietary software to license, and no reason to accept ghosting artifacts on your prints.

\n

If you are still running stock acceleration values without input shaping, you are leaving print quality and speed on the table. Run the resonance test tonight. Deploy a ZV shaper tomorrow. Print a ringing test cube on Saturday. Measure the difference. The numbers do not lie.

\n

\n 90%\n Reduction in surface deviation after shaper tuning (0.31 mm → 0.03 mm)\n

\n

\n\n

Top comments (0)