Klipper: Mechanical bed leveling with multiple Z steppers

Created on 5 Apr 2018  路  28Comments  路  Source: KevinOConnor/klipper

I would like to home my z axis as follows:

  1. Home XY
  2. Move Y to half point of bed and X inward to make sure the hotend will touch the bed.
  3. Home stepper_z using hot end as endstop (in my case tmc2130 sensorless homing)
  4. Move down Z-10 (or some max tolerated tilt distance) and X to other end of build plate.
  5. Home stepper_z1 using hot end as endstop (in my case tmc2130 sensorless homing) but keep track of how many steps/distance so we know the distance between stepper_z and stepper_z1
  6. Move stepper_z and stepper_z1 accordingly using some trigonometry taking into account where the pivot points on the lead screws are in relation to where the hot end touched the bed to level bed.

Of course the hot end would have to be clean

Sound possible?
Usefull or not a good idea?

Most helpful comment

@KevinOConnor Also the Voron 2 uses 4 independent Z steppers to level the gantry. It's a fixed bed printer that requires 7 steppers which currently only can run on Marlin and RRF due to the gantry leveling required. I know a lot of people have expressed interest in Klipper myself included. I would test this personally along with several other people that are currently running duel RAMPs on there Voron 2.

The Voron 2 went public beta at the beginning of January and there are already 21 printers built with many more currently in the build stage. So there is a demand for this and also plenty of testers. I would like to thank you for your efforts with Klipper and am eager to try out this addition once it's ready for testing. Here is how the Voron leveling works.

Voron 2 gantry leveling:

  1. Home X/Y
  2. Home Z in a safe spot with the inductive probe as the gantry will be sagging in the back 5-10mm
  3. Probe bed at four points with an inductive probe
  4. The controller uses least squares method to adjust each stepper
  5. Home Y
  6. Home Z in a safe spot with the inductive probe as gantry leveling has changed Z Height
  7. Probe bed at same four points and adjust gantry
  8. repeat steps 3-7 until planer deviation is less than a number say 0.005mm
  9. clean nozzle on a brush or wiper (optional)
  10. position nozzle over a mechanical switch
  11. activate the switch with multi tap/probe until a result deviation less than .005m is observed
  12. use offset from mechanical probe config to set Z min

I'll add a video as well to this in case I didn't explain it good enough.
Voron 2 Gantry Leveling

All 28 comments

I am actually doing a Railcore ZL build with dual RAMPS boards, and I'll be needing this feature! I'm happy to contribute to the project once I've got all my parts in.

The Railcore ZL has three stepper motors to adjust the bed plane, and the feature is added to RepRapFirmware.

@wizhippo This is currently how I home my axis on my DuetWiFi, so I can see why you want to do this as its a nice feature. (Except I use a probe for Z axis)

My only concern is using the Hotend and TMC2130 Sensorless homing. I don't think the Skipped Step detection will be able to do this on the Z axis. You need to detect a VERY fine force on the Print Head, while moving a Big Mass (Z axis). I don't think this is physically possible without getting false positive detections.

