Automated measurement of Z axis perpendicularity

I came up with a fairly simple but very accurate way of measuring how perpendicular your Z axis is.

You can find some more details and code at my Github project for this: pvdbrand/cnc-z-perpendicularity. The code is not that polished, so it may be hard to get everything working if you’ve never done anything in Python.

The basic idea is that you string a very thin piece of wire along the X and/or Y axis. Using a Z probe, the end mill touches off on both sides of the wire at various depths. You repeat the process with the end mill rotated 180 degrees, to compensate for a possible non-zero angle between the Z axis and the end mill itself (for example if your end mill is bent).

probe-in-action

Those measurements can be used to compute what the angle of the Z axis is, and what the angle between the Z axis and the end mill is. If you know the Z axis angle, you can calculate exactly how much to shim the mount in which place. No more trial and error, no need to make test cuts! (This is left as an exercise for the reader for now.)

The most important caveat is that your “end mill” should have the same diameter along the part that is used to probe the wire. A spiral flute will not work well for example. I used a small aluminum tube instead. If you have a very short cutting edge you may be able to insert it upside down.

I have never shimmed my tool mount, and my Z axis was only 0.2 degrees or so off perpendicular. Not bad! To test the approach further, I printed a special mount for my aluminum “end mill tube” at 5 degrees off in one axis and 10 degrees off in another axis. I also printed a small piece to simulate an angle of 2.5 degrees between the Z axis itself and the end mill. I ran the script, and all angles were measured correctly :slight_smile:

I also implemented measurements of backlash in the same script. The idea is that the probe moves towards the wire and stops on contact. Then the probe is moved away until contact is broken again. The distance moved until contact is broken is the backlash. I measured the backlash several times when I was testing various things, and I typically got a histogram that looked like this:

backlash

The X axis is the backlash in millimeters, the Y axis is how often I measured that specific backlash. Very good numbers I think!

6 Likes

Can you compensate a skewed z-axis in the software/firmware, like Prusa printers?

Even if you can, you’d still get small ridges when the depth of cut is less than the thickness of your stock. You’d also get ridges when you are trying to smooth a horizontal surface. For these reasons, it’s best to shim the router mount by putting thin washers or tape in the right places.

Making the Z axis perpendicular is called tramming. As far as I’ve read here in the forums, tramming is a trial and error process where you surface a small piece of material, check for ridges, and try to shim it in the right place, rinse and repeat until you’re happy enough with the result.

A quick google brought up this youtube video. I’ve only watched the first two minutes, but it shows the problem nicely. He uses a dual dial indicator, seems a lot more expensive than my approach. That gauge needs to be built pretty accurately for both dial indicators to be “in sync”.

1 Like

Nicr. Just for reference, here is the mechanical solution for this (for the dw660):

1 Like

I like this method but I think it would be helpful to be a bit more precise in the terminology.

I don’t have time to dive into it in detail now but I think you are directly measuring whether the axis of the tool is parallel to the direction of Z movement, and then by turning the spindle and taking the midpoint you are determining whether the axis of rotation is parallel to the direction of Z movement.

I don’t think you are measuring whether Z movement is perpendicular to X/Y movement. I think an additional measurement of whether the axis of rotation is perpendicular to the X/Y plane will tell you everything you’re wanting, including whether the tool and direction of Z movement are perpendicular to X/Y.

Also you don’t need a perfectly flat surface to use Ryan’s perpendicularity tester (a bit of a chicken-and-egg problem). You can mill a shallow circle of the proper diameter and that can serve as your reference X/Y plane for squaring everything else.

2 Likes

I was aware of it, and I used it some time ago. It confirmed that my Z was not too far off perpendicular. You still kind of have to eye ball it though, and as Jamie said elsewhere, it only helps with some issues (surfacing spoilboard for example).

As a low tech “good enough” solution it is more than adequate though.

You’re right, I did not think about the difference between the axis of Z movement and the axis of rotation of the spindle!

This is the (mental) image I had when I was thinking about this:

svg

I only thought about two axes, but in fact there are three axes:

  1. Axis of Z movement (“Z axis”): when the Z stepper moves the Z axis up and down, this is the axis long which the spindle and end mill will move.
  2. Axis of rotation of the spindle (“spindle axis”). This axis is definitely offset from the axis of Z movement, but that doesn’t matter I think.
  3. Axis of the end mill (“end mill axis”). This axis might be offset from the axis of rotation of the spindle.

If you think of the red dashed line as the Z axis, and you assume it to be plumb, then my method works as advertised and will help you make everything perpendicular by shimming the router mount.

If the end mill axis is offset from the spindle axis and the tip of the end mill is closer to the spindle axis, then my method will measure a negative angle between the end mill axis and the spindle axis, so you’ll still see something is off. In essence, it measures the angle of the sides of the cone defined by rotating the end mill. It’s even possible to measure an hour glass shape (though you can’t summarize it in a single angle).

If the Z axis is not plumb, then using my method you will still end up with an end mill that is perfectly perpendicular to the XY plane (as defined by the frame tubes of the MPCNC I think). However, in this case, a movement in the Z axis also leads to (small) movement in the XY direction, so you’re still not getting a perfect vertical edge if you make multiple passes with a small depth of cut, and tolerances are affected if you cut at different depths in general.

I’ll have to think about how to measure the axis of Z movement and separate it from the other axes. I think the axis of Z movement can be compensated in firmware, it’s kind of like skew correction.

Thanks for pointing out (one of) the holes in my thinking! Let me know if you spot another mistake or invalid assumption in this post :slight_smile:

1 Like

