What formulas do you need to calibrate a 3D printer?
Twelve formulas turn calibration tests into settings. For the machine: stepper driver Vref, belt tension, steps per mm, and e-steps on Marlin or rotation distance on Klipper. For extrusion: flow ratio and max volumetric speed. For part size: skew factor, shrinkage scale and hole compensation. For the slicer: full-step layer heights and wall thickness.
| What you calibrate | Formula | Worked example | Calculator |
|---|---|---|---|
| Driver current (Vref) | A4988: 8 × I_peak × Rs | 8 × 1.428 × 0.068 = 0.777 V | Stepper Vref |
| Belt tension | 4 × μ × L² × f² | 4 × 0.0084 × 0.15² × 110² = 9.15 N | Belt tension |
| Steps per mm (X, Y, Z) | full steps × microsteps × gear ratio ÷ travel per turn | 200 × 16 ÷ 40 = 80 | Steps per mm |
| E-steps (Marlin) | current × requested ÷ actual | 93 × 100 ÷ 96 = 96.88 | E-steps |
| Rotation distance (Klipper) | full steps × microsteps ÷ steps per mm | 200 × 16 ÷ 415 = 7.711 | Rotation distance |
| Flow ratio | current × expected wall ÷ measured wall | 1.00 × 0.45 ÷ 0.47 = 0.957 | Flow rate |
| Max print speed | max volumetric speed ÷ (layer height × line width) | 12 ÷ (0.2 × 0.45) = 133 mm/s | Volumetric flow |
| Skew factor | tan(90° − corner A) | AC 141.70, BD 141.14, AD 100 mm: 0.003960 | Skew |
| Shrinkage scale | 1 ÷ (1 − s) | 1 ÷ (1 − 0.0063) = 100.63% | Shrinkage |
| Hole compensation | (designed − measured) ÷ 2 | (5 − 4.80) ÷ 2 = 0.10 mm | Hole compensation |
| Full-step layer height | whole number × lead ÷ full steps per turn | 8 ÷ 200 = 0.04 mm per step | Layer height |
| Wall thickness | w + (walls − 1) × (w − h × (1 − π/4)) | 0.45 + 0.407 = 0.857 mm | Line width |
Calibrate in the table’s order, top to bottom, because an extruder or flow error throws off every later measurement.
Stepper driver Vref formula
A4988: Vref = 8 × I_peak × Rs
DRV8825: Vref = 5 × I_peak × Rs
TMC2208, TMC2209 in standalone mode:
Vref = I_peak × 2.5 × (Rs + 0.020) / 0.325
I_peak = rated current × run percentage
I_RMS = I_peak × 0.707
Vref is the driver’s reference voltage and I_peak the peak current per coil it sets. Rs is the sense resistor beside the driver chip, marked with a code such as R068 (0.068 Ω). Pololu’s A4988 carriers use 0.068 Ω, its DRV8825 carriers 0.100 Ω, and BIGTREETECH’s TMC2209 modules 0.110 Ω. Duet3D advises a peak of 50% to 85% of the motor’s rated current.
Worked line: a 1.68 A motor at 85% runs 1.68 × 0.85 = 1.428 A peak, so an A4988 needs 8 × 1.428 × 0.068 = 0.777 V, a DRV8825 0.714 V and a TMC2209 1.43 V.
What to set: turn the driver’s trim potentiometer until a multimeter between GND and the Vref point reads that voltage. A TMC driver in UART mode ignores Vref and takes RMS current from the firmware: run_current: 1.010 under [tmc2209 stepper_x] in Klipper, or #define X_CURRENT 1010 (mA) in Marlin’s Configuration_adv.h. The stepper Vref calculator handles other resistors and checks a Vref you measured.
Belt tension formula
T (N) = 4 × μ × L² × f²
f (Hz) = √(T / (4 × μ × L²))
T is the tension in newtons, μ the belt’s mass in kg per meter, L the free span in meters (contact point to contact point) and f the pluck frequency in hertz. Gates gives its 2 mm pitch belts 1.4 g/m per mm of width, so a 6 mm belt is 8.4 g/m (0.0084 kg/m).
Worked line: Voron’s A/B target, 110 Hz over a 150 mm span on a 6 mm belt, is 4 × 0.0084 × 0.15² × 110² = 9.15 N.
What to do: pluck the middle of the span, read the lowest strong peak on a spectrum app, and turn the tensioner until it matches your printer maker’s frequency. At a fixed tension the frequency scales with 1 / L, so the same 9.15 N over a 200 mm span reads 110 × 150 / 200 = 82.5 Hz. The belt tension calculator loads Voron and Prusa targets.
Steps per mm formula
steps per mm = full steps per turn × microsteps × gear ratio / travel per turn
belt and pulley: travel per turn = belt pitch × pulley teeth
lead screw: travel per turn = thread pitch × thread starts
measured move: new steps per mm = current × commanded / measured
Full steps per turn is 200 for a 1.8° motor and 400 for a 0.9° motor. Klipper’s docs note most drivers use 16 microsteps. The gear ratio is driven teeth over motor teeth, or 1 when the motor turns the pulley or screw directly.
Worked line: a 2 mm GT2 belt on a 20-tooth pulley moves 40 mm per turn, so 200 × 16 / 40 = 80 steps/mm. A T8 lead screw (2 mm pitch, 4 starts) moves 8 mm, so 200 × 16 / 8 = 400. Those are the X, Y and Z values in Creality’s Ender-3 firmware.
What to type: M92 X80 Y80 Z400, then M500 to save.
Read the measured-move line as a diagnosis, not a trim: Klipper’s docs say measure and trim “is not accurate enough” for X, Y and Z. A correction near 2, 4 or 1.25 (or their inverses) means a wrong setting: a 10 mm Z move that travels 2.5 mm gives 400 × 10 / 2.5 = 1,600, the value for a TR8x2 screw with a 2 mm lead. A small error on a belt axis is shrinkage or flow, so keep the hardware value. The steps per mm calculator names the setting behind a correction.
E-steps formula
new e-steps = current e-steps × requested length / actual length
from the parts: e-steps = full steps per turn × microsteps × gear ratio / (π × effective drive gear diameter)
Current e-steps is the E value on the M92 line that M503 prints. Requested length is what you told the extruder to push, usually 100 mm. Actual length is what went in: a mark’s distance from the extruder before the test minus its distance afterward.
Worked line: a stock Ender-3 at 93 steps/mm that feeds 96 mm of a requested 100 mm needs 93 × 100 / 96 = 96.88. From the parts, a Bondtech BMG (50:17 gearing, 1.8° motor, 16 microsteps) works out to the 415 steps/mm Bondtech publishes.
What to type: M92 E96.88, then M500. Klipper’s guide says to repeat the test when the first run misses by more than about 2 mm. The e-steps calculator writes both commands.
Klipper rotation distance formula
rotation_distance = full_steps_per_rotation × microsteps × gear / steps_per_mm
belt axis: rotation_distance = belt_pitch × pulley_teeth
lead screw: rotation_distance = thread_pitch × thread_starts
extruder: rotation_distance = drive_gear_diameter × π
trim: new rotation_distance = previous × actual_extruded / requested_extruded
rotation_distance is how far the axis or the filament moves in one motor turn, or in one turn of the final gear when gear_ratio is set. In the conversion, gear is that gear_ratio, or 1 without one. The trim runs the opposite way to e-steps: an extruder that pushes too little needs a smaller rotation_distance.
Worked line: Bondtech’s 415 e-steps convert to 200 × 16 / 415 = 7.711. A Voron Stealthburner at 22.6789511 that pushes 49 mm of a requested 50 mm trims to 22.6789511 × 49 / 50 = 22.225.
What to type: rotation_distance: 22.225 under [extruder] in printer.cfg, then RESTART. To try a value first, send SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=22.225. The rotation distance calculator converts e-steps to rotation_distance and back.
Flow ratio formula
measured wall: new flow ratio = current × expected wall thickness / measured average
OrcaSlicer Pass 1, 2: new flow ratio = current × (100 + modifier) / 100
OrcaSlicer YOLO: new flow ratio = current + modifier
The expected thickness of a one-wall (vase mode) test is the line width. For two or more walls, use the wall thickness formula at the end of this page, not walls × line width. The modifier is the number on the smoothest test block.
Worked line: a 0.45 mm single wall that measures 0.47 mm at flow 1.00 gives 1.00 × 0.45 / 0.47 = 0.957. OrcaSlicer’s own example starts at 0.98: the +5 block in Pass 1 gives 0.98 × 105 / 100 = 1.029, then the −6 block in Pass 2 gives 1.029 × 94 / 100 = 0.967.
What to type: 0.957 as Flow ratio in the OrcaSlicer or Bambu Studio filament settings, as Extrusion multiplier in PrusaSlicer’s Filament Settings, or as Flow 95.7% in UltiMaker Cura. Keep the firmware’s M221 flow at 100% while you test, since Prusa notes it multiplies with the slicer’s value. The flow rate calculator chains Pass 1 and Pass 2.
Max volumetric speed formula
volumetric flow (mm³/s) = layer height (mm) × line width (mm) × print speed (mm/s)
max print speed (mm/s) = max volumetric speed (mm³/s) ÷ (layer height × line width)
OrcaSlicer test result = start + height measured × step
Max volumetric speed is how many cubic millimeters of filament the hotend can melt per second. Bambu Studio and OrcaSlicer apply the cap to a rounded line cross-section: layer height × (line width − layer height × (1 − π/4)).
Worked line: Bambu Studio’s generic PLA profile allows 12 mm³/s, so a 0.2 mm layer and a 0.45 mm line top out at 12 ÷ (0.2 × 0.45) = 133 mm/s, or 147 mm/s with the rounded cross-section. An OrcaSlicer test at its default 5 mm³/s start and 0.5 step that fails at 19 mm reads 5 + 19 × 0.5 = 14.5 mm³/s. OrcaSlicer suggests entering a value 10% to 20% lower: 11.6 to 13 mm³/s.
What to type: the value into Max volumetric speed (mm³/s) under Volumetric speed limitation on the filament preset’s Filament tab in Bambu Studio and OrcaSlicer. The volumetric flow calculator lists published limits by filament and hotend.
Skew factor formula
AB = √(2 × AC² + 2 × BD² − 4 × AD²) / 2
factor = tan(90° − acos((AC² − AB² − AD²) / (2 × AB × AD)))
AC and BD are the diagonals of a printed test square and AD the side along X for the XY plane. AB is the other side, worked out from those three, and the acos term is the angle at corner A. Marlin and Klipper both use these lines, so one set of measurements gives the factor for either firmware.
Worked line: Marlin’s docs example has AC = 141.70 mm, BD = 141.14 mm and AD = 100.00 mm. AB is 99.998 mm and corner A is 89.773°. The factor is tan(0.227°) = 0.003960, a lean of 0.40 mm per 100 mm.
What to type:
- Marlin:
M852 I0.003960, thenM500. - Klipper: with a
[skew_correction]section in printer.cfg, sendSET_SKEW XY=141.7,141.14,100,SKEW_PROFILE SAVE=my_skew_profileandSAVE_CONFIG. PutSKEW_PROFILE LOAD=my_skew_profilein the start G-code after homing. - RepRapFirmware:
M556 S100 X-0.396, which takes the error in mm over the S length, with the opposite sign.
The skew calculator also covers the XZ and YZ planes.
Shrinkage scale factor formula
shrinkage s = (designed − measured) / designed
scale factor k = 1 / (1 − s)
Designed is the size in the model and measured is the printed part at room temperature.
Worked line: a 100 mm span that prints at 99.37 mm has shrunk 0.63%, so k = 1 / (1 − 0.0063) = 1.00634, a 100.63% scale.
What to type: OrcaSlicer’s Shrinkage (XY) and Bambu Studio’s Shrinkage take the measured size as a percentage of the design, 99.37%. PrusaSlicer’s Shrinkage compensation XY takes the shrinkage itself, 0.63%. Scaling the model to 100.63% does the same job, so doing both compensates the part twice. The shrinkage calculator gives each slicer’s value for X, Y and Z.
Hole compensation formula
per-wall correction = (designed diameter − measured diameter) / 2
new hole value = value used for the test print + per-wall correction
Slicers move each hole wall by the setting. As Bambu Lab’s wiki puts it, “The hole diameter will increase by twice the compensation value.”
Worked line: a 5 mm hole that prints at 4.80 mm, with compensation at 0, needs (5 − 4.80) / 2 = 0.10 mm.
What to type: 0.1 in X-Y hole compensation (Process > Quality > Precision) in OrcaSlicer and Bambu Studio, or in Hole Horizontal Expansion in UltiMaker Cura. PrusaSlicer has no hole-only setting: an XY Size Compensation of −0.1 opens holes by the same amount but also shrinks the outside. The hole compensation calculator handles reprints and the other slicers’ sign conventions.
Full-step layer height formula
Z travel per full step = lead ÷ full steps per turn
= microsteps ÷ Z steps per mm
full-step layer height = whole number × Z travel per full step
usable layer height = 0.20 × nozzle to 0.80 × nozzle
first layer height = 0.50 × nozzle
Lead is the Z travel per motor turn: thread pitch × starts, or Klipper’s rotation_distance divided by any gear_ratio. A full-step height (a “magic number”) ends every layer change on a full step. Prusa’s calculator explains why: a Z motor switched off between microsteps jumps to the nearest full step and adds error.
Worked line: a T8 screw (8 mm lead) on a 1.8° motor moves 8 ÷ 200 = 0.04 mm per full step, so 0.15 mm is 3.75 steps; use 0.12 or 0.16 mm. On a 0.4 mm nozzle the usable range is 0.08 to 0.32 mm (OrcaSlicer’s 20% to 80%; Bambu Lab’s wiki stops at 70%, 0.28 mm). Prusa’s profiles use a 0.20 mm first layer.
What to type: the height into Layer height, under Process > Quality in OrcaSlicer and Bambu Studio or Print Settings > Layers and perimeters in PrusaSlicer. The layer height calculator lists the full-step heights for your screw and nozzle.
Line width and wall thickness formula
automatic line width = 1.125 × nozzle diameter
spacing (mm) = w − h × (1 − π/4)
wall thickness (mm) = w + (walls − 1) × spacing
cross-section (mm²) = h × (w − h × (1 − π/4))
UltiMaker Cura: wall thickness = walls × w
w is the line width and h the layer height. PrusaSlicer, OrcaSlicer and Bambu Studio use 1.125 × the nozzle when the width is left at 0. They overlap neighboring lines by h × (1 − π/4), 0.043 mm at a 0.2 mm layer. Cura’s line width defaults to the nozzle size, and its walls sit one width apart.
Worked line: 0.45 mm lines at 0.2 mm layers sit 0.45 − 0.043 = 0.407 mm apart, so two walls are 0.45 + 0.407 = 0.857 mm. OrcaSlicer’s Precise wall removes the overlap between the outer and first inner wall, so its two walls come to 0.9 mm. Precise wall and the Inner/Outer wall order it applies to are both OrcaSlicer defaults. Two 0.4 mm walls in Cura are 0.8 mm.
What to do: model thin walls at that thickness so they fill with whole lines. Prusa’s knowledge base recommends 0.86 mm for two 0.45 mm perimeters at 0.2 mm layers. In Cura, set Wall Thickness to walls × line width, 1.2 mm for three 0.4 mm walls. The line width calculator handles different outer and inner widths.
Published · Figures last checked
Sources
- Allegro MicroSystems, A4988 DMOS microstepping driver with translator and overcurrent protection, datasheet (accessed 2026-10-18)
- Texas Instruments, DRV8825 stepper motor controller IC, datasheet SLVSA73F (accessed 2026-10-18)
- TRINAMIC (Analog Devices), TMC2209 datasheet Rev. 1.08, copy hosted by Digi-Key (accessed 2026-10-18)
- Pololu, A4988 stepper motor driver carrier (0.068 Ω sense resistors) (accessed 2026-10-18)
- Pololu, DRV8825 stepper motor driver carrier, high current (0.100 Ω sense resistors) (accessed 2026-10-18)
- BIGTREETECH wiki, TMC2209 (current formula, 110 mΩ sense resistors) (accessed 2026-10-18)
- Pololu, Stepper motor: bipolar, 200 steps/rev, 42×38 mm, 2.8 V, 1.7 A/phase (1.68 A per coil) (accessed 2026-10-18)
- Duet3D documentation, Choosing stepper motors (50% to 85% of rated current) (accessed 2026-10-18)
- Marlin firmware, Configuration_adv.h (X_CURRENT in mA RMS) (accessed 2026-10-18)
- Klipper documentation, Configuration reference (stepper, tmc2209, skew_correction) (accessed 2026-10-18)
- Gates, Model 550C Sonic Tension Meter manual (tension formula and belt mass constants) (accessed 2026-10-18)
- Voron Design documentation, Secondary Printer Tuning: belt tension (accessed 2026-10-18)
- Klipper documentation, Rotation distance (accessed 2026-10-18)
- Klipper documentation, G-Codes (SET_EXTRUDER_ROTATION_DISTANCE, SET_SKEW, SKEW_PROFILE) (accessed 2026-10-18)
- Marlin, M92: Set Axis Steps-per-unit (accessed 2026-10-18)
- Marlin, M500: Save Settings (accessed 2026-10-18)
- Marlin, M503: Report Settings (accessed 2026-10-18)
- Creality, Ender-3 Marlin firmware, Configuration.h (DEFAULT_AXIS_STEPS_PER_UNIT) (accessed 2026-10-18)
- Bondtech, BMG extruder (e-step value, rotation_distance and 50:17 gearing) (accessed 2026-10-18)
- Voron Design, Voron 2.4 reference printer.cfg (Octopus) (accessed 2026-10-18)
- OrcaSlicer wiki, Flow ratio calibration (accessed 2026-10-18)
- Prusa Knowledge Base, Extrusion multiplier calibration (accessed 2026-10-18)
- Bambu Lab wiki, Flow rate calibration (accessed 2026-10-18)
- UltiMaker Cura 5.13.0, fdmprinter.def.json (line_width, material_flow, hole_xy_offset, wall_line_count) (accessed 2026-10-18)
- Bambu Lab Wiki, Volumetric speed and how it impacts 3D printing (accessed 2026-10-18)
- BambuStudio profiles, fdm_filament_pla.json (12 mm³/s) (accessed 2026-10-18)
- BambuStudio source, Flow.cpp (auto_extrusion_width, mm3_per_mm, rounded line cross-section) (accessed 2026-10-18)
- BambuStudio source, GCode.cpp (speed capped at max volumetric speed / mm3_per_mm) (accessed 2026-10-18)
- OrcaSlicer source, Flow.cpp (auto_extrusion_width, mm3_per_mm, same rounded line model) (accessed 2026-10-18)
- OrcaSlicer Wiki, Max Volumetric Speed (FlowRate) Calibration (accessed 2026-10-18)
- OrcaSlicer Wiki, Material Volumetric Speed Limitation (accessed 2026-10-18)
- Marlin Firmware documentation, Skew, Backlash and X-Twist Compensation (accessed 2026-10-18)
- Marlin Firmware documentation, M852 Bed Skew Compensation (accessed 2026-10-18)
- Klipper documentation, Skew correction (accessed 2026-10-18)
- Duet3D documentation, Orthogonal axis compensation with M556 (accessed 2026-10-18)
- OrcaSlicer Wiki, Material basic information (Shrinkage XY and Z) (accessed 2026-10-18)
- Bambu Lab Wiki, 3D prints shrinkage: causes and solutions (accessed 2026-10-18)
- PrusaSlicer 2.9.6 source, PrintConfig.cpp (shrinkage compensation, XY Size Compensation) (accessed 2026-10-18)
- Bambu Lab Wiki, XY Hole / Contour compensation (accessed 2026-10-18)
- OrcaSlicer Wiki, Precision settings (X-Y hole compensation) (accessed 2026-10-18)
- OrcaSlicer Wiki, Quality settings: Layer Height (accessed 2026-10-18)
- Bambu Lab Wiki, Layer height (Bambu Studio) (accessed 2026-10-18)
- Prusa Research, 3D printing calculator: Optimal layer height for your Z axis (accessed 2026-10-18)
- Prusa Knowledge Base, Layers and perimeters (accessed 2026-10-18)
- PrusaSlicer 2.9.6 source, Flow.cpp (auto_extrusion_width, line spacing) (accessed 2026-10-18)
- OrcaSlicer source, PrintConfig.cpp (precise_outer_wall and wall_sequence defaults) (accessed 2026-10-18)