Updates:
- 2025/06/05: publishing article
- 2025/05/30: updating
maf.cfg
and more documentation - 2025/05/23: first write-up with MAF
maf.cfg
Table of Contents
Introduction
As of May 2025 Klipper supports multi-axis support on G-code level. It was possible to define “manual stepper“ motors, but those needed to be handled via “Extended G-code” of Klipper. Now those “manual steppers” can be tied to a G-code axis, and thereby multi-axis system can be composed and becomes available in traditional G-code context.
MANUAL_STEPPER STEPPER=stepper_x1 GCODE_AXIS=A
and after that
G0 A100
can be used.
As of 2025/05 only G0/G1
is supported, but not G92
, M82
(absolute extrusion), M83
(relative extrusion) in case “manual stepper” is used as additional extruder motors – so I coded a Multi-Axis Framework for Klipper, just a bunch of Klipper macros which provide a better multi-axis & multi-extruder support:
G0
,G1
supports relative extrusion if enabled withM83
(I prefer)G28
homing the new axes as wellG92
supports the new axes tooM82
,M83
switches absolute/relative extrusionT0
,T1
, … switch extrudersM104
,M109
support of multiple extruders usingT
<n> notion
Klipper natively supports:
G90
,G91
for new axes also
Setup
Create a dedicated file, or add following into printer.cfg
, for example:
[include maf.cfg]
[gcode_macro MY_MAF]
variable_maf = {
"X": { "motor": "stepper_x", "dir": -1, "end_pos": 0 },
"Y": { "motor": "stepper_y", "dir": -1, "end_pos": 0 },
"Z": { "motor": "stepper_z", "dir": -1, "end_pos": 0, "bounce": 2 },
"E": { "motor": "extruder" },
"U": { "motor": "stepper_x1", "dir": -1, "end_pos": 0 },
"V": { "motor": "stepper_x2" "dir": 1, "end_pos": 380 },
"W": { "motor": "stepper_x3" "dir": -1, "end_pos": 0 },
"A": { "motor": "extruder1" },
"B": { "motor": "extruder2" },
"C": { "motor": "extruder3" }
}
gcode:
This defines all axes, the additional 3 X carriages, and additional 3 extruders. If you declare X
, Y
, Z
as well, it will home the same way as the new axes. By default after sensor is hit for homing, it bounces back 10mm (recommended for sensorless homing), you can override it with “bounce” value.
The maf.cfg
once included, the MAF
will be automatically executed at boot/restart.
M82 / M83: Absolute / Relative Extrusion
This applies to all extruders, M82
(absolute extrusion) is the default. I prefer relative extrusion (M83
) as it makes it easier to insert or remove G-code without affecting existing G-code with extrusion.
G92: Set Position
Any new axis can be set now, including the extruders.
G92 W0 A0 B90 C110
M104 / M109: Set Temperatures
One can set temperature per extruder/tool:
T0
M104 S200
T1
M104 S200
or more compact
M104 T0 S200
M104 T1 S200
M104
set the temperature but doesn’t wait, and M109
waits until temperature is reached.
G28: Homing
The new axes can be homed as well:
G28 X Y U V W
G28 Z
Note: if you declared the axis in MY_MAF
it will use the new G28
procedure, otherwise uses the native Klipper one.
G0 / G1: Move & Extrude
The G0
/ G1
is overridden in order to support relative extrusion.
M83 ; relative extrusion
G0 X100 U300 Y100 ; move two X carriages on common Y gantry
G1 X150 U350 Y150 E5 W5 ; extrude with both extruders on the X carriages
Note: given we work in cartesian kinematics, X
Y
Z
dictates the total distance as dist = sqrt (X^2+Y^2+Z^2) and the feedrate F
(mm/min), any additional axis is given time t = dist (mm) / feedrate (mm/min) to reach its destination, and therefore has its own feedrate or speed – so, when operating new axes in this context, it’s up to you to be aware of the other axes speeds and keep them below operation limits.
MAF: Current State
One can send MAF
command, and an output like this is received:
echo: == MAF: Multi-Axis Framework 0.1.0 ==
echo: motion mode: absolute
echo: extrude mode: absolute
echo: axis X: stepper_x, pos: 0.0000
echo: axis Y: stepper_y, pos: 0.0000
echo: axis Z: stepper_z, pos: 0.0000
echo: axis E: extruder / T0, pos: 0.0000
echo: temperature: 26.67C / 0.0C
echo: axis U: stepper_x1, pos: 0.0000
echo: axis A: stepper_x2, pos: 0.0000
echo: axis I: stepper_x3, pos: 0.0000
echo: axis B: stepper_y1, pos: 0.0000
echo: axis W: extruder1 / T1, pos: 0.0000
echo: temperature: 26.82C / 0.0C
echo: axis C: extruder2 / T2, pos: 0.0000
echo: temperature: 26.49C / 0.0C
echo: axis K: extruder3 / T3, pos: 0.0000
echo: temperature: 26.57C / 0.0C
ok
Download
- maf.cfg (Github GIST)
I plan to keep the code updated and backward compatible.
Use Case
I used “MAF” for early prototyping a Multi Gantry with Multi Extruder (IDEX) setup – Ashtar Q (MG2 IDEX) – printing in duplication mode (horizontal & vertical mirrored) on G-code level.



Operating in two different modes:
- 1x Klipper instance (with 4x MCUs): 2x Y gantries, 4x X carriages, 4x extruders = 11 axis (XYZE+XE+XYE+XE) – all motors fully synced
- 2x Klipper instances (with 2x MCUs each): Dual of 1x Y gantry, 2x X carriages, 2x extruders = 6 axis (XYZE+XE) + 5 axis (XYE+XE) – two gantries loosely synced
References
- Github PR #6888: Support for additional G1 axes (merged in May 2025)
- Klipper Forum: Macros
- Ashtar Q (MG2 IDEX) – coming soon