Build Sheet Manager & "Adjust Live Z"

This is a small group of macros that implements Prusa’s Build Sheet system and Adjust Live Z behavior in klipper. Specifically:

  • You can have as many build sheets as you like, each with a unique human readable name
  • Each sheet has its own Z offset
  • A sheet can be installed in the printer and this persists across restarts.
  • When you “Adjust Live Z” (AKA Baby Stepping) with your klipper UI of choice the offset change is saved instantly to the sheet that is installed.
  • Anything thats not a true “Adjust Live Z” call wont change the sheet’s z-offset value. You need to set MOVE=1 and ADJUST_Z= in your call to SET_GCODE_OFFSET. This is how Fluidd, Mainsail & Klipper Screen etc do it. All other call patterns wont change the sheet offset.

Requirements:

  • You have [save_variables] set up
  • You need to call the APPLY_BUILD_SHEET_ADJUSTMENT in your PRINT_START macro after you calibrate your Z offset. This is when the sheet offset is applied.
  • Last but most important: Your PRINT_START macro must set your Z Offset. You can do this with a plugin like CALIBRATE_Z. Or, you can add a line to your PRINT_START to reset the Z offset to the correct value for your printer: SET_GCODE_OFFSET Z=0.0. This macro doesn’t try to keep track of the state of the z offset, that’s on you. If you don’t do this the APPLY_BUILD_SHEET_ADJUSTMENT call will apply the same adjustment multiple times and you will crash your printer.

Nice To Have:

  • You’ll probably want to make some small macros for each build sheet you have to make swapping them easy. E.g. :
[gcode_macro INSTALL_TEXTURED_SHEET]
gcode:
    INSTALL_BUILD_SHEET NAME="Textured PEI Sheet"
  • In your PRINT_START you can add a call to SHOW_BUILD_SHEET at the start and end. This prints the build sheet name and offset to the console. This can be helpful and remind you if you forgot to swap sheets!

Macros:

## Macro to install a build sheet
[gcode_macro INSTALL_BUILD_SHEET]
description: Install a build sheet and save settings
variable_parameter_NAME: "Unknown Build Sheet"
variable_parameter_OFFSET: 0.0
gcode:
    {% set svv = printer.save_variables.variables %}
    {% set sheet_name = (params.NAME | default("Unknown Build Sheet") | string) %}    
    {% set sheet_offset = (params.OFFSET | default(0.0) | float) %}
    {% set sheet_key = ("build_sheet " ~ (sheet_name | lower | replace(" ", "_"))) %}
    {% set sheet = (svv[sheet_key] | default(None)) %}
    {% if not sheet %}
        # the sheet does not exist, create it
        {% set sheet_literal = ('{"name": "%s", "offset": %.3f}' % (sheet_name, sheet_offset)) %}
        SAVE_VARIABLE VARIABLE="{sheet_key}" VALUE='{sheet_literal}'
    {% endif %}
    SAVE_VARIABLE VARIABLE="build_sheet installed" VALUE="'{sheet_key}'"
    SHOW_BUILD_SHEET

[gcode_macro SHOW_BUILD_SHEET]
gcode:
    {% set svv = printer.save_variables.variables %}
    {% set sheet_key = (svv["build_sheet installed"] | string) %}
    {% set sheet = (svv[sheet_key] | default(None)) %}
    {% if sheet %}
        {action_respond_info("Build sheet: %s, Offset: %.3fmm" % (sheet.name, sheet.offset))}
    {% else %}
        {action_respond_info("No build sheet installed") }
    {% endif %}

[gcode_macro SET_BUILD_SHEET_OFFSET]
description: Set an arbitrary offset for the build sheet
variable_parameter_OFFSET: 0.0
gcode:
    {% set svv = printer.save_variables.variables %}
    {% set sheet_offset = (params.OFFSET | default(0.0) | float) %}
    {% set sheet_key = (svv["build_sheet installed"] | string) %}
    {% set sheet = (svv[sheet_key] | default(None)) %}
    {% if sheet %}
        {% set sheet_literal = ('{"name": "%s", "offset": %.3f}' % (sheet.name, sheet_offset)) %}
        SAVE_VARIABLE VARIABLE="{sheet_key}" VALUE='{sheet_literal}'
    {% endif %}
    SHOW_BUILD_SHEET

[gcode_macro RESET_BUILD_SHEET_OFFSET]
description: Set the build sheet offset to 0.0
gcode:
    SET_BUILD_SHEET_OFFSET OFFSET=0.0