Because the force is too high when the motor starts skipping (especially for lead screws), the sensorless z-probe is usually not based on skip detection, but based on "back EMF" (see on Wikipedia https://en.wikipedia.org/wiki/Counter-electromotive_force).
Somehow the TMC2130 uses back EMF to measure the force (not sure how good this value is) and you can probe before loosing steps.

I still didn't try it myself, but I remember you have two possibilities:

  • use SPI to read the force value while probing
  • use SPI to program a threshold that can be assigned to a diag pin and use this as z-probe or end stop

The TMC might be reprogrammed after homing.

Not sure which one @cruwaller implemented.

I would like this to support 2+ steppers and endstops for users like @Papsnoek too. In my case I was planning on using "SPI to program a threshold that can be assigned to a diag pin and use this as z-probe or end stop" Just waiting for my new board and drivers to come in so I can play with the TMC2130 and see if they would be sensitive enough for this. If not I would add a sensor like the bltouch and still do the same.

Hello Kevin,

I have bed_tilt_calibrate command running correctly. Next step is, how move each z motor individually?

Thank you.

I've got my printer up and running and will look at the individual movement. My thinking is that we would have a setting in the bed_tilt section that, if set, automatically levels the bed plane given the locations of the leadscrews. This is how RRF handles it, currently, as far as I'm aware.

Any input on this? Should this leveling support only 3 points? 2 points? Arbitrary amounts greater than 1? A plane is overconstrained at 4 points, so I would suggest against using anything other than 2 or 3 points.

My idea at this moment is very simple. I have four stepper motors (one in each corner), so with nozzle just above each corner do a individual z_stepper move until we reach the nozzle.

What if you had started from, say, 200mm away from the bed? Your method would mean that the bed rips away from the mount, since it would only move one stepper.

I could see, perhaps, homing the bed normally (so moving to the center and probing), then doing what you've suggested, of course.

just as @wizhippo described in the first post.

btw.

Of course the hot end would have to be clean

it is probably sufficient if it's hot. Any blobs should be flattened out. But filament may drip on the bed at the probe points. Eventual the hot hotend could be cleaned on some surface before probing.
A hot hotend may also be a better for accurate probing, because it may expand a bit when hot.

EDIT: step 3 should say "home all z steppers at once.."

depending on the printer, homing could also start at the other end like it is for a delta.
E.g. my corexy could be homed via force detection at the bottom (because it is usually already there).
May be this could be scripted, because of all the possible variants.

A home command with parameters for the axis (allowing the name of stepper) and direction.
I think this would need some configuration for the xy position of each z axis.

Kevin, could you implement this feature? I can be a tester.

Regards,

On Thu, May 17, 2018 at 11:46:23AM -0700, pitucorto wrote:

Kevin, could you implement this feature? I can be a tester.

I was hoping to put together some test code, but I haven't had a
chance to look at it. I probably wont get time until next week.

-Kevin

@KevinOConnor Also the Voron 2 uses 4 independent Z steppers to level the gantry. It's a fixed bed printer that requires 7 steppers which currently only can run on Marlin and RRF due to the gantry leveling required. I know a lot of people have expressed interest in Klipper myself included. I would test this personally along with several other people that are currently running duel RAMPs on there Voron 2.

The Voron 2 went public beta at the beginning of January and there are already 21 printers built with many more currently in the build stage. So there is a demand for this and also plenty of testers. I would like to thank you for your efforts with Klipper and am eager to try out this addition once it's ready for testing. Here is how the Voron leveling works.

Voron 2 gantry leveling:

  1. Home X/Y
  2. Home Z in a safe spot with the inductive probe as the gantry will be sagging in the back 5-10mm
  3. Probe bed at four points with an inductive probe
  4. The controller uses least squares method to adjust each stepper
  5. Home Y
  6. Home Z in a safe spot with the inductive probe as gantry leveling has changed Z Height
  7. Probe bed at same four points and adjust gantry
  8. repeat steps 3-7 until planer deviation is less than a number say 0.005mm
  9. clean nozzle on a brush or wiper (optional)
  10. position nozzle over a mechanical switch
  11. activate the switch with multi tap/probe until a result deviation less than .005m is observed
  12. use offset from mechanical probe config to set Z min

I'll add a video as well to this in case I didn't explain it good enough.
Voron 2 Gantry Leveling

Adding on to what @Maglin mentioned, currently the only two options for Voron 2 are a Duet Wifi/Ethernet board or a dual ramps/ramps+expander setup. The only thing missing from Klipper that is needed for Voron 2 is the addition of leveling for 4 Z motors. There would definitely be alot of people in the Voron community, including me, who aren't currently using Duet who would be interested and willing to test out Klipper on a Ramps setup.

The Railcore is the same, at least the version I built, the ZL. 3 steppers for bed tram to the nozzle.

My thinking is that there would be a little addition to the Z stepper section of the config, as well as to the bed_tilt_calibrate section.

[stepper z]
...
location: -20,20

[stepper z2]
...
location: -20,180

[bed_tilt_calibration]
...
mechanical_leveling: true

Then the bed_tilt_calibration function itself would, instead of calculating a mesh adjustment as it seems to now, move the appropriate steppers to level the bed plane, thus the offsets. This shouldn't require too many runs to get within acceptable range, if you measure your offsets accurately. I guess we'd pick the center of the bed as Z0 and use that as our plane angle?

FYI, I've put together some demo code for this. It's on the work-ztilt-20180521 branch:

cd ~/klipper ; git fetch ; git checkout origin/work-ztilt-20180521 ; sudo service klipper restart

You'll need to add a [z_tilt] config section to your printer config. The parameters for the section are described in the updated config/example-extras.cfg file. After running with that config section it should enable a new Z_TILT_ADJUST extended G-Code command. However, I don't have the hardware to test this, and I don't expect it will actually work. (Definitely be ready to pull the power!)

Let me know if you make an attempt and what the results are.

Cheers,
-Kevin

On Mon, May 21, 2018 at 06:29:24AM -0700, Maglin wrote:

@KevinOConnor Also the Voron 2 uses 4 independent Z steppers to level the gantry. It's a fixed bed printer that requires 7 steppers which currently only can run on Marlin and RRF due to the gantry leveling required. I know a lot of people have expressed interest in Klipper myself included. I would test this personally along with several other people that are currently running duel RAMPs on there Voron 2.

The Voron 2 went public beta at the beginning of January and there are already 21 printers built with many more currently in the build stage. So there is a demand for this and also plenty of testers. I would like to thank you for your efforts with Klipper and am eager to try out this addition once it's ready for testing. Here is how the Voron leveling works.

Voron 2 gantry leveling:

  1. Home X/Y
  2. Home Z in a safe spot with the inductive probe as the gantry will be sagging in the back 5-10mm
  3. Probe bed at four points with an inductive probe
  4. The controller uses least squares method to adjust each stepper
  5. Home Y
  6. Home Z in a safe spot with the inductive probe as gantry leveling has changed Z Height
  7. Probe bed at same four points and adjust gantry
  8. repeat steps 3-7 until planer deviation is less than a number say 0.005mm
  9. clean nozzle on a brush or wiper (optional)
  10. position nozzle over a mechanical switch
  11. activate the switch with multi tap/probe until a result deviation less than .005m is observed
  12. use offset from mechanical probe config to set Z min

Interesting. It doesn't sound that difficult to script this up in
Klipper (it can be done entirely in the Python code). It may even be
possible to do this with the recently posted Z_TILT_ADJUST demo code
and some homing_override directives.

I'm curious about the Voron 2 homing procedure. The first four stages
are similar to what Z_TILT_ADJUST does. I'm guessing that you want to
run that analysis again after the first application, because the Y
axis may have been skewed on the first round, and thus the XY location
may have skewed the original Z tilt analysis. Could one just rerun
the same Z tilt code a second time though?

What's the purpose of the final 3 stages? Wouldn't the Z analysis
from the previous rounds be sufficient to know the Z offset? Or, is
the Z probe using some kind of special mechanism that isn't super
accurate when applied to the bed?

-Kevin

I'm curious about the Voron 2 homing procedure. The first four stages
are similar to what Z_TILT_ADJUST does. I'm guessing that you want to
run that analysis again after the first application, because the Y
axis may have been skewed on the first round, and thus the XY location
may have skewed the original Z tilt analysis. Could one just rerun
the same Z tilt code a second time though?

What's the purpose of the final 3 stages? Wouldn't the Z analysis
from the previous rounds be sufficient to know the Z offset? Or, is
the Z probe using some kind of special mechanism that isn't super
accurate when applied to the bed?

The Voron 2 is an enclosed printer intended to print ABS and other materials that require an enclosure and heated chamber. Inductive probes sensing distance changes as the probe temperature changes. that is the reason for the mechanical switch probing to attain the final Z min which is pretty accurate.

The reason for probing the bed multiple times is it never gets it right on the first try. The fast probe or 1st iteration is to get the gantry pretty square to the bed. The home Y and Z just so the probe offset is correct as well as the bed locations in Y. The third and final leveling sequence is just so I know it's good. I'm running RRF on a Duet and I usually see .003m of deviation which is next to nothing.

Also, I never disable my steppers so I only level my gantry and set Z min once. I've had my printer on for a week with maybe 12-15 print jobs all of the same leveling routines from day one. I don't have missed steps so I don't have to worry about my Z being off.

Thank you @KevinOConnor for doing this so quickly. I don't have a RAMPs on my V2 just yet but I'll pull a few out and give it a try here in a week or two. I honestly didn't think you would have this ready to test so fast. I'm pretty excited to try it.

I also have a VORON2 with RAMPS.
Gonna try that demo code.

FYI, based on testing feedback from @chainsol, I've gone ahead and committed this change to the main repo (commit 3025638b).

-Kevin

I currently have @KevinOConnor's Z leveling working correctly - Here's the config I'm using.

My printer has three leadscrews, so someone with 4 and someone with 2 should test this.

So It took me far longer than expected to replace my Duet+DuetX5 with 2x RAMPs. But I've also now got the Z_Tilt working on the Voron 2. Still doing testing to refine processes. I do get this error while running the Z_Tilt.

Send: Z_TILT_ADJUST
[...]
Communication timeout while idle, trying to trigger response from printer. Configure long running commands or increase communication timeout if that happens regularly on specific commands or long moves.
[...]
Recv: // Making the following Z tilt adjustments:
Recv: // z = -0.003255
Recv: // z1 = -0.010545
Recv: // z2 = 0.013186
Recv: // z3 = 0.020475
Recv: // z_offset = 0.030013
Recv: ok

Also, It is going to be necessary to make some scripts to run the Z_Tilt because I don't think it's necessary to run it with every G28 in the homing_override section. I think I've read most all the documentation I can find but don't recall seeing how to use scripts and then call them in OctoPrint. Thank you for getting this in. I think after I post all my results we'll start seeing a trickle of people in the Voron community start to use Klipper.

On Thu, May 24, 2018 at 10:03:51AM -0700, Maglin wrote:

So It took me far longer than expected to replace my Duet+DuetX5 with 2x RAMPs. But I've also now got the Z_Tilt working on the Voron 2. Still doing testing to refine processes. I do get this error while running the Z_Tilt.

Send: Z_TILT_ADJUST
[...]
Communication timeout while idle, trying to trigger response from printer. Configure long running commands or increase communication timeout if that happens regularly on specific commands or long moves.
[...]
Recv: // Making the following Z tilt adjustments:
Recv: // z = -0.003255
Recv: // z1 = -0.010545
Recv: // z2 = 0.013186
Recv: // z3 = 0.020475
Recv: // z_offset = 0.030013
Recv: ok

Okay, thanks. That's a warning from OctoPrint - I don't think it will
adversely impact anything. I'll see if there is something the code
can do to let OctoPrint know that Klipper is busy.

Would you able to attach the log after Klipper runs through your
calibration process? I'd like to confirm everything looks okay in the
log. The details for gathering the log are at:
https://github.com/KevinOConnor/klipper/blob/master/docs/Contact.md

Also, It is going to be necessary to make some scripts to run the Z_Tilt because I don't think it's necessary to run it with every G28 in the homing_override section. I think I've read most all the documentation I can find but don't recall seeing how to use scripts and then call them in OctoPrint. Thank you for getting this in. I think after I post all my results we'll start seeing a trickle of people in the Voron community start to use Klipper.

Currently, the only way to add a "script" is to write it in Python.
Alternatively, there are some OctoPrint plugins that will do this.

If you're okay with writing it in Python, the
klippy/extras/homing_override.py file can be used as a starting
example. There's also some documentation at:
https://github.com/KevinOConnor/klipper/blob/master/docs/Code_Overview.md#adding-a-host-module

-Kevin

I know enough about python to kind of follow and troubleshoot, but not write code. I checked out the script you wrote for the multi Z leveling and I actually got lost. I'll learn though.

Also, I put a dial indicator on my X carriage and after 3 gantry levelings, the gantry was perfectly level. It's better than the duet has ever done. I actually thought my MIC6 bed wasn't perfectly flat. I used all the same settings as in my max and min axis settings as well as my belt locations and probing points. I'll get you that debug output. I'm still doing some testing but I'm very happy so far.

here is a video showing how level it is. https://youtu.be/_ETgxVOVQ3A

On Thu, May 24, 2018 at 03:12:10PM -0700, Maglin wrote:

I know enough about python to kind of follow and troubleshoot, but not write code. I checked out the script you wrote for the multi Z leveling and I actually got lost. I'll learn though.

Ah, yeah, the z_tilt.py code isn't a good starting point for learning
the Klipper code. The system is organized to step the Z steppers
synchronously, so the z_tilt code has to perform some contortions to
independently command each z stepper. For reference, the __init__(),
printer_state(), and handle_connect() methods are initialization; the
cmd_Z_TILT_ADJUST(), get_position(), and finalize() methods perform
the probe and bed tilt least squares analysis; the adjust_steppers()
performs the actual Z stepper motor movement to level the bed.

Also, I put a dial indicator on my X carriage and after 3 gantry levelings, the gantry was perfectly level. It's better than the duet has ever done. I actually thought my MIC6 bed wasn't perfectly flat. I used all the same settings as in my max and min axis settings as well as my belt locations and probing points. I'll get you that debug output. I'm still doing some testing but I'm very happy so far.

Great!

Thanks for posting the video.

-Kevin

Here is that debug output. Hope this has what you are looking for.
Klippy Log Z Tilt

I've been thinking about why I have to run multiple Z_TILT_ADJUST to get the gantry square to the bed and I think I've figured out where the error is coming from. We need to define the position of the probe not from the nozzle but from the center of the X axis. As that would change the height of the probe based on how out the gantry is.

Anyways just wanted to add this. I think it will make the leveling process that much more accurate.

edit: I removed some test code that I now know why that didn't work.

On Sun, May 27, 2018 at 06:26:35AM -0700, Maglin wrote:

I've been thinking about why I have to run multiple Z_TILT_ADJUST to get the gantry square to the bed and I think I've figured out where the error is coming from. We need to define the position of the probe not from the nozzle but from the center of the X axis. As that would change the height of the probe based on how out the gantry is.

I've given this some thought and I don't think the probe's XY offset
impacts the stepper tilt adjustment.

Specifically, the probing code effectively finds the angle between the
gantry and the bed. That angle is calculated using the distance
travelled between probing points and the distance between the probe
and the bed when the probe triggers. The angle is the same
independent of whether the bed is ultimately being moved or the gantry
is ultimately being moved. After the angle is found, the adjustment
code effectively alters the positions of the steppers relative to
themselves. Thus, the adjustment is dependent on the angle and the
configured distance between each stepper XY position. So, I don't
think the probe's XY offset impacts these calculations.

One area that the probe's XY offset could impact is the final z offset
between bed and nozzle. Since you're doing a Z height probe
immediately after Z_TILT_ADJUST, this wouldn't have an impact for you.

I think it's possible the reason multiple Z_TILT_ADJUST rounds are
improving accuracy is that your gantry isn't fully square on initial
rounds. That is, on initial probe rounds, if the head is commanded to
move X+30, it may be moving something like X+29.9 Y+.1 instead, which
would slightly skew the bed/gantry angle calculation. Just a guess.

-Kevin

Was this page helpful?
0 / 5 - 0 ratings

Related issues

leungtech picture leungtech  路  4Comments

CHILLYSMOKES picture CHILLYSMOKES  路  5Comments

Hywelmartin picture Hywelmartin  路  6Comments

Michael-Bell picture Michael-Bell  路  5Comments

LazaroFilm picture LazaroFilm  路  6Comments