Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

X-Axis twist compensation. Software fix using a mesh for z-probe-offset #23167

Closed

Conversation

Giuseppe499
Copy link
Contributor

Description

I added a feature called PROBE_OFFSET_MESH that adds a calibration procedure to create a mesh for the z-probe-offset in the menu "Configuration->Advanced Settings->Probe Offsets". I added this feature to compensate in the firmware for a twisted X-axis as short discussed in this issue #22791. This should also fix this issues #11234, #12349, #15206, #15753, #18591.

Requirements

This PR requires an automatic bed levelling probe and an LCD to show menus. To test if it works you should also have a twisted X-axis on a 3d printer of your choice (I can suggest you a Tronxy X8 ;) )

Benefits

I added this feature to compensate in the firmware for a twisted X-axis as short discussed in this issue #22791. This should also fix this issues #11234, #12349, #15206, #15753, #18591.

Configurations

Just enable PROBE_OFFSET_MESH in Configuration_adv.h and AUTO_BED_LEVELING_BILINEAR in Configuration.h. As stated before you should also have an LCD enabled to show the menus and an automatic bed levelling probe.

Related Issues

#22791, #11234, #12349, #15206, #15753, #18591.

@Giuseppe499 Giuseppe499 changed the title X-Axis twist compensation softwar fix using a mesh for z-probe-offset X-Axis twist compensation software fix using a mesh for z-probe-offset Nov 21, 2021
@Giuseppe499 Giuseppe499 changed the title X-Axis twist compensation software fix using a mesh for z-probe-offset X-Axis twist compensation. Software fix using a mesh for z-probe-offset Nov 22, 2021
@Roxy-3D
Copy link
Member

Roxy-3D commented Nov 22, 2021

If a person probes the entire bed to create a mesh... How is the probe offset mesh created? If the X carriage is twisted, how is the difference between the probe's Z offset and nozzle determined at each position?

@Giuseppe499
Copy link
Contributor Author

Giuseppe499 commented Nov 22, 2021

If the X carriage is twisted, how is the difference between the probe's Z offset and nozzle determined at each position?

It is determined in the same way that you do with the Z probe wizard: with manual calibration. If you are not familiar with the Z probe wizard, it is a calibration feature that can be enabled with PROBE_OFFSET_WIZARD and you can see it at work in this video.

As I said in issue #2279, this is similar to MESH_BED_LEVELING but you have to do it only once. After this first calibration, you can just use auto bed leveling. This approach should yield results equal or better than MESH_BED_LEVELING but with only one manual calibration. I said that it can yield better results than MESH_BED_LEVELING because you can use a small grid for the z offset mesh (like 3x3) and instead use a bigger mesh for ABL (like 5x5).

@thinkyhead
Copy link
Member

It would be more optimal to apply such twist compensation to the G29 Z mesh values during –or at the end of– G29 instead of applying another set of bilinear mesh calculations throughout the printing process. Since twist compensation would be a necessary preliminary element for any meaningful G29 probing on a twisted printer, it might as well be added as an optional first part of G29 instead of making it separate.

@Giuseppe499
Copy link
Contributor Author

Giuseppe499 commented Nov 24, 2021

It would be more optimal to apply such twist compensation to the G29 Z mesh values during –or at the end of– G29 instead of applying another set of bilinear mesh calculations throughout the printing process.

Yes, it would be more optimal but this would mean that the z offset mesh should be the same size as the ABL mesh. I think this is not a good idea because we can have a good twist compensation with a small grid for the z offset mesh (like 3x3) and then we can use a bigger grid for ABL (like 5*5). If we want to have the same results with your method, we would have to do the manual calibration on 5x5 = 25 points instead then doing it on only 3x3 = 9 points. I don't know about you, but I wouldn't want to do a calibration on 25 points instead of 9 to get the same results.

Other than that, if it runs easily on my sanguinololu 1.2 based board I don't think it is too much of a computational cost.

Since twist compensation would be a necessary preliminary element for any meaningful G29 probing on a twisted printer, it might as well be added as an optional first part of G29 instead of making it separate.

This calibration shouldn't be run before any G29 probing. If you do that you are better off enabling MESH_BED_LEVELING and throwing your probe out of the window because it will give you the same results with fewer steps. This calibration should only be run once in a while, after that, the data will be stored and will be used for every G29 probing.

@Roxy-3D
Copy link
Member

Roxy-3D commented Nov 24, 2021

