Why CoreXY printers need separate X and Y input shaper calibration
If your CoreXY firmware copies the Y-axis shaper result onto X after one calibration run, that's mechanically wrong — different mass, different belt path, different damping. Three reasons CoreXY isn't symmetric, plus how to disable Creality's silent copy on the K2.
A CoreXY printer doesn't have an X motor and a Y motor in the way a bedslinger does. It has two motors that together drive both axes through a coupled belt path. Move motor A alone and the toolhead goes diagonally. Move both motors in opposite directions and it goes purely along one axis. This coupling is what makes CoreXY fast — both motors contribute to every move, so peak acceleration scales — but it's also why "X and Y are the same" intuition is wrong.
That intuition is baked into one piece of stock Creality K2 firmware behaviour, and it's worth understanding why it's wrong even if you don't own a K2.
A two-paragraph CoreXY refresher
Skip this if you already know.
On a Cartesian bedslinger (Ender 3, Prusa, etc.) the X motor moves the toolhead and the Y motor moves the bed. The two axes have completely different masses and different mounting structures, but each motor only ever drives one axis. Resonance on X and Y just happens to be different because the moving parts are different.
On CoreXY, both motors mount to the frame and drive a pair of crossed belts that loop around idler pulleys. The toolhead rides on the belts. To move +X, both motors spin the same direction. To move +Y, they spin opposite directions. To move at 45 degrees, only one motor moves. The mechanical implication: X moves and Y moves load the belt path differently. Different effective belt lengths under tension, different pulleys engaged in compression vs tension, different mass moments around the gantry corners.
So even though the toolhead is the same lump of mass for both, the resonant behaviour the toolhead exhibits when commanded along X is genuinely different from when commanded along Y, because the spring-mass system behind the motion is different.
What stock Creality K2 firmware does
Inside /usr/share/klipper/klippy/extras/resonance_tester.py on a K2, there's a flag named copy_TestAxis_y_to_x. With that flag set, when you run SHAPER_CALIBRATE AXIS=Y, the firmware runs the Y test, picks a shaper based on the Y data, and also stamps that result onto the X axis.
The presumed logic is: "users are lazy, this saves them a calibration run, X and Y are 'the same axis' on a CoreXY anyway." That last clause is the broken part.
Practically: if you've ever calibrated only Y and assumed the SAVE_CONFIG output for X was independent, on a stock K2 it wasn't. It was a copy.
Three reasons CoreXY isn't symmetric
1. The moving mass is different on each axis
When you accelerate in X, the entire toolhead-plus-X-rail assembly translates left-right. The X gantry rail itself doesn't move. The mass involved is just the toolhead.
When you accelerate in Y, the toolhead plus the entire X gantry rail translates front-back. That rail's mass is significant — often more than the toolhead itself. So Y is moving a much larger mass than X, even though the motors and belts are the same.
Different mass means a different mass-spring-damper system means a different resonance frequency. Typically Y resonates at a lower frequency than X by 5 to 15 Hz. On my K2, after patching, X picked EI at 58.4 Hz and Y picked MZV at 49.4 Hz — a 9 Hz gap that no single shaper centre frequency can cover well.
2. The belt path is different on each axis
In CoreXY, the two belts loop through the toolhead and around idlers in a specific path. When you move along X, both belts feed at the same rate; when you move along Y, one feeds while the other unfeeds. The effective stiffness of the system differs between these two modes because the belt sections under tension are different.
This is why two physically identical CoreXY machines built to the same spec can have noticeably different X-vs-Y resonance gaps depending on belt routing, idler bearings, and even belt age. Copying one axis's tuning to the other ignores this entirely.
3. Different damping characteristics
Damping in a CoreXY rig comes from belt internal friction, linear-rail bearings, and idler bearings. On most CoreXY designs the X gantry uses different rails — often shorter, sometimes a different bearing type — than the bed-frame Y rails. Different rails means different damping. So even if X and Y started with the same resonance frequency, their resonance peak shapes would differ — one sharper, one broader — which influences which shaper algorithm wins.
What happens if you copy Y to X anyway
You get one of two outcomes.
You over-shape the X axis: Y picks a low-frequency shaper centred at 49 Hz; X actually wants 58 Hz. Applying Y's tuning to X means you're suppressing frequencies the X axis doesn't have, which costs you accel headroom for no benefit.
Or you under-shape the X axis: Y picks a mild shaper (zv or mzv); X actually has a sharper or doubled peak that wants a stronger shaper (ei or 2hump_ei). Applying Y's tuning leaves the X resonance uncancelled and you get visible ringing on X-axis features.
Either way, you've masked the actual X tuning. And critically, SHAPER_CALIBRATE overwrites the value silently. There's no warning. You won't know unless you go and check.
Spotting it on your firmware
If you're on a stock K2, run SHAPER_CALIBRATE AXIS=Y and check /mnt/UDISK/printer_data/config/printer.cfg afterwards. If you see the same shaper and frequency under both [input_shaper] X and Y entries — and you didn't run X — your firmware is doing the copy.
You can also check /usr/share/klipper/klippy/extras/resonance_tester.py directly — grep -n "copy_TestAxis" against that file will show you whether the flag and copy logic are present.
The fix on the K2
Force the flag to False after the axis check, take a backup first. The pattern I follow: copy the file to resonance_tester.py.bak-disablecopy-<unix-ts>, then patch the flag in place. Restart Klipper with /etc/init.d/klipper restart. Now SHAPER_CALIBRATE AXIS=X and SHAPER_CALIBRATE AXIS=Y produce two independent recommendations.
For the broader question of why the K2's shaper analysis differs from upstream (and what other patches I'm running), see Why your Creality K2's input shaper recommendation might be wrong.
The right calibration ritual
For any CoreXY printer, the procedure is the same:
- Run
SHAPER_CALIBRATE AXIS=X. Note the frequency and shaper picked. - Run
SHAPER_CALIBRATE AXIS=Y. Note the frequency and shaper picked. - Verify in
printer.cfg's SAVE_CONFIG section that both axes have distinct entries with the values you just calibrated. Not the same value twice. - If the two axes have very different
max_accelrecommendations, set your printer-widemax_accelto the lower of the two. Klipper's input shaping caps your accel based on the worst axis, not the best.
Bottom line
CoreXY isn't symmetric. The maths doesn't pretend it is, and your firmware shouldn't either. If yours is silently copying Y onto X, that's a five-line patch (or a manual cleanup) that gives you visibly better print quality for free.
If your CoreXY is ringing on cornering and you've already calibrated, send it in for a tune-up — half the time it's exactly this kind of axis-coupling assumption hiding in the firmware.