-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
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
z_thermal_adjust: Add Z thermal adjuster module #4157
z_thermal_adjust: Add Z thermal adjuster module #4157
Conversation
Use a frame-coupled temperature probe to compensate for thermal expansion in real-time. Signed-off by: Robert Pazdzior <robertp@norbital.com>
Can confirm this works perfectly |
Thanks. In general it looks fine to me. I'd like to give a few more days for others to comment though. I also saw some minor things:
-Kevin |
Thanks for having a look.
-Rob |
Add 'current_z_comp', 'frame_ref_temp', and 'state' to get_status. Match config_reference formatting. Signed-off by: Robert Pazdzior <robertp@norbital.com>
Signed-off by: Robert Pazdzior <robertp@norbital.com>
Okay, but that is quite surprising to me. It's surprising that commodity parts would actually follow theoretical expansion numbers so closely. I would have thought a user would want to measure and confirm the actual deviation. Separately, just as high-level feedback, this support certainly looks interesting, but I don't see a rush to merge it. I'd be interested in hearing the results of many users over the coming months. Cheers, |
I've been running this branch for a a couple months now and its fantastic. It seems to greatly improve my first layer's which have been a problem for me since voron 2.1... |
I've also had zero issues. I'd love to see it merged |
Thanks. I agree it looks like a useful tool. It would be great to get feedback on the type of printer and the specific configuration for each deployment that is currently using this PR. -Kevin |
350^3 voron 2.4, using the default config and frame height 530.0 |
Voron 2.4 300^3 default config |
Sounds like a good idea to me, Kevin. Thanks. Everybody I know currently using it is running a Voron V2. Since I only shared/discussed it on the Voron Discord, that's also probably the only source of testers unless somebody is motivated by this PR. In theory, any enclosed printer in which the XY gantry is connected to the build surface through an appreciable length of aluminum frame would also be susceptible. The common fixed top gantry and descending lead-screw driven bed layout should manifest the same expansion symptoms. Though here it gets a bit more complicated:
Since this is a more common arrangement (see Ender 5, TronXY X5, Hypercubes, Voron V1, etc). Perhaps implementation of configuration options for this two-factor expansion might broaden the applicability of the module? |
That's an interesting idea. Does it run permanently, or just adjust actual print commands? I'm just asking, because I could swear I see some minor frame expansion when doing long bed probing (e.g. 5x5 multisampled). |
As a newer Voron V2.4 owner, this feature is invaluable. Not necessary for people only printing small footprint items but once you start printing full plates, absolutely necessary. I was seeing upwards of 0.04mm of drift due to frame expansion that was unable to be solved by heatsoaking alone. Something about printing that first layer heats up my 300mm V2.4 more than just hours of idle heatsoaking is capable of. This feature is a must have and made me go from hating my expensive and time consuming Voron to loving it again when printing full plates of parts. Only thing it needs is a smoothing function to cut down on the unnecessary rapid fire z-stepping at times. Should be easy to implement. |
Currently running this on a Voron V2.4 and it is working perfectly. This has greatly improved layer consistency as long prints progress and the frame heats and expands. Even after an extended heat soak prior to starting the print there is a noticeable improvement in layer consistency using this code. |
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.
Thanks.
I guess my main comment is that the configuration of this module seems more complicated than I think it could be. Is there any reason we can't simplify this to:
[frame_expansion_compensation]
#adjustment:
# The amount of Z adjustment (in millimeters per degree Celsius) to apply.
#sensor_type:
#sensor_pin:
#min_temp:
#max_temp:
#gcode_id:
# See the "heater_generic" and "extruder" sections for the definition of these
# parameters.
If I understand the code correctly, it seems to apply a Z offset based on the temperature difference since the last Z home. If so, I think both the config and code could be simplified.
See some additional comments below.
-Kevin
raise self.printer.config_error( | ||
"'%s' is not a valid stepper" % self.z_stepper_name) |
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.
It's not valid to raise an error in a "klippy:ready" event handler (see docs/Code_Overview.md). You probably want the "klippy:connect" event handler.
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.
Thanks.
I guess my main comment is that the configuration of this module seems more complicated than I think it could be. Is there any reason we can't simplify this to:
[frame_expansion_compensation] #adjustment: # The amount of Z adjustment (in millimeters per degree Celsius) to apply. #sensor_type: #sensor_pin: #min_temp: #max_temp: #gcode_id: # See the "heater_generic" and "extruder" sections for the definition of these # parameters.
If I understand the code correctly, it seems to apply a Z offset based on the temperature difference since the last Z home. If so, I think both the config and code could be simplified.
See some additional comments below.
-Kevin
Thanks for the review, Kevin.
In principal I agree, and would like to simplify both before finalizing.
I would like to keep the coefficient
config parameter name, as this is consistent with the technical term, "coefficient of linear expansion". As well, the length of the frame member is a necessary input as the change is length is proportional to the total length: l_total = l_ref + l_ref * (coeff * (t_current - t_ref)
gantry_factor
is a kind of stand-in for broader compatibility I'd like to introduce for top mounted fixed gantry/moving bed machine down the line. Hard-coding the 0.5 factor necessary for Voron V2 would make it specific to that machine, so until I can think of a nice way to take care of as many use-cases as possible I would like to keep this factor accessible in the config.
Is there any reason to omit the optional limiting safety parameters? Perhaps I could hard-code some safety checks in this regard. If the min_temp
parameter is defined, will the ADC range error out in time to avoid crashing the head into the bed while trying to e.g. correct for thermal contraction of suddenly dropping to -80C?
def handle_homing_move_end(self, hmove): | ||
'Triggered when Z axis is homed.' | ||
if self.check_eligible(hmove.get_mcu_endstops()): |
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.
This should catch the "homing:home_rails_end" event and look for 2 in homing_state.get_axes()
.
if temp: | ||
self.measured_min = min(self.measured_min, temp) | ||
self.measured_max = max(self.measured_max, temp) |
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.
The if temp
check doesn't make sense - it's always valid (or there is a severe error occurring). Unless there is a need for it, I don't think this code should be tracking measure_min/measured_max.
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.
I'm not running Mainsail or other Moonraker-interfaced frontends, so I can't test this at the moment without some effort, but in so far as I understood min/max tracking was necessary for compatibility. It was a kind contribution from @fsironman necessary to get it running on his system, perhaps he might be able to comment?
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.
The frame_expansion_compensation class is more or less a temperature sensor class that can apply a Z-offset.
The feature itself will work without tracking measure_min/measured_max yes,
but wont work with any third party (in this case moonrake/mainsail)
for which it makes sense to display the temperature from frame_expansion_compensation in its UI.
Hence the same functions as the generic temperature sensor are included (https://github.com/KevinOConnor/klipper/blob/master/klippy/extras/temperature_sensor.py)
This will allow 3rd party pluging to display the temperature in its UI as if its a generic temperature sensor:
(below without it, on top proper display with including min/max change)
self.last_position[:] = newpos | ||
self.last_position[:] = newpos |
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.
Duplicate lines.
I have a question, as I have often wondered if this was some of the reason my second layers were failing on larger prints, also on a 350mm^3 voron v2. Why do you think the frame expansion effects the Z height of the print head? On the Voron, wouldn't it only increase the tension on the z belt loops? I dont see how that directly translates into the gantry rising. Your measurements speak for themselves, as do the positive results others are finding. I look forward to trying it myself. Just curious as to the reason why you think this is happening. |
Hello, The reason the tension increases is because the belts are stretching: the Z idlers are mounted to the top of the frame while the drive pulleys are mounted to bottom, therefore the expansion increases the belt length and consequently the tension. Because of the top mounted idler acting as a pulley, the movement gets reduced to 0.5x the increase in frame length ( |
@KevinOConnor I'd like to do a |
If I understand this code correctly, if I define a printer with In this case, I think it would be preferable to define a single FWIW, with the current code, if I home at 25 degrees, and print a layer at 30 degrees it will apply an offset of .017550mm, and if I print another layer at 35 degrees it will apply an offset of .035100mm. However, if I home at 30 degrees and print a layer at 35 degrees it will apply an offset of 0.0175705335mm. It seems odd to me that going from 30-35 degrees when homing at 25 degrees would have a different offset than going from 30-35 degrees when homing at 30 degrees (.017550mm vs 0.0175705335mm). It looks like a code error to me, but perhaps I'm missing something. -Kevin |
Sorry, I'm really not explaining this clearly and forgot to mention that the length of the frame at the time of homing is also calculated assuming the length provided in the config was measured at room temperature (25C). This value is then used as the reference length to calculate the necessary Z offset. |
Okay, but that calculation does not look correct to me. In the example above, if I home at 25 degrees, and later put down a layer at 40 degrees followed by a layer at 41 degrees then that layer itself has a Z offset of .003510mm subtracted from it. That makes sense as the Z stepper should move less because of heat expansion. However, if I home at 30 degrees and later put down a layer at 40 degrees followed by a layer at 41 degrees then that layer has .0035141067mm subtracted from it. It does not look correct to me that homing temperature is altering the impact of temperature later in the print. Cheers, |
Actually, this is correct, and the reason for sampling the temperature at the time of Z-homing: longer objects expand to a greater (absolute) extent than shorter objects. If you home at 30c then your frame is already longer than it was at 25c, therefore if used as a reference will grow more per degC/K than at 25c - hence the larger offset you mentioned. And since homing to Z-min essentially 'resets' the expansion by driving down past this expansion and re-referencing Z, we don't really care how much a 25c frame would have expanded from 40-41c but rather how much the 30c frame we homed to and are referencing is expanding. I hope that clarifies my considerations in laying out the calculation. Edit: that said, I could be using this equation incorrectly. Maybe you're not meant to 'stack' them like I'm doing. |
I'm sorry but I don't see why this would be any more accurate. Could you please explain? |
That doesn't answer my question. I agree the belt tension increases, and stated as much. The question is how much does the increase in tension raise the gantry? I would propose it would depend on the height of the gantry, ie if you are in the middle of your Z travel, your factor of 0.5x the rate of frame length extension makes good sense. However, if you are at z = 0 or z = max, that surely wouldn't still be the case, would it? I would state the most accurate factor should be a a function of % of z travel currently being used. ( total frame expansion in z * current %z travel). Which is to say the belt is being stretched linearly, with no displacement at the lower drive pulleys, and full displacement at the location of the upper idlers. Assuming the lower drive pulleys is effectively fixed, and the upper idler pulleys are shifting away as the machine warms up. I don't think it makes sense to assume you can just halve the expansion of the vertical frame members because of the idler pulleys. |
You originally asked why, not how. The belts stretching with the frame and dragging the gantry with it is why. How is, however, a very good question and one that I'm honestly not entirely sure of the answer to.
I would expect the belt to stretch more or less uniformly, but I genuinely do not know. I'd like to look into this some more down the road, and if an easy-to-use configuration for such compensation could be implemented ( If you're willing to look into the physics and provide some reading, that would be greatly appreciated, however. My main priority right now is cleaning up the code to Kevin's standards and implementing smoothing for the machine-gun microstepping sound. |
The difference is very small, ignore my comment. frame_length_at_x_a != frame_length_at_x_b then i found the difference is so small, we can just ignore. |
It looks like this GitHub Pull Request has become inactive. If there are any further updates, you can add a comment here or open a new ticket. Best regards, PS: I'm just an automated script, not a human being. |
Signed-off-by: Robert Pazdzior <robertp@norbital.com>
Signed-off-by: Robert Pazdzior <robertp@norbital.com>
Signed-off-by: Robert Pazdzior <robertp@norbital.com>
Signed-off-by: Robert Pazdzior <robertp@norbital.com>
@KevinOConnor Sorry for the inactivity, got stuck on the code and then summer carried me away. I think I've addressed all of your previous points, and the PR should be ready for another look. Thanks, |
Thanks. Looks fine to me. Can you confirm this is still ready to merge? If so, I'll go ahead and merge. -Kevin |
I'd say it's ready to go out the door, merge away! Thanks for all your help and the discussions along the way, Kevin. |
Thanks. -Kevin |
Internal error during connect: 'stepper_z' I assume the current implementation doesn't support delta kinematics? |
Use a frame-coupled temperature probe to compensate for thermal expansion in real-time. Signed-off by: Robert Pazdzior <robertp@norbital.com>
Use a frame-coupled temperature probe to compensate for thermal expansion in real-time. Signed-off by: Robert Pazdzior <robertp@norbital.com>
Use a frame-coupled temperature probe to compensate for thermal expansion in real-time. Signed-off by: Robert Pazdzior <robertp@norbital.com>
Use a frame-coupled temperature probe to compensate for thermal expansion in real-time. Signed-off by: Robert Pazdzior <robertp@norbital.com>
Context/Rationale
For some enclosed 3D printers, particularly larger-format machines, thermal expansion of the vertical frame members can continue for hours after the build plate and air temperature have stabilized. If the machine has not reached equilibrium when a print starts, the toolhead can slowly drift upwards while the frame continues to expand. This is of particular concern with long first layer times, and can even result in weak adhesion with the second layer.
Using MCU position and a nozzle-triggered endstop on my Voron V2 printer:
![image](https://user-images.githubusercontent.com/20025999/165365344-b4482271-c13f-4e06-9aca-adbeac489dd1.png)
Enclosed delta and moving gantry printers likely suffer most from this phenomenon.
Approach
Couple a temperature probe to a vertical member of the frame and use the coefficient of linear expansion for the frame material to calculate the expansion relative to last homing measurement, and transform Z accordingly.
I've personally had success with this approach, and several members of the Voron community have tested it on their machines with positive results.
All comments, criticism, and feedback are very welcome! Thank you.
Signed-off by: Robert Pazdzior robertp@norbital.com