It would be more optimal to apply such twist compensation to the G29 Z mesh values during –or at the end of– G29 instead of applying another set of bilinear mesh calculations throughout the printing process. Since twist compensation would be a necessary preliminary element for any meaningful G29 probing on a twisted printer, it might as well be added as an optional first part of G29 instead of making it separate.

I agree. But I have additional reservations. I think we will need the capability of calculating the offset of both the nozzle and probe due to twist to address higher resolution bed leveling mesh's. A calculation based approach is going to give us more flexibility than forcing the user to generate 'yet another mesh' for the purpose of dealing with X Axis twist.

Correcting mechanical X-Axis twist in firmware is kind of a hack. I am concerned that if the solution isn't robust and handles the general case we will just generate more support issues.

Personally, I feel more comfortable having a few values in Configuration_Adv.h that allow the user to specify the twist at the Min side of the X Axis, the twist at the Max side of the X axis and the offset of the nozzle and Z probe from the real X Axis. With those values (correctly defined) we could adjust any generated mesh. And I suspect we could modify G26 to help the user find and fine tune those values. That would make for a more robust solution for the user.

@Giuseppe499
Copy link
Contributor Author

Giuseppe499 commented Nov 24, 2021

I made a pdf file with some images and some notation so we can easily communicate about this issue.
X axis twist compensation.pdf

I agree. But I have additional reservations. I think we will need the capability of calculating the offset of both the nozzle and probe due to twist to address higher resolution bed leveling mesh's. A calculation based approach is going to give us more flexibility than forcing the user to generate 'yet another mesh' for the purpose of dealing with X Axis twist.

Whit which method could a user easily compute the nozzle-pivot offset (l1 in the pdf) and the probe-pivot offset (l2 in the pdf)? Even assuming that the pivot YZ coordinates are fixed in relation to the X coordinate (as I drew in the pdf above), how do you precisely locate the rotation pivot on this printer?
photo_2021-11-24_13-13-15

I think that a calculation-based method is not feasible. There are too many variables that are not easily measurable by the user. Other than that we have no idea how the α(x) function is made and so we should still find some points of that function to approximate it with interpolation (first graph in the pdf). How can we retrieve such points? I have no idea. What I know is that we can easily retrieve points for the z-offset(x) function and we can interpolate that. This is far easier and the user doesn't need to take measures for l1, l2 and β.

If you don't want the user to generate 'yet another mesh' for the purpose of dealing with X-Axis twist, I understand that and I propose a solution that will not require 'yet another mesh'. Instead of creating a mesh ( so z-offset(x,y) ) we can just create a function ( z-offset(x) ) interpolating between points retrieved only on a line. This will make the calibration procedure shorter, should be less computational expensive (even if I don't think that this was a problem), we will need to store fewer points and if the only mechanical problem is a twisted X-axis this should yield the same results of a mesh-based approach.

Correcting mechanical X-Axis twist in firmware is kind of a hack. I am concerned that if the solution isn't robust and handles the general case we will just generate more support issues.

I think that a mesh-based approach is as robust and general as you can get.

Personally, I feel more comfortable having a few values in Configuration_Adv.h that allow the user to specify the twist at the Min side of the X Axis, the twist at the Max side of the X axis and the offset of the nozzle and Z probe from the real X Axis.

As I said above, good luck measuring those with enough precision.

With those values (correctly defined) we could adjust any generated mesh. And I suspect we could modify G26 to help the user find and fine-tune those values. That would make for a more robust solution for the user.

As a user, I don't want to use G26 to do trial and error to fine-tune 5 or even more values that don't easily correlate to the G26 results. I would prefer a lot more to just do a simple calibration to fine-tune only 1 value that will get me better results than a trial and error approach in less time.

@Roxy-3D
Copy link
Member

Roxy-3D commented Nov 24, 2021

That drawing is helpful. But the initial good thing about the drawing is it confirms you understand what I'm suggesting.
Thank You for taking the time to do the drawing!

(With) which method could a user easily compute the nozzle-pivot offset (l1 in the pdf) and the probe-pivot offset (l2 in the pdf)? Even assuming that the pivot YZ coordinates are fixed in relation to the X coordinate (as I drew in the pdf above), how do you precisely locate the rotation pivot on this printer?

I don't know the best method right now. But we do have some factors working in our favor. For the sake of this discussion, how about we assume the user can just look and see how far the nozzle tip is from the center of the two X rails when the nozzle is at the center of the bed? We don't have a super precise way to measure the Z-Probe X & Y offset either. People just put a ruler under their nozzle and get a pretty good estimate. And in that measurement, we have a similar factor working in our favor. The bed is close to flat (albeit not perfect). And the bed is assumed to be level (albeit not perfect).

