I couldn’t find any OctoPrint plugin to help me with the process of calibrating and setting the correct Z probe offset, so I tried to realize this with OctoPrints custom controls. The goal was to avoid having to enter the Z probe offset manually and be able to use 0.02 mm baby steps to find the correct Z probe offset.

The basic steps to calibrate and set the Z probe offset are the following:

  1. Setup: Home all axis, reset the Z probe offset to 0, disable soft endstop for Z, move the hotend to the middle of the bed and lower it to position 0
  2. Calibration: Now you must move the hotend down until the nozzle touches the bed (maybe with a sheet of paper in between)
  3. Save: Read the negative Z position from the display and set it as Z probe offset via the appropriate GCODE commands, then enable the soft endstop again

Step 1 and 2 are easy to realize with OctoPrints custom controls. Step 3 gets a little bit tricky, because the custom controls do allow to capture the Z position via a regex, but there is no way to use the captured value of the regex as a parameter for the M851 command. But fortunately a custom control can execute a JavaScript, so this can be used for a little ‘hackish’ solution.

Here’s what my custom controls config looks like:

controls:
- name: Probe-Z-Offset-Calibration
  collapsed: true
  layout: horizontal
  children:
  - name: Start
    commands:
    - M851 Z0                # reset Z probe offset
    - G28                    # home all axis
    - G1 X110 Y110 Z0 F3000  # postion hotend
    - M211 S0                # disable soft endstop, so we can move below 0
    - M 114                  # read postion
  - name: Z+0.1
    commands:
    - G91                    # relative mode
    - G1 Z0.1 F150           # move up by 0.1mm
    - G90                    # absolute mode
    - M114                   # read postion
  - name: Z+0.02
    commands:
    - G91                    # relative mode
    - G1 Z0.02 F150          # move up by 0.02mm
    - G90                    # absolute mode
    - M114                   # read postion
  - name: Z-0.02
    commands:
    - G91                   # relative mode
    - G1 Z-0.02 F150        # move down by 0.02mm
    - G90                   # absolute mode
    - M114                  # read postion
  - name: Z-0.1
    commands:
    - G91                   # relative mode
    - G1 Z-0.1 F150         # move down by 0.1mm
    - G90                   # absolute mode
    - M114                  # read postion
  - name: Z-Offset-Label
    regex: 'X:.+ Y:.+ Z:(?P<offset>[+-]?\d+(\.\d+)?) E:'
    template: 'Z-Offset: {offset}'
    width: '50'
  - name: Save Z-Offset
    # JavaScript will get the Z offset from the Z-Offset-Label, use M851 to set it, M500 to store it
    # and will enable the soft endstop again
    javascript: |
      var customControls = document.getElementsByClassName('custom_control');
      for (var i = 0; i < customControls.length; i++) {
    match = customControls[i].firstElementChild.textContent.match(/Z-Offset: ([+-]?\d+\.\d+)/);
    if (match) {
      self.sendCustomCommand({commands: ['M851 Z' + match[1], 'M500', 'M211 S1']});
    }
      }

And this is how it looks like on the UI:

Screenshot

You might want to adjust the X/Y in the start commands to match your bed dimensions. Please note, that the JavaScript formatting in the config.yaml does not get preserved by OctoPrint, so once you’ve changed the config and restarted OctoPrint, it will get “messed up” a little bit, but still works fine.

With these custom controls in place, all you now have to do is, to press the Start button, Use the Z+/- buttons to find the correct Z position of the nozzle and then press Save.

This was tested with Marlin 2.0.3 and OctoPrint 1.3.12 on an ANET-A8 printer.