Miron Vranješ Product Manager 💡 ⋅ Pilot ✈️ ⋅ Tinkerer 🔬

Installing Klipper on Ender 3 v2 with BLTouch

I recently switched to Klipper on my Ender 3 v2 and it took my printing to a whole new level of speed and quality without any hardware changes. Klipper may seem intimidating at first, but it’s quite easy to install. In some ways, it’s easier than Marlin. In this post, I go through how to install Klipper and talk about some of the most common customization options including pressure advance and ringing compensation.

What is Klipper?

Klipper is fundamentally similar to Marlin except that it runs on a Raspberry Pi connected to the printer vs. the printer’s motherboard itself. The firmware on the motherboard becomes a “dumb” thin client and everything runs on the Pi’s much more powerful CPU.

Why should I install Klipper?

Installing Klipper on the original Ender’s 8-bit CPU meant detailed prints were significantly better since it simply didn’t have enough processing power to keep up. The Ender 3 v2 has a 32-bit CPU so this advantage is reduced (though Klipper uses more advanced kinematics equations so the prints will still be slightly better). But, there are a lot of other advantages to Klipper:

  • Ability to have pressure advance (similar to linear advance) on any Ender 3 v2
  • Ability to use input shaping to eliminate ghosting and ringing
  • Better bed leveling
  • Deep customizability without needing to recompile firmware
  • Custom G-codes and macros

Important Note: Installing Klipper will mean your printer’s LCD is always blank. If you want control when you’re physically at the printer, you’ll need to add a touchscreen LCD to your Raspberry Pi instead and control the printer via OctoPrint.

What do I need to run Klipper?

Klipper requires a Raspberry Pi which you may already be using for OctoPrint. Once you install Klipper, the Raspberry Pi becomes the “brain” of your printer and the printer’s motherboard is simply there to pass messages to the hardware.

Basic Installation

  1. You’ll need to install OctoPi on a Raspberry Pi (don’t use a v1 or a Zero). If you have OctoPrint, this should already be done.
  2. You’ll be doing work on the Raspberry Pi itself, so you’ll want to SSH into it from another computer. You’ll run a command like ssh pi@octopi where octopi is the IP address or hostname of the pi. The default password is raspberry.
  3. We’ll generally be following this guide.
    1. Clone the git repository: git clone https://github.com/KevinOConnor/klipper.
    2. Run the install script: ./klipper/scripts/install-octopi.sh.
    3. Change to the Klipper directory (cd ~/klipper/) and run the config tool (make menuconfig). Select the following in the menu:
      1. Uncheck Enable extra low-level configuration options.
      2. Set processor architecture to STMicroelectronics STM32.
      3. Set processor model to STM32F103.
      4. Set bootloader offset to 28KiB bootloader.
      5. Uncheck the other two options (Use USB and Use CAN).
      6. Save and exit.
    4. Type make and let it run.
  4. The firmware file will be in ~/klipper/out/klipper.bin. There’s many ways to get it out of the Raspberry Pi, but I used scp. From the main computer (where you ran ssh), type scp pi@octopi:~/klipper/out/klipper.bin klipper.bin.
  5. Put the file on an SD card and put the SD card into the Ender 3 while the printer is off. Turn on the printer and it should flash the firmware. If it flashed successfully, your LCD will go blank. Don’t worry, if anything goes wrong simply put Marlin firmware on it and flash it again.
  6. You need to configure OctoPrint to communicate with the printer. You don’t have to use OctoPrint with Klipper and can use an alternative like Fluidd (and also add KlipperScreen).
    1. In Settings, go to Serial Connection and add /tmp/printer to Additional serial ports. Once you save, in the same menu choose /tmp/printer under Serial Port.
    2. Under Behavior, select Cancel any ongoing prints but stay connected to the printer.
    3. If everything is good, you should see /tmp/printer in the main connection page and you should be able to connect. If you go to Terminal and type status you should get back an error about config files. This means you’re communicating with the printer’s new firmware!
  7. Now we want to configure the firmware for the Ender 3 v2. This is the equivalent of Marlin’s configuration.h but you don’t have to recompile firmware to change anything! It’s pretty slick.
    1. I recommend installing VS Code and the remote editing extension. This allows you to edit files on the Raspberry Pi directly from VS Code.
    2. Click the green >< button in the bottom left and select Remote-SSH: Connect to Host... and type pi@octopi.local (or whatever the IP address is you used above) and enter your password.
    3. In the home directory folder (~/) make a file called printer.cfg. Do not do this in the Klipper sub-folder, it should be in your regular home directory.
    4. Copy the contents of this Ender 3 v2 configuration file into printer.cfg and save it.
    5. In the Terminal of OctoPrint, type restart. You should see the printer restart and become ready without errors. You can also issue a status command. What’s beautiful about Klipper is that whenever you make config changes, you just save and run restart and that’s it. No recompiling!
    6. You should calibrate your e-steps and enter the value under [extruder] in step_distance. To convert between Marlin and Klipper values, simply take the reciprocal value. So if in Marlin the steps are 96, they’re 1/96 or 0.0104166667 in Klipper.
    7. To enable M118 and pausing functionality, add:
      default_type: command
      [pause_resume] recover_velocity: 50