[gcode_macro SET_GCODE_OFFSET]
rename_existing: _BUILD_SHEETS__SET_GCODE_OFFSET
gcode:
    # this runs first so if the caller messed up the params it failes
    _BUILD_SHEETS__SET_GCODE_OFFSET {% for p in params
            %}{'%s=%s ' % (p, params[p])}{%
           endfor %}

    {% set svv = printer.save_variables.variables %}
    {% set sheet_key = (svv["build_sheet installed"] | string) %}
    {% set sheet = (svv[sheet_key] | default(None)) %}
    {% if sheet and (params.Z_ADJUST is defined) and ((params.Z_ADJUST | float) != 0.0) and ((params.MOVE | int) == 1) %}
        {% set offset = (sheet.offset + (params.Z_ADJUST | default(0.0) | float)) %}
        {% set sheet_literal = ('{"name": "%s", "offset": %.3f}' % (sheet.name, offset)) %}
        SAVE_VARIABLE VARIABLE="{sheet_key}" VALUE='{sheet_literal}'
        SHOW_BUILD_SHEET
    {% endif %}

[gcode_macro APPLY_BUILD_SHEET_ADJUSTMENT]
description: Applies the sheet offset adjustment for the installed build sheet, call from your PRINT_START macro
gcode:
    # get the offset from saved variables
    {% set svv = printer.save_variables.variables %}
    {% set sheet_key = (svv["build_sheet installed"] | string) %}
    {% set sheet = (svv[sheet_key] | default(None)) %}
    {% if sheet %}
        # log this to the console so if there is an issue with the print the user can see which sheet the printer thought it had installed
        {action_respond_info("Applying offset: %.3fmm for build sheet: %s" % (sheet.offset, sheet.name))}
        _BUILD_SHEETS__SET_GCODE_OFFSET Z_ADJUST={sheet.offset} MOVE=1
    {% else %}
        {action_respond_info("No build sheet installed, offset adjustment: 0.000mm") }
    {% endif %}

My file on GitHub: klipper-voron2.4-config/build-sheets.cfg at mainline · garethky/klipper-voron2.4-config · GitHub

Enjoy, let me know how its working for you, your suggestions and all my terrible spelling mistakes. :beers:

5 Likes

You can add a menu to KlipperScreen to change build sheets like this:

[menu __main actions build_sheets]
name: Build Sheets
icon: bed-level

[menu __main actions build_sheets smooth_pei]
name: Smooth PEI
method: printer.gcode.script
params: {"script":"INSTALL_SMOOTH_PEI_SHEET"}

[menu __main actions build_sheets textured_pei]
name: Textured PEI
method: printer.gcode.script
params: {"script":"INSTALL_TEXTURED_PEI_SHEET"}

[menu __main actions build_sheets smooth_garolite]
name: Smooth Garolite
method: printer.gcode.script
params: {"script":"INSTALL_SMOOTH_GAROLITE_SHEET"}

[menu __main actions build_sheets textured_garolite]
name: Textured Garolite
method: printer.gcode.script
params: {"script":"INSTALL_TEXTURED_GAROLITE_SHEET"}
1 Like

Although I have Voron TAP installed, I use this macro to differentiate between smooth and textured beds. I love it!

1 Like

Got a question on this. I’ve been using it for a while and just realized its never been working the way I needed it to, and I’m not sure if I’m doing something wrong or not.

