Skip to main content

Installing a BLTouch on an Ender 3: Mount, Wiring, and Probe Offsets

·3447 words·17 mins
Emiliano Fernández Cervantes
Author
Emiliano Fernández Cervantes
I build things where hardware meets software: Verilog architectures, biomedical instrumentation, and a home lab that keeps growing.
Ender 3 Upgrade - This article is part of a series.
Part 3: This Article

Have you spent an evening chasing a perfect first layer, only to nail one side of the bed and lose the other? Manual bed levelling on a stock Ender 3 is a ritual: four knobs, a sheet of paper, and a first layer that is beautiful on the left side of the bed and translucent on the right. The problem is not that you are bad at turning knobs. It is that the bed is not flat, and no amount of adjusting four corners will fix a surface that bows in the middle.

A BLTouch solves this differently. Instead of asking you to make the bed flat, it measures how unflat the bed is and tells the printer to follow that shape. This post covers adding one to an Ender 3 that already has a BIGTREETECH SKR Mini E3 V2.0 in it: printing a mount, wiring the probe, and (the part that actually determines whether it works) measuring the offsets between the probe and the nozzle.

I did not work this out from first principles. The procedure below follows Teaching Tech’s BLtouch for any 3D printer - Comprehensive step by step guide, which is the video I had open on a second screen while I installed mine. What I add here is everything specific to this machine: the SKR Mini E3 V2.0 wiring, the offsets I measured on my own mount, and the numbers that only show up once you run the arithmetic for your own geometry.

This is part 3 of five. Part 2 covered the board swap that makes this part easy, and part 4 compiles the firmware that ties everything together.

Placeholder graphic reading BLTouch mounted photo coming soon
The BLTouch mounted next to the hotend on a printed bracket, pin deployed.

What the BLTouch actually is
#

The name suggests something exotic, but the mechanism is simple and clever. Inside the housing there is a small push pin and a solenoid, plus a Hall-effect sensor that detects the pin’s position magnetically.

To take a measurement, the firmware energises the solenoid, which drops the pin. The printer then lowers the Z axis until the pin touches the bed and is pushed back up into the body; the Hall sensor sees that motion and the probe sends a trigger signal, exactly like an endstop switch closing. The firmware records the Z height at that instant, then retracts the pin and moves on to the next point.

Do that at a grid of points across the bed and you have a mesh: a map of how high or low the bed sits at each location. During a print, Marlin adjusts Z continuously against that mesh, so the nozzle traces the real surface instead of an imaginary flat plane.

Two practical consequences of the mechanism are worth knowing before you install one:

  • It touches the bed with a plastic pin, not with the nozzle. So it measures whatever surface you probe on, and it will happily probe a bed clip and give you a nonsense reading.
  • It self-tests on power-up. When you switch the printer on, the pin should deploy and retract a couple of times and end up retracted, with a steady red light. That little dance is your first and best diagnostic: if it does not happen, or the pin ends up stuck out and blinking, the probe has a wiring or power problem and there is no point moving on to firmware.

Printing the mount
#

The BLTouch does not come with a way to attach itself to an Ender 3. You print one.

I used (Yet Another) Ender 3 BLTouch Mount by Thingiverse user StevenMLawson (licensed under Creative Commons). It replaces the front cover of the hotend fan shroud and holds the probe out to the left of the nozzle, which is what makes the X offset as large as it is later on.

The download contains two models:

  • BLTouchMount.STL: the plain version, which is the one I printed.
  • BLTouchMount-Laser.STL: a variant with provision for a laser module, which you only want if you are actually mounting one.

Print it in PETG if you can. This part sits directly next to the heater block. PLA is fine for a while, but one hot summer print later your probe is quietly drooping a fraction of a millimetre out of position, which shows up as a bad first layer you will spend an evening chasing. PETG or ABS avoids the whole issue.

Settings-wise nothing exotic: 0.2 mm layers, 4 perimeters, 30–40 % infill. This part holds the alignment of your measuring instrument, so it is worth printing solidly and worth checking that it came out without warping before you bolt a probe to it.

