Input shaping is the one Klipper feature that turns a measurement into a configuration value with no guesswork in between. An accelerometer on the toolhead produces a resonance profile per axis, and Klipper’s calibration script reads that profile and recommends a shaper type, a frequency, and an acceleration ceiling. The setup is short. The failures are specific, and almost all of them happen before any useful data is collected.
This walks the procedure documented by the Klipper project, in the order the machine will actually make you do it, with the errors that interrupt each step.
Before You Wire Anything
Resonance compensation reduces the visible effect of vibration. It does not compensate for a loose belt, a flexing gantry, or a toolhead that rocks on its carriage. Measuring a machine that is mechanically unsound produces a clean graph of a problem you should have fixed instead.
Three things should be true first:
- Belts tensioned and consistent, frame square, gantry not flexing under hand pressure.
- Kinematics and motor directions confirmed. On CoreXY both motors contribute to both axes, so a mirrored motor shows up as skew rather than as an obvious single-axis fault.
- Extruder rotation distance and flow calibrated, and pressure advance tuned. Otherwise every later artefact gets blamed on the wrong subsystem.
For the host’s role in motion planning and configuration, see how Klipper works. If you have not chosen an accelerometer or a place to plug it in yet, Klipper hardware requirements covers the options.
Step 1: Host Prerequisites
The resonance-analysis scripts use NumPy and Matplotlib in the host’s system Python. Klipper’s automatic calibration also needs NumPy in its separate Python virtual environment, ~/klippy-env. Installing the system packages alone does not install NumPy there. Follow the Klipper software installation procedure, starting with the system dependencies:
sudo apt update
sudo apt install python3-numpy python3-matplotlib libatlas-base-dev libopenblas-dev
Then install NumPy in Klipper’s environment and check that its Python interpreter can import it. Resolve any import error before running SHAPER_CALIBRATE:
~/klippy-env/bin/pip install -v "numpy<1.26"
~/klippy-env/bin/python -c 'import numpy;'
If the sensor is going to hang off the host’s own SPI pins rather than the printer’s control board, SPI has to be enabled on the host and Klipper needs a second microcontroller target built for the host itself. Klipper calls this the Linux process microcontroller, and it exists precisely so the host can own SPI devices like an accelerometer without spending pins on the printer board.
Step 2: Wiring
The ADXL345 is an SPI device. Four signal lines plus power and ground: chip select, clock, and the two data lines. Two details cause most of the trouble:
Voltage. Most breakout boards are 3.3V parts. Feeding one 5V, or driving its inputs from 5V logic, is the fastest way to a sensor that reads garbage or nothing at all.
Mounting. The sensor measures whatever it is bolted to. A rigid mount directly on the toolhead is the goal; a sensor taped to a cable or dangling from a zip tie measures the tape and the zip tie. On machines whose bed moves in Y, the bed needs its own measurement, so plan for a second mounting position rather than a single permanent one.
Keep the cable routed so it is not being whipped by the toolhead during the test. Cable noise shows up in the data and is easy to mistake for a resonance.
For a machine-specific mounting walkthrough, see ADXL345 mounting on a Voron 2.4 gantry, then return here for the generic Klipper commands.
Step 3: Configuration
With the sensor on the host’s SPI bus, the configuration is three stanzas. The Klipper documentation gives this shape:
[mcu rpi]
serial: /tmp/klipper_host_mcu
[adxl345]
cs_pin: rpi:None
[resonance_tester]
accel_chip: adxl345
probe_points:
100, 100, 20
probe_points is a coordinate near the middle of the bed at a safe height. The toolhead moves there and shakes in place, so give it room and make sure nothing on the bed is in the way.
If the sensor is wired to the printer’s control board instead of the host, the [mcu rpi] section is unnecessary and cs_pin names a pin on that board. If the machine has an accelerometer at both the toolhead and the bed, Klipper supports naming each chip and pointing the tester at the right one per axis.
Restart the firmware after saving, and confirm Klipper starts cleanly before going further.
Step 4: Verify the Sensor Answers
Two commands, in this order, from the console in your web front end:
ACCELEROMETER_QUERY
MEASURE_AXES_NOISE
ACCELEROMETER_QUERY returns a single reading. On a stationary printer it should be roughly one g on the vertical axis and near zero on the other two. If the numbers are wildly wrong or the command errors, stop here; nothing downstream will be meaningful.
MEASURE_AXES_NOISE reports the background noise on each axis with the machine idle. The Klipper documentation describes good values as being on the order of 1 to 100. Values far above that mean the sensor is picking up something other than the machine’s structure, and the usual culprits are power supply noise, a long unshielded cable, or a fan running near the sensor.
Step 5: Measure and Calibrate
TEST_RESONANCES AXIS=X
TEST_RESONANCES AXIS=Y
Each command sweeps the toolhead through a frequency range and writes a CSV to /tmp on the host. That data can be plotted with the project’s calibrate_shaper.py script, which produces a graph of response against frequency and prints a recommended shaper and frequency.
For the shorter path, Klipper can do the measurement and the recommendation in one step and write the result straight into the configuration:
SHAPER_CALIBRATE
SAVE_CONFIG
SAVE_CONFIG stores the chosen values in an autosave block at the end of printer.cfg and restarts Klipper. Active settings in the regular configuration, including included files, take precedence over duplicate autosave values. When checking a manual edit, confirm that the setting is active rather than commented out, inspect included files, and restart Klipper after saving.
SHAPER_CALIBRATE accepts a MAX_SMOOTHING argument. Constraining smoothing biases the recommendation toward shapers that cost less detail, at the price of leaving more vibration unsuppressed. It is the right knob when the default recommendation produces visibly softened corners.
Step 6: Read the Result Like a Trade, Not a Score
The output names a shaper type and a frequency per axis, which end up as an [input_shaper] section. The values below are placeholders to show the shape of the block, not numbers to copy:
[input_shaper]
shaper_freq_x: 52.4
shaper_type_x: mzv
shaper_freq_y: 38.1
shaper_type_y: ei
Shapers differ in how much vibration they cancel and how much smoothing they impose to do it. More aggressive suppression tolerates a wider error in the frequency estimate but costs more smoothing, and smoothing costs effective acceleration and fine detail. A lower resonant frequency makes every option worse, which is why a heavy toolhead or a flexible gantry is a mechanical problem that no shaper choice repairs.
Acceleration is where that trade becomes a number you have to set. Use the input shaper and acceleration sizer to see how a measured frequency and a shaper choice constrain usable acceleration before committing a max_accel, then verify against what the calibration script itself recommended for your machine. The script’s recommendation is the authority; the sizer is for understanding the shape of the trade-off quickly.
Print a ringing test after saving. The graph says the resonance was suppressed; the print says whether the result is what you wanted.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
An invalid chip id error on ACCELEROMETER_QUERY | Wrong CS pin, SPI not enabled on the host, miswired data lines, or a board that is not actually an ADXL345 | Re-check the CS pin name, confirm SPI is enabled, verify the two data lines are not swapped |
| Klipper will not start after adding the config | Missing host microcontroller target, or a typo in a section name | Confirm the host process microcontroller is built and running before adding [adxl345] |
calibrate_shaper.py exits immediately | numpy or matplotlib missing on the host | Install both, then re-run against the CSV already in /tmp |
| Noise values far above the documented range | Cable routing, an unshielded run, or a fan near the sensor | Shorten and route the cable away from motors, re-measure with fans off to isolate |
| Both axes return near-identical peaks | Sensor is measuring the frame rather than the toolhead | Re-mount rigidly to the moving mass |
| Recommendation changes every run | Sensor mount is not rigid, or belts moved between runs | Fix the mount first; an unrepeatable measurement is not a measurement |
| Values edited by hand have no effect | The edited setting is commented out, an included file defines it, or Klipper has not restarted | Check active versus commented [input_shaper] settings in printer.cfg and included files, then save and restart Klipper |
When to Measure Again
The resonance profile belongs to a specific machine in a specific state. Remeasure after anything that changes moving mass or frame stiffness: a new hotend or toolhead, a different carriage, retensioned belts, a rebuilt gantry, or moving the printer to a different surface. Copying shaper values from another machine of the same model is the one shortcut that reliably wastes the whole exercise, because the values encode that machine’s mass and stiffness rather than the model’s.
If you are still weighing whether this workflow justifies running Klipper at all, the measurement pipeline described here is the clearest difference between the two options in Klipper vs Marlin.