It occurred to me you could combine Ryan’s tramming tool with a touch plate to get a more precise and repeatable measurement of axis tilt, and no flat surface is needed, not even a circle. Leave the touch plate fixed and move the tool in a circle around it.

Simplest is to sweep the arm manually to stay over the touch plate, but you could sweep it around a peg or something to move the arm. By measuring z height a bunch of times and interpolating you could probably get a very accurate measure of spindle axis tilt relative to XY motion, more accurate than a pure mechanical measurement.

1 Like

This is a cool idea. Quite the setup and work went into it. I have done the mechanical tramming routine and done a dial indicator along a long machined ruler and have pretty good perpendicularity. I think my Z travel is pretty perpendicular.

My only issue is that the whole travel rises in Y because I can’t get the corner height correct. My tubes keep slipping and then when I try to cut them all the correct length, it still is off. Less than a mm over 32" of travel, but still noticeable. I could resurface the spoil board but before I do that I want it to be as level/flat perpendicular to the tool over the whole bed as I can.

You have given me motivation to address this again.

Great idea!

But wouldn’t you be measuring the end mill axis relative to the XY movement? I agree that even if that’s the case then all angles can be determined though. I need to think it through a bit more.

This approach won’t help with that… And, it seems my work is not quite done yet, so maybe it’s better to hold off on trying to use the script right now :slight_smile:

1 Like

Ryan’s tramming tool clips onto the nut, not the endmill, so it turns with the spindle and measures the axis of rotation, not the shank of the tool or crookedness of the collet. As long as the spindle is one rigid assembly it doesnt matter where you attach, you always sweep a plane perpendicular to the axis of rotation.

If you inserted a smooth rod into the collet and had an arm that slipped around the rod like a plain bearing and you ensured the spindle didn’t turn, then you would be measuring the axis of the endmill/collet.

2 Likes

Cool idea, Jamie.

A standalone touchoff plate with an LED indicator is on my project list. Combine that with Ryan’s tramming tool and I’m sure it would be more effective than the sheet of paper I used last time.

Got it. I was indeed thinking about the “rod with an arm” inserted into the collet, instead of an arm attached to the spindle. Thanks!

I skimmed through the video (insofar as skimming through a video is possible, I might have missed something). It’s overly complicated to use a standalone touch off plate with an LED.

You can wire your touch probe (the two wires with alligator clips) to an end stop on your main board, and configure Marlin to use it. Enable G38 in the firmware, search for it in Configuration_adv.h. Then use G38.2 to move until the probe is triggered. No need for manual jogging or a separate battery/LED. If you leave your touch plate in the same place, you can also move to its X and Y coordinates, and use G28 Z (home Z) to touch off on it again after a tool change or something.

I could only get Marlin to work properly for both G28 (homing) and G38 (probing) when I configured the probe to use the z_min endstop. My github account has my Marlin config in case you want to check your config against mine. It’s pretty confusing how Marlin handles z_probe vs z_min etc.

On level of complication I’d put it somewhere in between a simple sheet of paper or re-configuring my setup :wink:

1 Like

I like it!

I tried working through the math to emulate the tramming tool idea on paper, but it was getting very complicated very fast. So I did what any software engineer would do: I let the computer do the hard work for me. I built a simulator that you can configure for any angle of the Z axis, spindle, and end mill. You can then send it gcode to move around and use the Z probe. It has a GUI so you can see whether the end mill or probe is actually moving the way you expect.

The calibration now uses a 3D printed arm attached to the collet nut. The arm holds a needle, which is used as one part of the probe. Instead of two wires, I now use just a single feeler gauge mounted to the spoilboard as the other part of the probe.

The needle is used to find a single location on top of the feeler gauge (on the center line, 5mm from the tip). The spindle is then rotated 45 degrees by keeping the needle against the side of the feeler gauge and moving the router in a circle around it. Each time, the exact same spot on the feeler gauge is found. The positions of the router form a circle around that spot on the feeler gauge and the plane through that circle is used to compute the spindle angles. Care is taken to correct for non-zero angles of the needle itself.

You can see the simulator in action here.

I can put in different values for the Z axis, spindle, and needle angles (angle of rotation around X and around Y axis). The script that does the probing can correctly measure all those values! (Although there is a small measurement error when things are far off of perpendicular, if you iterate a few times those measurement errors will disappear when you get closer to perpendicular.)

Knowing the needle angle is not very useful, but the same approach can be used to measure end mill angle and runout, as I did above.

Also, I think this same approach can be used to measure skew. The router makes a circle around the feeler gauge. But if you have non-zero skew, that circle will be an ellipse. By fitting an ellipse, it should be possible to compute the skew. By computing the skew in each of the four corners of the workspace, you may even be able to check whether the belts have equal tension (by checking whether the skew is the same for all corners).

I have not tried it on my MPCNC yet (still waiting for the feeler gauges to arrive), but it should be easy to iron out any potential issues. I’m pretty confident that the hard part is solved now.

2 Likes

WHOA, that is some precision stuff right there. I guess I need to make an adjustable mount now.

2 Likes

Wow this is really interesting. I need to think on this some more. I understand the spindle axis relative to x/y. And sweeping upwards you get the z tilt plus needle tilt in one orientation, and by measuring z tilt plus opposite needle tilt in the opposite orientation you can separate z tilt from needle tilt.

I also see you’re sweeping both sides of the feeler gauge, so in principle you could get needle taper and needle tilt and z tilt in different combinations and separate them back out with math. Although that seems a bit much so I am guessing you are aiming for lower noise by getting multiple points and averaging, and ensuring to start with that your needle is not tapered.

For a short needle your x/y resolution might be limited by steps per mm but if you have a long needle, say half your Z travel, you should be able to get a really precise measurement.

1 Like