Mount it with the hotend fan screws, using M3 hardware. The general rule is to put the probe as close to the nozzle as you can without it failing from heat exposure, and to bolt it down tight, because any play or wobble in the bracket destroys the accuracy of every reading it takes. Three things to check once it is on:

  1. The probe body is square to the bed, and there is no play in the mount. A tilted probe measures a tilted mesh, and a loose one measures a different bed every time.
  2. The retracted pin sits between 2.3 mm and 4.3 mm above the nozzle tip. That is Antclabs’ own window, and the reason it has two edges is that the pin’s stroke is fixed, so the probe fails in a different way at each end. Mount it too high and the deployed pin no longer reaches far enough below the nozzle to touch the bed first: the nozzle arrives first, the probe never triggers, and Marlin keeps driving Z down because as far as it knows the bed is still out of reach. That is the dangerous end of the range, and it ends with the nozzle buried in your build surface. Mount it too low and probing itself works fine, but the retracted pin now hangs down into the work for the rest of the print. Setting the height is easier than it sounds. With the printer powered off, lower the print head by hand until the nozzle rests on the bed, then use a 3 mm allen key as a spacer to set the probe’s height against it. If the bracket does not let the probe slide, shim it with washers until it lands in the window.
  3. Nothing on the bed for the retracted pin to catch. This is the low end of that same concern, checked against your actual machine instead of against a number: deploy the pin by hand at various positions and confirm that it never lands on a bed clip when the printer probes near an edge, and that it has nothing to snag on as the head crosses a tall part.
Placeholder graphic reading Printed mount photo coming soon
The printed BLTouch bracket fresh off the bed, before mounting.

Wiring it up
#

A BLTouch comes with five wires, normally split into two connectors:

  • A 3-pin connector: brown (GND), red (5 V), and orange/yellow (the control signal, which behaves like a servo signal and tells the pin to deploy or stow).
  • A 2-pin connector: black (GND) and white (the trigger signal, which behaves like an endstop).

On most boards you have to route those two connectors to two different places, which is exactly the awkwardness that made adding a probe to the stock Creality board annoying. The SKR Mini E3 V2.0 has a dedicated probe header that takes both, so this is a single plug.

In firmware terms, that header maps to two pins on the STM32: the trigger signal lands on PC14 and the servo control on PA1. You will see PC14 appear explicitly in the configuration in part 4, as:

#define Z_MIN_PROBE_PIN PC14

Watch the polarity of the connector. The probe header is keyed, but the cable that ships with a BLTouch is not always crimped in the order you expect, and 5 V into the signal pin is a bad afternoon. Compare the wire colours against the pin labels silkscreened next to the header before you push it home.

What about the original Z endstop switch? Leave it plugged in. The probe has its own dedicated pin, so the mechanical switch on the Z axis does not conflict with it, and keeping it costs nothing. The firmware will use the probe for homing Z (that is the USE_PROBE_FOR_Z_HOMING option) while the switch stays wired as the plain Z-min endstop.

Route the cable along the existing loom to the hotend, with enough slack that a full-travel move in X and Y does not tug on it, and enough restraint that it never dips into the path of the gantry. Cable ties and the existing sleeve are your friends here.

Placeholder graphic reading BLTouch wiring photo coming soon
The BLTouch’s 5-pin connector plugged into the dedicated probe header on the SKR Mini E3 V2.0.

Testing the probe before trusting it
#

Before any levelling, confirm the probe responds to commands. Connect over USB and send these one at a time:

M280 P0 S10    ; deploy the pin
M280 P0 S90    ; stow the pin
M280 P0 S120   ; run the self-test (pin cycles repeatedly)
M280 P0 S160   ; reset / clear an alarm state

If S10 and S90 work, your servo signal is wired correctly and the firmware is talking to the probe. Send S120 and let it cycle a few times, then S160 to stop it.

Next, confirm the trigger signal, which is a separate wire and can be wrong even when deploy and stow work perfectly. Deploy the pin, then send:

M119

Look for the z_probe line, or z_min if your build has no separate probe pin. Once an auto bed levelling probe is configured, Marlin gives it a status line of its own, and this build has a dedicated Z_MIN_PROBE_PIN, so z_probe is the line that matters here.

Push the pin up by hand and send M119 again: the state should flip. Here is the detail that sends people chasing imaginary faults: a BLTouch reports the opposite of what you expect from an endstop. With the pin retracted and idle it reads TRIGGERED, and with the pin deployed and waiting for the bed it reads open. Read that polarity the intuitive way around and you will conclude that a perfectly healthy probe is broken. What you are confirming is simply that the two states change when the pin moves. A probe that deploys beautifully but never changes state at all will drive the nozzle straight into the bed on the first G28, so do not skip this.


The part that actually matters: probe offsets
#

The BLTouch does not sit where the nozzle sits. It hangs off to one side, at a different height. Every measurement it takes is therefore taken somewhere else, and the firmware needs to know exactly where in order to convert probe readings into nozzle heights.

That is one setting, three numbers:

#define NOZZLE_TO_PROBE_OFFSET { -41, -12, -1.925 }

Those are the numbers I ended up with for this mount. Do not copy them blindly: X and Y depend on your bracket, and Z depends on your specific probe, bracket and how it is bolted on. Here is how to get your own.

X and Y: where the probe is relative to the nozzle
#

The values are measured from the nozzle to the probe, in printer coordinates. Negative X means the probe is to the left of the nozzle; negative Y means it is in front.

The reliable low-tech method:

  1. Tape a sheet of paper to the bed and home the printer.
  2. Move the nozzle down until it just touches the paper, and mark the exact point under the nozzle tip.
  3. Raise Z, then move the carriage so that the probe pin is over that mark, using the printer’s own jog controls, and deploy the pin so it touches the paper. Mark that point too.
  4. Read the X and Y distances between the two marks with a caliper, and work out the signs by which way you had to move.

A caliper straight onto the hardware works as well if the geometry is accessible: measure the horizontal distance between the centre of the nozzle and the centre of the probe pin in each axis. For my mount that came out as 41 mm to the left and 12 mm forward, hence -41 and -12.

Moreover, those numbers have a real cost, and it is worth doing the arithmetic instead of guessing at it. The carriage only travels so far, so a probe hanging 41 mm to one side simply cannot reach the far strip of the bed. Add the 10 mm PROBING_MARGIN that keeps probe points away from the edges (both values are set in part 4) and Marlin clamps the probed region on a 235 × 235 mm bed to:

  • X: 10 mm to 194 mm, which is 184 mm of the 235 mm available. The far end comes straight from the offset (235 − 41 = 194) and the near end from the margin.
  • Y: 10 mm to 223 mm, which is 213 mm. Here the 12 mm offset costs far less (235 − 12 = 223), and the margin again sets the near edge.

So the probe actually touches about 184 × 213 mm out of 235 × 235 mm, which leaves close to 30 % of the bed area never measured directly. Run that same subtraction with your own offsets and margin and you will know your own number before you print anything.

That unmeasured border is exactly why part 4 enables EXTRAPOLATE_BEYOND_GRID, which extends the mesh past the outermost probe points so the edges and corners still receive a correction instead of falling off the map.

Z: how far below the trigger point the nozzle sits
#

This is the number that decides whether your first layer is perfect or a smear, and unlike X and Y you cannot get it with a ruler.

The classic procedure:

  1. Home the printer with G28, then send M851 Z0 and M500 to zero out any stored offset and start from a known state.
  2. Move to the middle of the bed and lower Z in small steps with a sheet of paper under the nozzle, until the paper drags slightly. Note the Z value on the display. That negative number is your offset.
  3. Set it and save it:
M851 Z-1.925
M500

Marlin also ships a guided version of exactly this, the probe offset wizard, which walks you through it from the LCD and stores the result for you. It is enabled in the firmware built in part 4, precisely because doing this by hand is fiddly and you will want to redo it any time you change nozzles or re-mount the probe. One detail that costs people an afternoon of searching: PROBE_OFFSET_WIZARD does not live in Configuration.h, where every other setting this series quotes lives, but in Configuration_adv.h, the second and much longer config file. Marlin even leaves a note about it in the first file, pointing across: “PROBE_OFFSET_WIZARD (configuration_adv.h) can be used for setting the Z offset.”

The other tool worth enabling for this is babystepping with BABYSTEP_ZPROBE_OFFSET, which lives in Configuration_adv.h as well. That lets you nudge Z live, during the first layer of a print, and have the adjustment written back into the probe offset instead of being lost when the print ends. Start a large first layer and watch it; on this build you reach the adjustment with a double-click on the status screen (that is DOUBLECLICK_FOR_Z_BABYSTEPPING, also enabled), then nudge until the extrusion looks right and save with M500. It is by far the fastest way to converge on a good number.


Levelling, and making it stick
#

With offsets set, the actual levelling workflow is short:

G28        ; home all axes (Z now homes with the probe)
G29        ; probe the grid and build the mesh
M500       ; save the mesh to EEPROM

G28 first is not optional, and the reason is more specific than “measure only what you have homed.” Marlin’s own Configuration.h says it plainly: “Normally G28 leaves leveling disabled on completion.” Homing does not merely fail to enable compensation, it actively switches it off. That is why M420 S1 has to come afterwards to turn it back on, and it is the same reason the re-probe variant further down puts G29 after G28 and never before. With a probe installed, Marlin also insists on homing Z at a safe spot rather than at the corner (the Z_SAFE_HOMING option), because at the far corner the probe would be hanging off the edge of the bed with nothing under it.

Then there is the step everyone forgets. Saving the mesh does not mean the printer uses it. The mesh has to be loaded and enabled at the start of every print, which is one line in your slicer’s start G-code:

M420 S1

Put it after the G28 in the start sequence. Without it, the printer dutifully stores a perfect map of your bed and then ignores it, and you conclude that auto bed levelling does not work.

If you would rather re-probe before every print instead of relying on a stored mesh, replace M420 S1 with a G29 in the start G-code, still after the G28. It costs a minute or two per print and is more robust if you move the printer around or swap build surfaces often.

Placeholder graphic reading Bed mesh result screenshot coming soon
The bed mesh after a G29, showing how far from flat the bed actually is.

Why tall prints stop following the bed
#

There is one behaviour that surprises almost everyone the first time they notice it: the correction fades out with height. ENABLE_LEVELING_FADE_HEIGHT is enabled by default in Marlin, with DEFAULT_LEVELING_FADE_HEIGHT 10.0, and both are live exactly as written in the firmware running on my machine. I did not choose that value, I inherited it, and after building the firmware myself I would rather know what it is doing than be surprised by it later. The comment in Configuration.h describes it precisely: “Gradually reduce leveling correction until a set height is reached, at which point movement will be level to the machine’s XY plane.”

In other words, my printer does all of the mesh’s work over the first 10 mm of a print and then tapers it away, and above that it moves in its own flat plane rather than following the shape of the bed. That is deliberate and it is the behaviour you want: bed compensation exists to rescue the first layers, not to skew a 200 mm tall part along the warp of the glass. If you ever want to change it, M420 Z<height> sets the fade height at runtime.


When it does not work
#

The pin blinks red and stays down. That is an alarm state, usually caused by the pin being obstructed, the probe being knocked, or a bad connection. Send M280 P0 S160 to reset it. If it re-alarms immediately, check the pin can move freely.

No self-test at power-up. No self-test means no 5 V or no ground: a wiring problem, not a firmware one.

Deploys and stows, but the printer crashes into the bed. The control signal is fine and the trigger signal is not. Go back to the M119 test above.

The mesh looks like a mountain range. Values varying by more than a few tenths of a millimetre usually mean something mechanical: a loose probe bracket, a bed spring with no tension left, or a probe that is not square to the bed. Fix it there, not in software.

The first layer is uniformly too high or too low. That is purely the Z offset. Babystep it during a print until it looks right and save with M500.


What you gain, and what is next
#

With the probe mounted, wired, and its offsets measured, your Ender 3 no longer needs the four-knob ritual. It measures its own bed and Marlin corrects for it automatically, print after print. Mine went from a first layer that depended on which corner I babysat to one that is consistent from edge to edge, which is the kind of unglamorous, repeatable result that actually matters day to day.

Getting there, though, assumed a firmware that already knows about the probe: that BLTOUCH is enabled, that the probe is on PC14, that bilinear bed levelling is turned on, that the offsets are stored. That firmware does not come from anywhere by magic.

Part 4 builds it: VS Code, PlatformIO, Auto Build Marlin, and the specific set of configuration changes that turn a generic Marlin download into firmware for this exact machine.

Ender 3 Upgrade - This article is part of a series.
Part 3: This Article