That helps with any measurement error because the limit of sin(x)/x as x approaches 0 is equal to 1. We have the same identity working for us on the X twist calculation. And I suspect we can add some features to G26 to help the user get initial values that are very close and maybe iteratively get them almost exact.

If a user had the correct numbers, then what ever mesh dimensions they use (or change to) get the 'correct' offsets applied to the freshly generated mesh. It is possible that just normal mesh editing is sufficient at that point to give the user a very accurate mesh.

@Giuseppe499
Copy link
Contributor Author

We don't have a super precise way to measure the Z-Probe X & Y offset either. People just put a ruler under their nozzle and get a pretty good estimate.

I think that this is not a good example. The Z-probe X e Y offsets are only two values and you can iteratively and precisely set them because they easily correlate to something that is visible by the user. You can measure them with a ruler, use a pencil to mark the nozzle position on the bed, make the printer probe at the same point, and now you can correct the initial guess.

There isn't a similar procedure to compute a bunch of values of α(x) to approximate that with interpolation. Even if we had such a procedure, it doesn't matter. The only thing that matters to compensate for the X-axis twist is the function z-offset(x). So, why should we bother to approximate a function that we don't need? Why should we bother to measure some values that are not needed?

That helps with any measurement error because the limit of sin(x)/x as x approaches 0 is equal to 1. We have the same identity working for us on the X twist calculation.

I don't understand exactly where this identity comes in handy for the X twist calculation.

And I suspect we can add some features to G26 to help the user get initial values that are very close and maybe iteratively get them almost exact.

As I said before I don't think that we can create an easy procedure for the user to compute a bunch of values for α(x). And as I said before those values are not needed. The only thing that is needed is a bunch of values to approximate z-offset(x). I can make an easy procedure for the user to compute those values and I think this is the best way to solve this issue. Is easy for the user, is easy to implement and it gives perfect first layers.

If a user had the correct numbers, then what ever mesh dimensions they use (or change to) get the 'correct' offsets applied to the freshly generated mesh.

This is also true for the method that I propose. If we approximate z-offset(x) then whatever mesh dimensions the user uses (or changes to) the 'correct' offsets will be applied to the freshly generated mesh. I would do this as @thinkyhead suggested.

Now that I have explained myself, I would love to implement the procedure that I suggested as stated here:

