Adaptive meshing probes only the part of the bed the current print uses. This page covers the config, the start macro line, the slicer setting, how it relates to KAMP, and what to check when Klipper still meshes the whole bed.
Adaptive bed meshing makes Klipper probe only the rectangle covered by the objects in the current print, not the whole bed. Add an empty [exclude_object] section to printer.cfg, slice with object labels, and run BED_MESH_CALIBRATE ADAPTIVE=1 in your start macro. Klipper has done this natively since January 2024 (release 0.13.0), without the KAMP (Klipper Adaptive Meshing and Purging) add-on.
What is adaptive bed meshing in Klipper?
Adaptive bed meshing is a mode of Klipper’s bed_mesh module that probes only the area used by the objects in the current file, plus an optional margin. It reads the object outlines from the [exclude_object] module and shrinks the mesh to the rectangle around them. The probe count shrinks in proportion, so small parts mesh quickly.
In Klipper’s own example, objects covering half the width and depth of a 100 by 100 mm mesh turn a probe_count of 7,7 into 4,4. The source code (bed_mesh.py) adds three rules:
- Minimum points. At least 3 per axis, or 4 when the other axis needs more than 6.
- Clamped. The adapted area, margin included, stays inside
mesh_min and mesh_max.
- Not saved. The mesh is named
adaptive-… and goes into no profile. Klipper says adapted meshes “should not be re-used”.
Klipper recommends it for beds whose full mesh varies by one layer height or less. Otherwise, moves outside the probed area risk “undesirable results”.
How to set up adaptive bed meshing in Klipper
- Update Klipper. Builds from before January 2024 have no adaptive mode.
- Enable object tracking. Add
[exclude_object] to printer.cfg. It takes no options.
- Label objects in the slicer. The file needs
EXCLUDE_OBJECT_DEFINE lines.
- Set the full-bed density. Adaptive mode scales
probe_count down, so a 3 by 3 grid stays 3 by 3.
- Call it at print start. Run
BED_MESH_CALIBRATE ADAPTIVE=1 after heating the bed and homing.
- Test with a real print. Check the console for the adapted-mesh lines.
[exclude_object]
[bed_mesh]
mesh_min: 35, 6 # placeholder: nearest point your probe can reach
mesh_max: 240, 198 # placeholder: farthest point your probe can reach
probe_count: 7, 7 # density for a full-bed mesh; adaptive scales it down
adaptive_margin: 5 # mm added around the objects; default 0
Raise adaptive_margin if a skirt, brim or purge line lands outside the object outlines. ADAPTIVE_MARGIN=10 on the command overrides it once.
Klipper adaptive bed mesh start G-code
Mesh after heating the bed and homing, and before heating the nozzle:
[gcode_macro PRINT_START]
gcode:
{% set BED = params.BED|default(60)|int %}
{% set EXTRUDER = params.EXTRUDER|default(210)|int %}
M190 S{BED} ; heat the bed and wait
G28 ; home at temperature
BED_MESH_CALIBRATE ADAPTIVE=1 ; probe only where the objects sit
M109 S{EXTRUDER} ; heat the nozzle and wait
Without a macro, the line goes in the slicer’s start G-code after G28. Do not also run BED_MESH_PROFILE LOAD=default, which Klipper warns “may produce unexpected results, especially with adaptive meshing.” The PRINT_START macro guide covers passing temperatures from the slicer.
Adaptive bed mesh with OrcaSlicer
In OrcaSlicer, set Printer settings > G-code flavor to Klipper and tick Print settings > Others > G-code output > Exclude objects (off in Orca’s base defaults). Orca then writes an EXCLUDE_OBJECT_DEFINE line with an outline for each object at the top of the file, ahead of your start G-code.
- PrusaSlicer 2.7.0 or newer: set G-code flavor to
Klipper and Print Settings > Output options > Label objects to Firmware-specific (Mainsail docs).
- Other slicers: add
enable_object_processing: True under [file_manager] in moonraker.conf. Moonraker then adds the definitions on upload, though it warns this is file I/O intensive and not recommended on a Pi Zero.
Orca’s separate adaptive bed mesh settings fill the bounds into BED_MESH_CALIBRATE through placeholders such as {adaptive_bed_mesh_min[0]}. Use that or ADAPTIVE=1, not both.
Why is Klipper adaptive bed mesh not working?
Klipper adaptive bed mesh usually fails because Klipper sees no objects when the mesh runs, so it probes the full bed. The causes are a missing [exclude_object] section, a G-code file without EXCLUDE_OBJECT_DEFINE lines, definitions placed after the mesh call, or a macro that overrides BED_MESH_CALIBRATE and drops ADAPTIVE=1.
A working run prints Found N objects, Adapted mesh bounds and Adapted probe count. Without those lines, check:
Exclude objects not enabled. Using full mesh... The config lacks [exclude_object].
- No message, full mesh. The file defines no objects. Search the G-code for
EXCLUDE_OBJECT_DEFINE. The same command with no parameters lists the objects Klipper knows.
- Definitions below
PRINT_START. Klipper clears the object list when a print starts, so definitions must precede the mesh call. KAMP notes Moonraker’s processor can place them late; an M117 line before PRINT_START usually restores the order.
- An override. A macro that renames
BED_MESH_CALIBRATE passes only the arguments it chooses. KAMP’s meshing file never passes ADAPTIVE, and KAMP warns that Klicky and Euclid probe macros define their own. Search your config for rename_existing.
- Old firmware. Any build based on Klipper from before January 2024, vendor forks included, has no adaptive code.
Console tests between prints mislead. The object list survives “until another action resets it”, so the mesh follows the last print’s objects.
KAMP and the built-in adaptive mesh
KAMP is a macro set that meshed adaptively before Klipper could. Its Adaptive_Meshing.cfg renames BED_MESH_CALIBRATE and calls the original with bounds taken from the same object outlines.
Use one. On current Klipper, leave [include ./KAMP/Adaptive_Meshing.cfg] commented out in KAMP_Settings.cfg and use ADAPTIVE=1. KAMP’s version keeps two extras: fuzz_amount randomizes the bounds to spread nozzle-probe wear (KAMP recommends 3 mm at most), and probe_dock_enable handles dockable probes.
A KAMP start print macro
To pair KAMP’s purge and park with Klipper’s mesh, include ./KAMP/Line_Purge.cfg and ./KAMP/Smart_Park.cfg in KAMP_Settings.cfg, then add [include KAMP_Settings.cfg] to printer.cfg:
[gcode_macro PRINT_START]
gcode:
{% set BED = params.BED|default(60)|int %}
{% set EXTRUDER = params.EXTRUDER|default(210)|int %}
M190 S{BED} ; heat the bed and wait
G28 ; home at temperature
BED_MESH_CALIBRATE ADAPTIVE=1 ; Klipper's adaptive mesh
SMART_PARK ; KAMP: park near the print area
M109 S{EXTRUDER} ; heat the nozzle and wait
LINE_PURGE ; KAMP: purge beside the print
KAMP puts SMART_PARK before the final heat and the purge last. LINE_PURGE needs max_extrude_cross_section: 5 under [extruder], or KAMP skips the purge with a warning. To purge without KAMP, see the purge line macro.