Klipper Input Shaper Setup: Wiring and Tuning an ADXL345
Wiring, configuration, and calibration commands for measuring resonance with an ADXL345 in Klipper, plus fixes for the errors that stop a run.
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.
The reasoning behind that ordering is covered in Klipper firmware architecture and input shaper tuning. 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 calibration scripts run on the host and depend on numpy and matplotlib. Install them before wiring, because the usual sequence is that the sensor answers queries perfectly and then the analysis script exits on an import error twenty minutes later.
sudo apt update
sudo apt install python3-numpy python3-matplotlib
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.
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 appends the chosen values to an autosave block at the end of printer.cfg and restarts the firmware. Know that this block exists and that it overrides what you wrote by hand higher up in the file, because a value you edited manually and cannot make take effect is usually being overridden down there.
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 | An autosave block at the end of printer.cfg is overriding them | Edit or remove the autosave entry, then restart |
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.
Sources
Related
Klipper Hardware Requirements: SBC, MCU, and Sensors
What Klipper actually needs to run: a Linux host, a supported control board, an accelerometer for input shaping, and the wiring between them.
Klipper vs Marlin: Which Firmware Should You Run?
A spec-level comparison of Klipper and Marlin: where motion is computed, how each is configured, what tuning features ship, and who each one suits.
Klipper Firmware Architecture and Input Shaper Tuning
How Klipper splits motion planning between the host and the MCU, and how to tune pressure advance and input shaping in the order that works.