-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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_twist_compensate: Add X twist compensation module #6048
x_twist_compensate: Add X twist compensation module #6048
Conversation
Implements XTwistCompensation, Calibrater and ProfileManager classes Supports calibration of z-offsets caused by x gantry twist, saving/loading of compensation profiles and manual correction of existing bed_mesh using a calibrated compensation profile. Signed-off-by: Jeremy Tan <jeremytkw98@gmail.com>
…pensation Modify PrinterProbe._probe function to check if the probed z value should be adjusted based on x_twist_compensation profile Signed-off-by: Jeremy Tan <jeremytkw98@gmail.com>
Signed-off-by: Jeremy Tan <jeremytkw98@gmail.com>
Installation instructions for interested testers:
And configuration/setup info can be found here |
…sation value Signed-off-by: Jeremy Tan <jeremytkw98@gmail.com>
Hi @koonweee, Is this X twist compensation module, be rearranged to XY? i.e: cross xy could have a twisted Y too. So the given reads could be a misrepresentation of your xy plane twist. Cheers. |
Hi @koonweee , I just tested your work. I did everything as described, but for me it didn't work; at least not without a small modification: I use a Geeetech A30M with a creality sprite pro extruder (and obviously klipper). |
Hey! It is possible to generalize the module for the y axis too. The compensation required would be a summation of both the x and y axis if both are twisted. I believe X twist issues are more common however |
Hey thanks for testing the module. Could you elaborate on your probe setup on your printer? (eg. what probe is used) |
I will be testing this solution this week/weekend. I have mesh issues that I have narrowed down to X extrusion twisting. Unfortunately I cannot manually level this bed so I'm hoping this will work and I will report back my findings and printer information. |
Hey, I edited my previous post with the missing info.
Sent with Spark
Am 12. Feb. 2023, 13:45 +0100 schrieb Jeremy Tan ***@***.***>:
… > Hi @koonweee ,
> I just tested your work.
> I did everything as described, but for me it didn't work; at least not without a small modification: I had to invert the values in the printer.cfg to make the mesh look similar to my manual mesh. Didn't do a new test-print since then. But first test was just as off as the mesh looked like in mainsail.
> I use a Geeetech A30M with a creality sprite pro extruder (and obviously klipper).
Hey thanks for testing the module. Could you elaborate on your probe setup on your printer? (eg. what probe is used)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
Just a guess on my part, but does edit: Let me know about the above, but I will also write some test cases soon which should catch any anomalies in the code |
Thank you and please let me know! out of curiosity, why cant your bed be manually levelled? |
The build plate was hard mounted. I have modified the bed so I can manually adjust the bed, but the screws are located under the flex plate which makes tramming via paper/feeler gauge difficult as I would have to move the nozzle and flex plate every time I needed to make an adjustment. The underside "nut" is just tapped into the Y carriage so I can't use a normal wheel nut to adjust from below. There are also 12 mounting points instead of your typical 4. I however can use screws_tilt_calculate since I can make all 12 adjustments, then re-run it until "level" but I think this was not working right because of possible twist in the X axis. I was having issues where the far right was nearly touching the bed, and the far left was stringing. My BLTouch sensor offset is x: -41, y: +25 from the nozzle. So my probe is actually behind the nozzle which explains why I'm see the opposite pattern as people with a probe in front of the nozzle. I tried it last night, it was more simple than I thought it would be. I had to manually adjust the values myself across 3 points but it did indeed work. I didn't have any non-magnetic feeler gauges so I first did the paper test and got better results than what I was getting prior, and then manually adjusted the values myself until now the whole plate has a great first layer. What method would you use for a bed that cannot be trammed? Like, what order of leveling with only access to screws_tilt_adjust. Should I run that without x_twist_compensation enabled first, then preform x_twist after, and then re-level using screws_tilt_calculate? I'm thinking the order I did things may have made the results not perfect first try around, or maybe its because I was using the paper test which can be pretty inaccurate. Anyways, thank you so much for this! I haven't had a good first layer in almost a year and have been ready to trash this printer so I'm pretty stoked. EDIT: I also used the value recommended for probe_offset which worked nearly perfect. I adjusted it a bit after but no more than 0.02mm. I have not tried to use probe_calibrate after doing any of the above. I saw you asked another user about that. |
Great to hear! I actually have a similar setup with my sv06 where the 4 mounting points have been hardmounted with nylock nuts but I can use bed_screws_calculate to figure out how much to adjust them. As you noted, using this compensation allows you to use bed_screws_calculate, since the probe readings are now correct. Since the x_twist_compensation profile corrects your probe readings, I recommend having compensation profile loaded before you perform any bed_screws_calculate or bed_mesh. I think the slight inaccuracy you saw was indeed from using the paper test. I also use the paper since I do not have any feeler gauges and also have to tweak the recommended probe_offset and generated compensation values ever so slightly to get a perfect first layer. With a feeler gauge, I'm quite sure the generated compensation would be even more accurate on the first try. Do not worry about the probe_calibrate, I asked the other user to perform it just to make sure that their probe setup is correct since they were facing unexpected results (the x twist correction generated was inverted from what was expected) |
I had been meaning to pick up a set of plastic feeler gauges or at least some non magnetic. Maybe I have more of an excuse for it now! I'm about to start a full plate of prints which I haven't been able to do in a very long time :) |
PROBE_CALIBRATE works normal incl. moving the nozzle. |
Hi @koonweee, I performed several tests. Since the result was not yet perfect and my mesh is done on 9 points, The calibration went well, but when I want to perform a BED_MESH_CALIBRATE it probes the first point "list indices must be integers, not float" With 7 or 5 points it is on the third point. By leaving default (so with 3 points) no worries. But the result is not perfect. Thank you for your help. |
Hi @koonweee, I looked quickly.
Must do the job. But I'm not a python expert. |
I created a small simulation program based on your function (with the addition of the int conversion of the index) The way "interpolate_t" is calculated is used in the calculation of the linear correction gives a small error but Now all that remains is to test with 9 points in real on my machine. Many thanks for your work. |
@murdock62 Did you get round to testing it on your machine? |
Hi @koonweee. Yes I'm not yet at the end of everything I wanted to test but if all goes well However, I still have the first results which are rather very encouraging. It's not perfect, However, I ask myself two questions about the small lack to achieve perfection :
Let's assume that this is my first use of your function. When I launch a print I start by activating the compensation then home then QGL (this time with the compensation The problem is that this QGL carried out with the compensation certainly gives a better mechanical alignment of We could perhaps improve the linearity of the correction by playing on the calculation of the "interpolate_t" variable, Congratulations and thank you again for your work. |
@koonweee I finally got around to redoing it with plastic feeler gauges and it worked perfectly. I can print full plates of parts with no deviation from side to side. I think I might have a slight twist in my Y axis as well though, so if we could get this to do both that would be amazing! Deviation from front to back is pretty minor, but noticeable when printing a full plate. Probably less than 0.1mm. |
Thanks for the update! Doing it for the Y axis should be possible as well with some refactoring of the code. I am hoping to do this soon (swamped with school at the moment 😓 ) |
That would be awesome! No rush, I appreciate what you have done already! |
self.pmgr.create_profile(profile_name, self.results, avg) | ||
# recommend z offset to user | ||
self.gcmd.respond_info( | ||
"X_TWIST_CALIBRATE: Calibration complete, reccomended z_offset: %f" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"X_TWIST_CALIBRATE: Calibration complete, reccomended z_offset: %f" | |
"X_TWIST_CALIBRATE: Calibration complete, recommended z_offset: %f" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drive-by review - currently testing the PR and figured I would check the code as well :)
desc=self.cmd_X_TWIST_COMPENSATE_STATUS_help) | ||
|
||
def get_z_compensation_value(self, x_coord, optional_profile_name=None): | ||
# returns the (lineraly interpolated) z compensation value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# returns the (lineraly interpolated) z compensation value | |
# returns the (linearly interpolated) z compensation value |
avg = sum(self.results) / len(self.results) | ||
# subtract average from each result | ||
# so that they are independent of z_offset | ||
self.results = [avg - x for x in self.results] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be useful to print the variance here so the user can have an idea how bad their probe location bias is?
I think a side effect of this PR is that it easily allows users to check probe location bias - along the X axis, at least. That might be useful when attempting to tune out mechanical problems.
# return the current profile | ||
if self.current_profile is None: | ||
raise self.gcode.error( | ||
"No X_TWIST_PROFILE loaded") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this would help the user:
"No X_TWIST_PROFILE loaded") | |
"No X_TWIST_PROFILE loaded. Load an existing profile with X_TWIST_PROFILE_LOAD or create a new profile with X_TWIST_CALIBRATE.") |
is enabled. | ||
|
||
#### X_TWIST_CALIBRATE | ||
`X_TWIST_CALIBRATE [N_POINTS=<value>]`: Initiates the X twist calibration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include PROFILE_NAME
here?
self.load_profile(profile_name) | ||
|
||
cmd_X_TWIST_PROFILE_CLEAR_help = \ | ||
"Clears the active mesh" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is mesh the correct wording here?
"Clears the active mesh" | |
"Clears the active X twist compensation" |
self.clear_profile() | ||
|
||
cmd_X_TWIST_PROFILE_SAVE_help = \ | ||
"Saves the active mesh to the config file" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Saves the active mesh to the config file" | |
"Saves the active X twist compensation profile to the config file" |
After more tests I can say that according to my results this function brings a significant improvement. On a machine where the X axis is fixed like a cr-10 or other, we are almost at perfection. On a machine like a voron 2.4 there is still a very small defect but I think that as mentioned above I think best when printing and only activating the correction after the QGL. Good work !!! |
I have a SV06 and I want to let you know that this module has made a huge difference! It seems to be working great for me! |
Interesting, thanks. As high-level feedback, compensating for probe location based inaccuracies seems like useful functionality. When reviewing the code it seems to me like the feature is in an "experimental" phase though. So, I'm not sure it is ready to merge to the master Klipper repository. Some high-level comments:
Cheers, |
Thanks a lot for porting this feature to Klipper! I also have a SV06 and was thinking I had to give up the automatic bed mesh feature when switching from Marlin to Klipper. I have tested your code (rebased on v0.11.0, but it shouldn't matter much). I have found a couple bugs, you can look at my fixes here blastrock@0fc4d9f . The first bug is that all offsets were calculated against the same measured Z from the probe, at the launch of Klipper. This not only included the X twist offset, but also the offset from the bed not being leveled. It looks like your patch discards the measured Z on each point. The second bug is that the results array was not reset upon rerunning the calibration. This made the array contain 6 values at the end of the calibration instead of 3. With these fixes I finally got a nice first layer, really looking forward to this being merged :) |
Hello, my mesh probing also crashes when i perform the twist calibration with 9 points. |
Having looked at this PR I agree with Kevin's comments. I don't think its a good idea to transform saved mesh profiles, instead we should encourage users recalibrate the mesh after twist calibration. It may be worth exploring whether or not twist is impacted by heat. If there is data that shows a measurable impact based on temperature then profiles may be useful. Should it turn out that profiles are useful I think it would be desirable for the commands to be consistent with |
Thank you for your contribution to Klipper. Unfortunately, a reviewer has not assigned themselves to this GitHub Pull Request. All Pull Requests are reviewed before merging, and a reviewer will need to volunteer. Further information is available at: https://www.klipper3d.org/CONTRIBUTING.html There are some steps that you can take now:
Unfortunately, if a reviewer does not assign themselves to this GitHub Pull Request then it will be automatically closed. If this happens, then it is a good idea to move further discussion to the Klipper Discourse server. Reviewers can reach out on that forum to let you know if they are interested and when they are available. Best regards, PS: I'm just an automated script, not a human being. |
Hi there, Since there isn't much activity on this PR, I took the liberty of fixing what was pointed out during this review: #6149 |
Unfortunately a reviewer has not assigned themselves to this GitHub Pull Request and it is therefore being closed. It is a good idea to move further discussion to the Klipper Discourse server. Reviewers can reach out on that forum to let you know if they are interested and when they are available. Best regards, PS: I'm just an automated script, not a human being. |
Is there still someone watching? |
@Flol0 |
Sorry i read it but didn`t realize it was linking to another PR. Thought it got fixed in here. |
Context
Printers with a probe that have a probe y_offset may give inaccurate probe results due to a twist in the probe's X axis. This is common in printers with designs like the Prusa MK3, Sovol 06 etc, as described under probe location bias in the Klipper documentation. It may result in probe operations such as Bed Mesh, Screws Tilt Adjust, Z Tilt Adjust etc returning inaccurate representations of the bed.
The following diagram (by @MauroGil66) and video help to visualize the issue
Video "Visualization of x-sled-rotation", by Elhanan Maayan
This issue is also often reported on Marlin, and some of the users on the Klipper discourse [Post 1, Post 2]
Fix
The fix implemented adapts math from the fix implemented in Marlin. The user can manually calibrate the z-offset at a few points along the x axis, and linear interpolation is done to figure out the appropriate z-offset at all other points.
probe.py
is modified such that the z-compensation is applied for all calls to the probe to determine a z-height. This allows modules that use the probe such as bed_mesh and z_tilt_adjust to benefit from the calibrated probe z-heights.Testing
Admittedly, real world testing is currently limited on this. I have personally tested it to work wonderfully on my own SV06, and have posted it in a few Discord channels/the Klipper discourse for more users to test it out.
All comments, criticism, and feedback are very welcome! Thank you.
Signed-off by: Jeremy Tan jeremytkw98@gmail.com