I have a few different magnetic print beds, and my printer probes with a capacitive sensor (so its reading the metal surface, not what is on top. The surfaces vary quite a bit from a fraction of a millimeter to several millimeters thick.

What I’m seeing is that any time I use z babystepping to adjust the print height for a given bed type and then save the Z-height, it both saves the Z-height in variables.cfg and seems to apply the offset to the z_offset in printer.cfg as well, so at the next restart, everything is off by that amount.

Do these not work with probes where the trigger height isn’t at 0? Its not clear how the probe z_height, the gcode z_height and the offsets all relate. Everything just keeps shifting around, so nothing stays calibrated if the babystepping is touched.

On top of that, it seems like using the Mainsail option to reset the Z offset to zero does it in Mainsail, but does something weird in these scripts such that the script doesn’t see that, and baby stepping from there adjusts from the original offset.

Thanks for any tips!

Sorry, changing my answer after re-reading this:

This plugin auto saves the babystepping value. You shouldn’t save the z offset to the printers config after you do any babystepping. Youll save the sum of the offset AND the babystepping. Then the babystepping will be added again by this macro.

Home the printer with the probe and call 0. Then store the babystepping with this macro.

So, you don’t have to set the value to 0, but you have to set it to something. If you let the value carry over between prints you will get the behaviour you describe.

The adjustment value gets added to the offset. At the end of the print it’s still in there. If you start the print over you’ll add it in a second time. Unless you set the offset to a value in print start.

Do you home z only on boot-up and not in the PRINT_START macro?

Yeah, after I posted it, I was poking through the code and figured that out.

It wasn’t obvious that the macros change the core behavior of babystepping in Klipper (that being that its transient unless saved), and any tools that follow the core behavior will break the macros. Its certainly unexpected (and breaks a lot of workflows relative to tweaking first layers for specific filament and materials, etc).

Temporarily I just override Z_OFFSET_APPLY_PROBE to not do anything if a build sheet is set, which keeps the z_probe stable since pretty much all of the various UIs prompt for saving and if you forget you shouldn’t, it breaks not only the current bed profile, but all the others.

So that’s something people just need to be aware of – don’t use any of the built-in mechanisms for doing probe or endstop calibration, or manually save the babystepping if using these.

Thanks!

1 Like

The point of this tool is that all that ceremony of storing “one true offset” and rebooting goes away. If you’ve used a Prusa machine, it works just like they do. Just babystep and forget about it.

My proposition is that this is a friendlier user experience than Klipper’s default way of doing things. Klipper’s default is handicapped by the fact that saved variables is optional, so it cant be used.

I think in the time since I have released this tool the front ends have also gotten a lot more aggressive about pushing you to save the config. I’m not sure what to do about that.

Hello,
thanks for this set of macros I was looking for as I need to switch time to time between smooth and textured sheets on my Voron 2.4r2-300.

Before I jump in loading the code I wish to verify a few things… my English in not that fluent so I’m not confident enough to rush and crash my printer right after :face_with_raised_eyebrow:

Within the requirements, first one is cleared :grinning:
For the last two bullet points, I’m not sure to identify clearly when my z offset is done in my START macro (START_macro.cfg (5.4 KB))! My printer is quite standard (standard Z pin to zero the Z axis, no mod such as Klicky…) and I do not have any existing call to a CALIBRATE_Z macro already.

What I understand from your guidelines, is that I just need to add SET_GCODE_OFFSET Z=0.0 most probably just after the last G28 Z in my START macro.

Is this a correct understanding or did I missed something?

Thanks for sharing :slightly_smiling_face:

You can set it before G28. Doesn’t really matter. Just hast to be before APPLY_BUILD_SHEET_ADJUSTMENT.

If you had an offset before that wasn’t 0, you can start with that value as the build sheet offset.

ok clear enough so far, I’ll give a try in the coming days, thx

1 Like

back again… I can see quite a few differences between the above files in the original message and the ones on your github, including an additional macro named SHOW_BUILD_SHEETS

Which ones are the updated version please?

for sure the ones on github

Hello,

done!
So far I was able to setup my first sheet :smiley:
Thanks again for the work being done.

I was a little scary at the beginning as the offset value doesn’t seem to be updated in the Z-Offset TOOLHEAD Klipper window when you select a preloaded build sheet.
For example, my offset is 0.03mm in the save file and klipper shows 0.000 on the dashboard.
Is it a normal situation?

In terms of usage, what I understood so far to register a new sheet is that you should start with a zero offset value (in your macros en klipper), then use klipper to find the right Z offset, then copy this value into the INSTALL BUILD SHEET macro and it’s done!
Am I correct also?

Yes, the offset is only applied when you call APPLY_BUILD_SHEET_ADJUSTMENT. So you wont see it until after that happens.

If you have decided the offset of the sheet you can use SET_BUILD_SHEET_OFFSET SET_BUILD_SHEET_OFFSET= to set the offset.

After that, if you use the baby-stepping commands while printing, the changes will be saved imeidatly to the installed build sheet. So you can start with an approximate value that’s too high and then tune it in with baby-stepping during the printing of the first layer.

On setup for a new sheet, I just measure using a caliber the difference between the previous and new sheet and babysteep this at startup… works fine so far :wink:

1 Like

hum… just made two prints in a row.
During layer1 of the first print, I modified the offset from -0,235 to -0,15 (still adjusting, and I was really too low!)

After that, I launch a new print (printer not turned off in between, same filament).

I was expecting my offset to remain @-0,15, but it came back to -0,235 at the beginning of the second print.

Did I missed something in the above explanation?

How did you make the adjustment?

from the LCD screen directly on the printer, which is reflected back on klipper display

That should have worked. You should be able to use SHOW_BUILD_SHEETS to see the changes as that data is read from saved variables.

Not sure whats going wrong for you:

  • If SHOW_BUILD_SHEETS doesn’t show the updated value, then somethign went wrong with the baby stepping change?
  • If it does show the change then maybe you are overwriting the value somewhere else?

SHOW_BUILD_SHEETS gives me the same information, i.e. back to previous value!
Opening the save variable file also shows the previous value.

I have a 8 hour print currently on the way… I’ll see at the end what will be the behavior once again!