I propose a solution that will not require 'yet another mesh'. Instead of creating a mesh ( so z-offset(x,y) ) we can just create a function ( z-offset(x) ) interpolating between points retrieved only on a line. This will make the calibration procedure shorter, should be less computational expensive (even if I don't think that this was a problem), we will need to store fewer points and if the only mechanical problem is a twisted X-axis this should yield the same results of a mesh-based approach.

I would love to add this feature to Marlin and I think that this will be helpful to other users like me. I'm sorry, however, to tell you that I'm not willing to work on a procedure to compute values for α(x). I don't want to work on that because I think that is not feasible, is not necessary to solve this issue, and is unnecessarily difficult for the user.

Let me know if you are interested in this feature and if you are I will update this pull request as soon as I can. As I stated before, I think this would be a good addition to Marlin and it will be helpful to a lot of users.

@Roxy-3D
Copy link
Member

Roxy-3D commented Nov 27, 2021

Let me know if you are interested in this feature and if you are I will update this pull request as soon as I can. As I stated before, I think this would be a good addition to Marlin and it will be helpful to a lot of users.

The ability to compensate for an X Axis twist would be valuable for many users. From this discussion, there are several concerns. First, lets not have a second mesh that holds compensation numbers for the twist. Lets factor that directly into the main bed leveling mesh.

Secondly, lets make sure it is very straight forward, easy and quick for the user to get the twist compensation numbers into the system so they can be factored into the main bed leveling mesh. (This seems to be the main point of contention. I would lean towards an algorithmic method but if the user can just lower the nozzle to the bed and signal the firmware it is at bed level at various places across the X Axis that would work too.)

It is probably best to close this Pull Request and preserve it as it currently sits. I look forward to seeing the Pull Request for the next version of X Axis Twist Compensation. A lot of people will benefit from that.

@Roxy-3D Roxy-3D closed this Nov 27, 2021
@lrpirlet
Copy link
Contributor

Hi @Roxy-3D
Just a tought I had, but could not implement (lack of knowledge in C++)... We already have all the information needed in an established mesh...
We want the plane described by the tip of the hot end parallel to the plane described by 3 points taken on the bed... what if we decide that XminYmin, XmaxYmin and X((max-min)/2)Ymax are at the same distance from the tip (yes, this is your first autobed)... we could then correct all the points probed by the mesh... (in fact, in the end, the mesh would end-up as if it was established with a probe placed just under the hot end)

@Roxy-3D
Copy link
Member

Roxy-3D commented Nov 28, 2021

The big problem is that you don't know how the X Axis is twisted. It could be at the Xmin side this is no twist. But at the Xmax side the lower rail is a few mm. too far forward. In that case I don't think your condition holds.

One thing that may simplify this problem a lot is the twist of the X Axis should be identical no matter where you are on the Y Axis. If you pick a random location on the Y Axis and traverse it from Xmin to Xmax you should see an identical twist.

@lrpirlet
Copy link
Contributor

lrpirlet commented Nov 28, 2021

Well, it does NOT really matter to know how it is twisted... What matters is to simulate a probe located just under the tip of the hot end...

As I understand it (I may be wrong), the twist makes the line drawn between the tip of the hotend and the tip of the probe to be at an angle relative to the surface of the bed... (in both X and Y direction)... In other words a gap is forming while moving along the X and/or the Y axis.

The so said original "Auto_Bed_Leveling" would take care of that... The probe and the hot-end tip would then, after correction, move in a plane parallel to the bed plane.

Now, if we could apply the mesh bed leveling on top of this Auto_Bed_Leveled plane, we would take into account the lack of flatness of the bed (relative to the physical X Y plane).

In fact, I GUESS we could use G29 J to tilt the mesh after G29 P1 whenever a gap is forming when circulating along the X and Y axis.

PLEASE UNDERSTAND THAT I HAVE NOT TRIED THAT as I have no twisted X axis and even so, I have ZERO EXTRUDER-OFFSET in both X and Y direction as the hot-end tip press a switch inserted between the bed and the hot-end tip (by a servo).

@Roxy-3D
Copy link
Member

Roxy-3D commented Nov 29, 2021

Well, it does NOT really matter to know how it is twisted... What matters is to simulate a probe located just under the tip of the hot end...

Users have been fighting the twist problem for several years. And it is very confusing to debug (if you don't understand that there is a twist). The bottom line is the Z Probe Offset from the nozzle changes depending upon where the nozzle is on the X Axis. So all the established tools and procedures to help the user get the printer setup produce seemingly random problems. Or stated in different words, imagine if the Z Probe Offset is some value with a random value applied to it depending upon where on the X Axis the nozzle is.

I don't think a G29 J can be used to cure this (in the general case). The reason is very often the twist produces a saddle shape mesh. The reason is because at both the XMin and Xmax sides of the X Axis the twist is the most extreme in many cases and that lifts the Z Probe more than at the center of the bed. Albeit... If one side of the X Axis has no twist, I think I can envision how G29 J could tilt the mesh in an appropriate fashion. (Although... just from the geometry of how the twist generates the Z Probe Lift it is very likely the amount of lift isn't linear with respect to the X Axis.)

@lrpirlet
Copy link
Contributor

Hi @Roxy-3D

Thank you for these explanations. If the effects are as you describe them, indeed G29 j will not be able to correct the problem... As I understand it, when the probe is offset by a few centimeters, the deformations of the axis, at a given position over the bed, are far different under the probe and under the hot-end. Not only do we see a static twist due non parallel rods but also dynamic twist due to the elasticity of the axis supports...

So, to solve any hardware induced error, I strongly believe that the mesh should be produced using a probe with ZERO offset or as near as possible to zero offset for each and every axis...

epatel99 did use a switch fixed on the tip of the hot-end to produce a semi-automatic mesh see #2830 where he shares http://www.thingiverse.com/thing:1120142 (even if I think that the Z offset is too important)

I use a switch (surface mounted switch, Z offset is less than 5mm) that is inserted beween the tip and the bed with a servo as part of G28 and/or G29...

@Roxy-3D
Copy link
Member

Roxy-3D commented Nov 29, 2021

Thank you for these explanations. If the effects are as you describe them, indeed G29 j will not be able to correct the problem...

I didn't describe the example case as well as I could have. It is easier to envision the twist causing a rise of the Z Probe if the Z probe has 0.000 mm of Y offset. Please assume that the nozzle is exactly aligned with the Z Probe with regard to Y Axis at the middle of the bed. And if that is the case when the carriage moves to the XMin side it will twist one way. And if the carriage moves from the center to XMax side it will twist the other way. But the important point is either way the carriage moves off center it will raise the Z probe.

Even if the bed is perfectly flat... when you probe it, it will have a saddle shape to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants