Manual Mesh Bed Leveling with Klipper

Ok, so my bed is an absolute mess and I've been meaning to do a manual mesh for a very long time. It's now gotten to the point where it's pretty much a requirement for my 2 year old CR10. Been the stubborn bloke I am I was not about to just go out and spend actual money on a BLTouch

Manual Mesh Bed Leveling with Klipper

Note: This article has been updated as of 10/08/2019. I have changed the procedure for adding the menu, and some other nifty options.

Ok, so my bed is an absolute mess and I've been meaning to do a manual mesh for a very long time. It's now gotten to the point where it's pretty much a requirement for my 2-year-old CR10. Been the stubborn bloke I am I was not about to just go out and spend actual money on a BLTouch because:
1. It's another point of failure to an already failure loving machine.
2. I'm a cheapskate and prefer free things, even if I've got to DIY it.

Klipper isn't setup with this out of the box although I do believe it's on the way. This however isn't too hard to get setup for anyone who knows how to edit configuration files within klipper.  

Add the below code to your printer.cfg, this is to activate the bed_mesh feature of Klipper.

min_point: 10,10
max_point: 290,290
probe_count: 5,5
fade_start: 1.0
fade_end: 10.0

That's setup for a 300x300mm bed as you can see with the min/max_point's, these are the starting and ending positions for a row. I also increase the probe_count to 5,5 for 5 rows and 5 columns on the points map. My bed... is that fucked! The standard is 3,3 so most people will be fine with that.  The fade_start, and fade_end I left default but these are basically the point in which the z position will fade out the mesh bed levelling.  

Next find your stepper_z section and add the position_min code to allow minus figures. Even with my completely warped bed I didn't need anything more than -0.5mm.

position_min: -0.5

Note: Thanks to a reddit user, tollsjo! they correctly pointed out that whilst the "position_min" allows the Z to move to a negative position the LCD will show an incorrect value depending on what you have your "position_endstop" set to. I never noticed this as mine on the CR10 is set to 0. The ender-3 however has this set to 0.5 so all the values will be off by that amount. You can correct this by updating your [stepper_z] section with the following code:

position_endstop: 0.0

Also thanks to the same user, the default travel speed between probe points is 50mm/s which is as he pointed out, painfully slow! Especially for me, considering I use more than the normal amount of probe points. In the [mesh_bed] section of your printer.cfg you can increase the speed to 100mm/s by adding the following:

speed: 100

Next we need to create the menu so it displays on our printer. My old way edited the menu.cfg of Klipper which is fine, and will totally work. There is however a better way, and this will survive updates to the Klipper system. If you've got multiple printers like me, you will also be able to disable and re-enable it on which ever one you'd like.

Create a new file in the same directory as your printer.cfg, I just called mine meshBed.cfg. You'll need to remember this file name later. Your path could be different, don't just use the one displayed below.


In your empty file add the below list. This will override the default [menu __prepare option] in Klippers menu.cfg. I don't use __delta_calib or __bedprobe either so I also removed those.

[menu __prepare]
type: list
enable: !toolhead.is_printing
name: Prepare

That will setup the menu under Klippers Prepare menu, and it will only be available when the printhead isn't printing. That's probably how the entire prepare menu is, but I forget so thought I'd mention it.

In the same file add the below code under the [menu __prepare] code we created above. This will enable the "Mesh Bed Level" option under the prepare menu. Thanks to klipper and its programmability it allows us to use custom gcode and menu options to run those gcode.

[menu __prepare meshBed]
type: list
enable: !toolhead.is_printing
name: Mesh Bed Level

[menu __prepare meshBed zposition]
type: item
name: "Z Pos= {0:05.3f}"
parameter: toolhead.zpos
[menu __prepare meshBed start]
type: command
name: Start Callibration

[menu __prepare meshBed zNudgeDown]
type: command
name: Nudge Down
gcode: TESTZ Z=-0.025

[menu __prepare meshBed zNudgeUp]
type: command
name: Nudge Up
gcode: TESTZ Z=0.025

[menu __prepare meshBed next]
type: command
name: Next
[menu __prepare meshBed save]
type: command
name: Save & Restart

Open up your original printer.cfg and add the "include" code you see below. Klipper allows this with multiple configuration files which is great if you've got some you want applied to multiple printers, or you just like to segregate your code more. I do love how flexible this system is and i'm still learning everyday this little fact more and more. Mine was added just under the [bed_mesh] option, but it doesn't matter, you can keep them wherever it's easiest to manage them.

[include meshBed.cfg]

Run the good old "FIRMWARE_RESTART" command in Octoprints terminal and you should see the new menu options. You can now start your calibration process for the bed, manually! When you click "Start Calibration" it will home and then move to the first position depending on what you setup in your [bed_mesh] settings. Nudge your Z, up or down, and continue on with the "Next" option. At the last point your printer will move the Z axis to 0.5mm and then you can press the "Save and Restart" button.

That's it!  

Let's just say I'm happy with the results! Keeping my 2 year old original CR10 running well! 

You can download my meshBed.cfg file from my github here:

Additional: If you want to set it up in bed visualiser for Octoprint like I have in the picture displayed above, then download the plugin and add the below code in it's settings.

Thanks to user ardyesp and rlesac from for pointing me in the right direction to get this setup and running. I hope this is of some use to someone else.

Additional 2: I wanted a better way of testing the full bed so I knocked up 2 version of a 0.2mm layer height grid in fusion360. Just resize it in your slicer to the size of your bed and print it after doing your bed mesh.
You can find it here: