There have been several bugs in the auto leveling and distortion correction code. This documentation assumes you have version 0.92.8 from 03/01/2016 or later installed!

How it works

Before you start defining your auto leveling you should know what you are doing and what you can change and where you would change what error.
The most important tool is your z probe. That is a device switching a digital pin under some pressure like a switch and is connected to your extruder such
that it triggers normally before the nozzle hits the bed. Once you know the nozzle height above bed when it triggers we can use this to measure how the bed is positioned in z direction.

The first thing we normally do is level out the bed. To do so we measure at least 3 points and compute the average plane trough this. The difference to the theoretically constant z show us how much rotation is required to be everwhere on same height. This can be done through a software rotation (if z moves have no backlash) or through a mechanical movement of the bed sides (through motorized modification of 2 from 3 fix points). This works quite well, but neglects some errors:

  • Most beds are not totally flat. Especially under heat they get some bending
  • Measurement is not always 100% exact.
  • Measurement may bend your bed.

If that is a problem with your printer, you would measure a n x n grid to get a better approximation of the bed.

With z probes that require some considerable amount of force it may bend the bed depending on the position. For this we have a bending correction, that corrects measured values by bending. This is a bit limited especially if bending is not a linear function of x and y. Then you must limit measurements to 3 points for which you set the bending correction.

Even with an average plane for rotation, you still have bumps. With some luck the average bump is negligible and you can ignore it. In more extreme cases, especially with increasing bed sizes, it would be great to be able to follow the curvature of the bed for the first layers and remove that correction to zero with increasing z. That would help a big deal with correct bonding. This feature is called distortion correction and since 0.92.8 it is available for all printer types. It works by measuring a distortion map and storing it in eeprom (ideally) or ram (then you need to measure every time). Also since 0.92.8 we assume that distortion never changes, since it is a bed property. So recomputing the rotation will NOT reset the distortion map.

Configuring firmware


Since version 0.90 the Repetier-Firmware supports auto leveling. For auto leveling you need a z-probe to measure the distance in a automatic or semi-automatic fashion. An automatic z-probe is moved with the extruder, so that the firmware does not need to wait for user actions. A semi-automatic z-probe could be a switch used by cnc machines to measure tool height. Because it is not connected with the extruder, you need to position it underneath the extruder and click it once. Then the measurement will begin and after measurement, the extruder will move to the next position and wait for the next signal to start measurement. That way you can have a z-probe, where you do not need to consider on how to fix and activate it. First step is configuring the z-probe in the configuration.h file. Here the according settings part:

/* Z-Probing */
#define FEATURE_Z_PROBE true
#define Z_PROBE_PIN 63
#define Z_PROBE_PULLUP true
#define Z_PROBE_ON_HIGH true
#define Z_PROBE_X_OFFSET -11.2625
#define Z_PROBE_Y_OFFSET -6.5
// Waits for a signal to start. Valid signals are probe hit and ok button.
// This is needful if you have the probe trigger by hand.
/** Speed of z-axis in mm/s when probing */
#define Z_PROBE_SPEED 5
#define Z_PROBE_XY_SPEED 150
#define Z_PROBE_SWITCHING_DISTANCE 1.5 // Distance to safely switch off probe after it was activated
#define Z_PROBE_REPETITIONS 5 // Repetitions for probing at one point. 
/** The height is the difference between activated probe position and nozzle height. */
#define Z_PROBE_HEIGHT 39.91
/** Gap between probe and bed resp. extruder and z sensor. Must be greater then initial z height inaccuracy!  */
/** These scripts are run before resp. after the z-probe is done. Add here code to activate/deactivate probe if needed. */
/* Auto leveling allows it to z-probe 3 points to compute the inclination and compensates the error for the print.
 This feature requires a working z-probe and you should have z-endstop at the top not at the bottom.
 The same 3 points are used for the G33 command.
#define Z_PROBE_X1 -69.28
#define Z_PROBE_Y1 -40
#define Z_PROBE_X2 69.28
#define Z_PROBE_Y2 -40
#define Z_PROBE_X3 0
#define Z_PROBE_Y3 80

First you enable z-probe (FEATURE_Z_PROBE true) and define the pin, where it is connected (Z_PROBE_PIN). Like with endstops you can set the pullup (Z_PROBE_PULLUP) and invert the signal Z_PROBE_ON_HIGH). Many users like to use the z min endstop pins for this. That is ok, but you should be aware
that this does NOT mean you that you must define z min hardware endstop. It is only the z probe connected to the pin that could be used for this.
Next you define the offset relative to the extruder origin position (the basis you use to define extruder offsets). For single extruder setup this is the position of the nozzle. For multi-extruder setups the origin, from where you defined the extruder offsets.

If you need to manually move the z-probe, set Z_PROBE_WAIT_BEFORE_TEST to true. In that case, the extruder will hover over the measure points and wait for you to activate the switch once.

Z_PROBE_SPEED sets the probing speed in mm/s, while Z_PROBE_XY_SPEED is the speed in the xy plane. Z_PROBE_HEIGHT is the height difference between z-probe trigger and bed. This value is always added to the height, to compute the total height. Next comes Z_PROBE_BED_DISTANCE, which determines, at which height the probe will start measurements (probe height is added to this). You start with a guessed bed height, which you have set in the firmware. That height minus gap size must always be smaller then the real print area height. If you have some trick to enable/disable a z-probe, you can write the required g-code commands in Z_PROBE_START_SCRIPT and Z_PROBE_FINISHED_SCRIPT. Multiple commands are separated by a \n.

For more precise measurement you can repeat each point Z_PROBE_REPETITIONS times. After a probe is hit, the probe only lifts Z_PROBE_SWITCHING_DISTANCE mm. Depending on your probe type, this can be as less then 0.2 mm allowing very fast repetitions.


Now that we have a working z-probe, we enable auto leveling. For that you need to add “#define FEATURE_AUTOLEVEL 1”.
Then we define how we want the auto leveling to work. First we define how to measure the plane rotation. Currentyl 3 methods can be defined and set with BED_LEVELING_METHOD.


This method measures at the 3 probe points and creates a plane through these points. If you have
a really planar bed this gives the optimum result. The 3 points must not be in one line and have
a long distance to increase numerical stability. Delta printers should have them as close to the columns as possible.


This measures a grid. Probe point 1 is the origin and points 2 and 3 span a grid. We measure
BED_LEVELING_GRID_SIZE points in each direction and compute a regression plane through all
points. This gives a good overall plane if you have small bumps measuring inaccuracies.


Bending correcting 4 point measurement. This is for cantilevered beds that have the rotation axis
not at the side but inside the bed. Here we can assume no bending on the axis and a symmetric
bending to both sides of the axis. So probe points 2 and 3 build the symmetric axis and
point 1 is mirrored to 1m across the axis. Using the symmetry we then remove the bending
from 1 and use that as plane.

Next you should decide on the correction method. This correction is defined by BED_CORRECTION_METHOD and allows the following values:


Use a rotation matrix. This will make z axis go up/down while moving in x/y direction to compensate
the tilt. For multiple extruders make sure the height match the tilt of the bed or one will scratch.


Motorized correction. This method needs a bed that is fixed on 3 points from which 2 have a motor
to change the height. The positions are defined by
Motor 2 and 3 are the one driven by motor driver 0 and 1. These can be extra motors like Felix Pro 1
uses them or a system with 3 z axis where motors can be controlled individually like the Sparkcube

You need also to set the following parameter:

#define Z_HOME_DIR 1

The first makes the z-axis go down a few mm after hitting the endstop. This is needed, because we assume a not even bed and correct z height during x-y-travel. It is important not to hit the z-endstop during these travels or your coordinate system gets wrong. The value must be larger then the maximum height difference of your bed. Delta printer user have a special problem at z max. There it is not possible to move the extruder without hitting an endstop. Printing at that height is also not possible for the same reason, so it is a good idea to set ENDSTOP_Z_BACK_MOVE to even higher values where some movements are possible like 50mm. Remember that a slight bed tilt also needs a side move! The second sets homing to z-max. This again is required, because the bed is not planar. If we had a z-min endstop, it should only get triggered where the bed has it’s lowest point. Of course this would mean, that for all other positions homing to z-min would crash the extruder head into the bed.

Verify z-probe

Before you risk any damage, you should test, if you have configured the z-probe correctly. Run a


to check the signal of the z-probe. It should be low/off. Now trigger it by hand and send the command again. Make sure the signal is now inverted.

Next home and measure the distance between extruder and bed. Some commands like G30/G32 will go to a lower position when started, namely Z_PROBE_BED_DISTANCE + Z_PROBE_HEIGHT, so make sure that is everywhere above the bed!

Now that this works, make your first real probe. Move your extruder to a position you want to measure and send:


The extruder will now descent, until the z-probe gets triggered and then go back to the starting position. In your log, you should then find the distance needed to trigger the z-probe. For a first test you may start with plenty of room and trigger the switch manually, just to test if it reverse, which should be the case if you set up the probe correctly. If you have a semi-automatic z-probe hit the probe first to start probing.

Automatic correction

Now that everything is configured and working we can start adjusting the bed. Before using the leveling commands you need to at least home x and y axis. Deltas will home on G32, so they can skip this. Depending on the measurement method you have more or less testing points and time can be greatly reduced if we have to move less in z direction. When we have homed also in z axis the probe gets positioned at Z_PROBE_BED_DISTANCE + Z_PROBE_HEIGHT (if positive). You should select
Z_PROBE_BED_DISTANCE such that it is higher then every expected tilt. If you have only homed x and y as you do not want to home to max z for the time it takes, you should know that the height you enabled the printer is 0 internally until you home. So positioning will be normally higher.

One simple method is G33. It will measure 3 heights (at probing points) and use the average as printer height. This requires homing to z max before starting it.

The much better solution is to correct the possible rotation. We have already defined how we measure and how we correct, so there is no real difference any more. The command to start autoleveling is G32 with optional Sx parameter. What then happen is the following procedure:

  1. Disabling distortion correction and autolevelig. Autoleveling rotation matrix gets reset.
  2. Delta printers will home and go down again to starting height.
  3. If you are higher then max. starting height the probe will lower to that height.
  4. Measuring and correcting rotation.
  5. If you have a max z endstop and parameter S was not 0, we update the printer height so later homing gives correct results. Make sure to do this only IF you had homed to z max before or you get completely wrong heights.
  6. Update current position.
  7. Store new matrix in EEPROm if parameter S is 2 or higher.
  8. Enable automatic correction.
  9. Enable distortion correction if it was enabled before.
  10. Nonlinear printers like deltas will home again to get right positioning.

Older firmware versions (< 0.92.8) had S1 for measuring and update z length. This is now done always for z max homing as long as S is not 0.

Delta printer

Important: Newer firmware versions (greater than 0.92) use G33 for distorsion correction instaed of G29.

Delta printer need more calibration then normal cartesian printer. You need to calibrate the endstops first. This calibration changes the values you see in the eeprom configuration as “Tower X endstop offset [steps]” resp. Y and Z. The trick is simple. After homing to the max endstops, the firmware will move these steps down to position the extruder holder in the exact center. It is essential to define the exact center position or the nonlinear behavior of delta mechanics will result in wrong geometries. Measuring these values on your own is nearly impossible, so you need to use a simple trick. First home and remove any extruder offset using these commands:


Now position the 3 sliders, so that they are at the same height. To do this I use a stick and position all sliders, so that they press the stick lightly against the printer top, as I know it will be centered then. Depending on your printer it might be better to measure from the bottom (not the bed – that might be skewed in addition). The hard way is to use moves in x,y,z direction. The easy way is turn motors off with “M84” and slide by hand. Be careful not to slide fast. Movements create a current in the motors flowing back to the electronics. Since some printers will move down when motors are disabled, newer versions have a command to only disable one motor for a time. So now the best way is to use M99 X0 to move the X motor for 10 seconds. You can change the time with S<time in seconds>. Use Y0 and Z0 for the other 2 axis. Once all sliders are at the exact same height, send:

 G132 S1

That will measure the required offsets. S1 additionally stores the result in EEPROM, so you do not need to repeat it again.

After the endstops are calibrated, you can run the bed leveling routine the same way as for cartesian printers.

Enabling and disabling autolevel

Once you run auto level G32, the firmware switches to auto level mode. If you stored it in EEPROM (adding S2) it even survives printer restarts. Then new leveling is only needed if you have to assume that bed has changed the height. You can change this with:

M320 ; Activate auto level temporarily
M320 S2 ; Activate auto level permanently
M321 ; Deactivate autolevel temporarily
M321 S2 ; Deactivate auto level permanently
M322 ; Reset auto level matrix
M322 S3 ; Reset auto level matrix permanently

If you reset the auto level matrix you have the same behavior with enabled and disabled auto level.

Distortion correction

With some luck you are already finished. If your bed is not 100% flat or for delta printers, if your geometry description is not 100% correct you still have different heights between bed and extruder nozzle. Since 0.92.8 this can be corrected using a distortion map. What we do is that we measure a fixed grid of n x n values and store the difference between theoretical height and measured height in a bump map in eeprom (or in ram, but then you need to repeat that every time). This is done using the G33 command. It will measure a grid as you have defined it in your configuration. Start this command only if your z is set correctly. After it is finished, it enables distortion correction. Now your nozzle will also follow the bumps. With increasing z it will reduce the correction until it does not correct z any more.

G33 has also 3 special commands.

List bump map

With G33 L0 you will get a listing of all measured bumps and the stored correction. These values get added to z at the respective positions and between the points z correction gets interpolated.

Adjust bump map

G33 X<xpos> Y<ypos> Z<newCorrection>

will set a new correction value to the closest stored position. So you do not need to enter the exact position from the G33 L0 list.

Reset bump map

G33 R0

will set all corrections to 0.

Switching distortion correction on/off

M323 ; Show if correction is enabled
M323 S0 ; Disable correction
M323 S0 P1 ; Disable correction permanently
M323 S1 ; Enable correction
M323 S1 P1 ; Enable correction permanently

Manual Bed Correction

The alternative is to level the bed, so it is square to x-y-moves. This requires less computations and also does not wear out the z-axis as much as the auto leveling (this is equal to mechanical auto leveling). The only drawback is, that it is more work to set it up as good. The easiest solution is with beds supported by only 3 points. In that case you make the 3 measurement points identical to your bed supports. The method is quite simple. You send “G33” and the firmware will measure and output the heights at the three points. Then you change your bed to make them identical and retry. If you are satisfied and if you have a z-max endstop you can also send a “G33 S2” to measure the print area height and store it in eeprom (S1 will only measure the height).