Configuring BLTouch and Mesh Leveling

If you have BLTouch, you have to do a bit more work to get Klipper configured. You should read the detailed guide, but this is a quick summary.

  1. Add the following code to your printer.cfg. I use the x and y offsets from this Thingiverse mount.

    sensor_pin: ^PB1
    control_pin: PB0
    x_offset: -42
    y_offset: -10
    z_offset: 0
    home_xy_position: 117.5,117.5 # Change coordinates to the center of your print bed
    z_hop: 10 # Move up 10mm
    z_hop_speed: 5
  2. Under [stepper_z] in endstop_pin change ^PA7 to probe:z_virtual_endstop and add # in front of position_endstop: 0.0 to disable it.
  3. With Klipper you can calibrate the x and y offsets more precisely and then you’ll also need to add your z offset. The sign is flipped between Marlin and Klipper, so for me the z-offset of -2.60 became 2.60 here. Note that during calibration you will need to let the z axis go negative, so you can add position_min: -3 until you’re done calibrating.
  4. There’s a lot of bed mesh configuration options, but here’s one that works for me:

    speed: 120
    horizontal_move_z: 5
    mesh_min: 15, 15
    mesh_max: 205, 205
    probe_count: 5,3
    algorithm: bicubic
    fade_start: 1
    fade_end: 10
    fade_target: 0
  5. What’s amazing about Klipper is that it has a screw measurement feature. It runs BLTouch above each of the 4 screws and tells you how much to turn each one to dial your bed in perfectly (e.g., “CW 00:15” or turn clockwise 1/4 turn). To enable this, add:

    screw1: 70.5,37.5
    screw1_name: front left screw
    screw2: 240,37.5
    screw2_name: front right screw
    screw3: 240,207.5
    screw3_name: rear right screw
    screw4: 70.5,207.5
    screw4_name: rear left screw
    horizontal_move_z: 10
    speed: 50
    screw_thread: CW-M4
  6. With all of this done, you can now level the bed. First, home with G28 and type SCREWS_TILT_CALCULATE to adjust the bed. You can type SCREWS_TILT_CALCULATE multiple times until it’s close.
  7. To level the bed, you can run BED_MESH_CALIBRATE. After calibration, make sure to hit SAVE_CONFIG. Here’s a sequence I run for bed leveling:

    M190 S60

Advanced Stuff

Klipper lets you do a lot of advanced stuff. It’s a lot to cover, but here’s a brief overview of what you can do:

Tuning PIDs

It’s really simple to tune your extruder and bed PIDs. Just run PID_CALIBRATE HEATER=extruder TARGET=200 and PID_CALIBRATE HEATER=heater_bed TARGET=60. Don’t forget to SAVE_CONFIG after each run!

Resonance/Ringing Compensation

Do this before setting pressure advance, because it will change your values. When you start printing at higher speeds, you may see ringing. This is also fairly simple to fix by following this guide. Basically you print a model at very high accelerations, then measure the frequency of the ripples in the print. Then, you tell Klipper those frequencies and select the algorithm you want to make it go away:

shaper_freq_x: 45.5
shaper_freq_y: 46.8
shaper_type: ei

Pressure Advance

Setting pressure advance is really straightforward with these instructions. You just slice an stl file, then get the printer into a special mode, and print. Look for the height where your corners start becoming too rounded and calculate the value from there. Once you find the value, under [extruder] add pressure_advance with the number (e.g., between 0.5 and 0.9 for an Ender 3 v2) and you’re done! Now try printing at higher speeds and see how it goes.


Babystepping is easy with Klipper, enabling you to dial in your z-offset just right. While printing, simply issue SET_GCODE_OFFSET Z_ADJUST=0.01 MOVE=1 to move the head up 0.01. Reset to default with SET_GCODE_OFFSET Z=0.0 MOVE=1.

Custom Macros and G-Codes

At first glance, it looks like Klipper doesn’t support some g-codes that Marlin does. However, what Klipper supports is custom macros so you can create any g-code. For example, my G29 is:

[gcode_macro G29]
   G0 X0 Y0 Z10 F6000
   BED_MESH_PROFILE save=default

You can also create your very own ones! In Cura, my start and end g-codes are now START_PRINT T_BED={material_bed_temperature_layer_0} T_EXTRUDER={material_print_temperature_layer_0} and END_PRINT respectively. The actual commands are defined in printer.cfg using macros. This enables much easier porting between machines and slicers.

I recommend turning these commands into buttons in OctoPrint via the Custom Control Editor plugin.

Filament Load/Unload and M600

With Klipper, supporting M600 or any other command is trivial. I derived mine from a great set developed by a fellow Redditor. You can then simply use Cura scripts to enable two color prints!

What do I do with my LCD?

I’m sure at some point the regular LCD will be supported. For now, I removed the LCD completely and replaced it with a 3.5” TFT for the Pi with an enclosure from Thingiverse.

I originally published this as a Reddit post.