-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Create AddCoolingProfile.py #15853
Create AddCoolingProfile.py #15853
Conversation
I think adding more description, or a screenshot, would be extremely helpful |
Advanced fan control post-processor. "By Layer" or "By Feature" for up to 4 fan circuits. Update AddCoolingProfile.py Fixed a problem in the AddNonMesh section. Update AddCoolingProfile.py Added code to skip M20? accel and jerk lines when calculating travel moves. Update AddCoolingProfile.py Remove the line to add the name to the gcode file. Update AddCoolingProfile.py Move the initial fan shutoffs so they are before the "Layer_count" line.
Remove caps from variable names. Removed Logger.
Add a kick-out if "One at a Time" is enabled in Cura.
This reverts commit 34d348d.
Added ability to handle "One at a Time". Removed the One at a Time kickout code.
It's long, it's involved, it's industrial strength, it works. |
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.
Hi Greg!
I find that one of the reasons that it takes me so long to get to these each time, is that on the one hand they're useful and I can see a lot of work has gone into them. (Also, the code is at least quite readable, and I think to a certain extent also maintainable.)
And, like you said, they work (though I'm not sure I get what you mean with 'Industrial Strength'). Yet another thing is that the scripts don't quite need to adhere to the level of code-standards we use in the rest of the code, since they're --in a way-- separate.
On the other hand (and this gets me to my point, which is that) I don't think I'd be accepting any of this without alterations if it was for the main code base. I'm on the fence as it is. (Too much of my time is spend actually sitting on that metephorical fence, which I realize says a whole lot more about me then about your code, but here we are ... 😅 )
I've decided to finally bite the bullet and go through the things I'd really like to have changed, as I should have in the first place. We can have discussions about most of these, but at the very least I'd like to get rid of the repetition of the '9999..' string.
t0_fan = " P0"; t1_fan = " P0"; t2_fan = " P0"; t3_fan = " P0"; is_multi_extr_print = True | ||
|
||
#Get some information from Cura----------------------------------- | ||
extrud = Application.getInstance().getGlobalContainerStack().extruderList |
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.
If using this Application.getInstance().getGlobalContainerStack()
multiple times, you should request it once, and put it in a variable.
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.
Done.
fan_1st = self.getSettingValueByKey("fan_1st") | ||
if "/" in fan_1st: | ||
fan_list[0] = check_layer.layer_checker(fan_1st, "l", fan_mode) | ||
fan_list[1] = check_layer.layer_checker(fan_1st, "p", fan_mode) | ||
fan_2nd = self.getSettingValueByKey("fan_2nd") | ||
if "/" in fan_2nd: | ||
fan_list[2] = check_layer.layer_checker(fan_2nd, "l", fan_mode) | ||
fan_list[3] = check_layer.layer_checker(fan_2nd, "p", fan_mode) | ||
fan_3rd = self.getSettingValueByKey("fan_3rd") | ||
if "/" in fan_3rd: | ||
fan_list[4] = check_layer.layer_checker(fan_3rd, "l", fan_mode) | ||
fan_list[5] = check_layer.layer_checker(fan_3rd, "p", fan_mode) | ||
fan_4th = self.getSettingValueByKey("fan_4th") | ||
if "/" in fan_4th: | ||
fan_list[6] = check_layer.layer_checker(fan_4th, "l", fan_mode) | ||
fan_list[7] = check_layer.layer_checker(fan_4th, "p", fan_mode) | ||
fan_5th = self.getSettingValueByKey("fan_5th") | ||
if "/" in fan_5th: | ||
fan_list[8] = check_layer.layer_checker(fan_5th, "l", fan_mode) | ||
fan_list[9] = check_layer.layer_checker(fan_5th, "p", fan_mode) | ||
fan_6th = self.getSettingValueByKey("fan_6th") | ||
if "/" in fan_6th: | ||
fan_list[10] = check_layer.layer_checker(fan_6th, "l", fan_mode) | ||
fan_list[11] = check_layer.layer_checker(fan_6th, "p", fan_mode) | ||
fan_7th = self.getSettingValueByKey("fan_7th") | ||
if "/" in fan_7th: | ||
fan_list[12] = check_layer.layer_checker(fan_7th, "l", fan_mode) | ||
fan_list[13] = check_layer.layer_checker(fan_7th, "p", fan_mode) | ||
fan_8th = self.getSettingValueByKey("fan_8th") | ||
if "/" in fan_8th: | ||
fan_list[14] = check_layer.layer_checker(fan_8th, "l", fan_mode) | ||
fan_list[15] = check_layer.layer_checker(fan_8th, "p", fan_mode) |
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.
Extremely similar code, please replace with loop.
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.
Done.
T0_used = False | ||
T1_used = False | ||
T2_used = False | ||
T3_used = False |
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 sure machines can have a maximum of 4 fans. My issue is mostly that things like this are completely opaque to any user that doesn't dive into the 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.
Tool changer machines can have as many fans as they have toolheads. Large format machines can be configured in a lot of ways. I saw no reason not to support that. It's part of the "Industrial Strength" thing. Not everyone who uses Cura is printing dnd characters with it. For example, the 3D printing group at Ford Motor Company has 4 Modix 1800 printers and a variety of smaller printers (no Chinese crap). When things get large then needs change.
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.
What I mean is that there may be more than 4 fans.
if "T0" in lines: | ||
T0_used = True | ||
if "T1" in lines: | ||
T1_used = True | ||
if "T2" in lines: | ||
T2_used = True | ||
if "T3" in lines: | ||
T3_used = True |
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.
Also, it's probably a good idea to put these in a list anyway (T_used
or Tx_used
or something like that).
if T0_used and (T1_used or T2_used or T3_used): | ||
is_multi_extr_print = True | ||
elif T1_used and (T0_used or T2_used or T3_used): | ||
is_multi_extr_print = True | ||
elif T2_used and (T0_used or T1_used or T3_used): | ||
is_multi_extr_print = True | ||
elif T3_used and (T0_used or T1_used or T2_used): | ||
is_multi_extr_print = True | ||
else: | ||
is_multi_extr_print = False |
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.
Case in point: You could just count the number used here by looping over that array.
if line == "T0": this_fan = t0_fan | ||
if line == "T1": this_fan = t1_fan | ||
if line == "T2": this_fan = t2_fan | ||
if line == "T3": this_fan = t3_fan |
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.
Please loop.
if ";TYPE:SKIRT" in line: | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_skirt + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_skirt.split("S")[1]) | ||
elif ";TYPE:WALL-INNER" in line: | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_wall_inner + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_wall_inner.split("S")[1]) | ||
elif ";TYPE:WALL-OUTER" in line: | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_wall_outer + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_wall_outer.split("S")[1]) | ||
elif ";TYPE:FILL" in line: | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_fill + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_fill.split("S")[1]) | ||
elif ";TYPE:SKIN" in line: | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_skin + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_skin.split("S")[1]) | ||
elif line == ";TYPE:SUPPORT": | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_support + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_support.split("S")[1]) | ||
elif ";TYPE:SUPPORT-INTERFACE" in line: | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_support_interface + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_support_interface.split("S")[1]) | ||
elif ";MESH:NOMESH" in line or ";MESH:NONMESH" in line: #compatibility with 5.3.0 'NOMESH' | ||
if fan_combing == True: | ||
modified_data += line + "\n" | ||
modified_data += "M106 S0" + this_fan + "\n" | ||
current_fan_speed = "0" | ||
else: | ||
modified_data += line + "\n" | ||
elif ";TYPE:PRIME-TOWER" in line: | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_prime_tower + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_prime_tower.split("S")[1]) | ||
elif line == ";BRIDGE": | ||
modified_data += line + "\n" | ||
modified_data += fan_sp_bridge + this_fan + "\n" | ||
current_fan_speed = str(fan_sp_bridge.split("S")[1]) | ||
#If an end layer is defined - Insert the final speed and set the other variables to Final Speed to finish the file | ||
elif line == ";LAYER:" + str(the_end_layer): |
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.
For the similar bits of code here, you can make the three (often) repeated lines into a function, then do the same 'trick' I described earlier with the mapping (and/or another lambda/function).
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 have no idea what a lambda is beyond it being a Greek letter.
fan_string_l = str(fan_string.split("/")[0]) | ||
try: | ||
if int(fan_string_l) <= 1: fan_string_l = "1" | ||
if fan_string_l == "": fan_string_l = "999999999" |
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.
Repeated string 2
if int(fan_string_l) <= 1: fan_string_l = "1" | ||
if fan_string_l == "": fan_string_l = "999999999" | ||
except ValueError: | ||
fan_string_l = "999999999" |
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.
Repeated string 3
} | ||
}""" | ||
|
||
def execute(self, data): |
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'd greatly prefer it if this main execute function was broken up into more sub-functions.
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'll take another look. I learn as I go. Todays commit was housecleaning. I'll change this to a draft.
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.
Alright. I've removed the secondary classes and split 4 functions out of the long script. It's still long but it's a little neater.
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've got time to take a look now, but I noticed you closed a bunch of plugins. I hope I didn't come on too strong in the reviews?
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.
Nah. I'll never be a software engineer and I'm not going to bother to try. The only thing I know about a "lambda" is that it's a Greek letter. The posts work for me and I'm good with that.
For something like the fan control it's been requested for over six years and I agreed it would be a really good idea so I gave it a shot. I use it and DispalyInfoOnLCD on every print.
I'm sure all the UM code looks nice. Then there are things like this example. That bothered me on a very basic level.
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.
UM code is far from perfect. There are tons of things I'd change if I'd had the time (and energy).
It is a really goof idea, and we'd like to have it in here. The other reason I made my comments the way they are is that in the past, you'd indicated that you'd like to learn.
I'm really sorry this is taking all so long -- ideally, that should not happen, but it is what it is. Next week the team will have a meeting about what to do about the slowness of the interaction with parts of our work outside of that what UM itself mandates (largely community focussed).
I'm not sure if I said it before (I hope I did), but none of this is really bad. I was debating myself whether to just merge it in wholesale without saying anything, but then I wouldn't have done due diligence.
I've finally rested up enough to prepare for work again. As I feel I have some unfinished business here, since I feel like I let you down, I'm going to try and make some small adjustments here and perhaps get it merged this weekend.
Additional cleanup throughout. Altered some variable names. Eliminated the 9999999 strings.
Split the main section into sub routines. Eliminated 2 classes.
Hey man, don't give up on this thing, it rules. I appreciate it |
@rburema I made some of the changes you suggested. There was a lot of breakage but I think I'll take another look and try to get it squared away again. EDIT: I find the entire "pull request" thing to be maddening. I'm attaching my latest version. There are no substantial changes to the script but I did split 4 functions out of the main "execute" function. I found some issues with the regex searches and replacements and those are fixed. Remco, as a side note; I've added functionality to Display Info on LCD, Add Cura Settings, and Little Utilities. |
See discussions in #15853 (on github) and (internally) tracking-ticket CURA-11520
@GregValiant I could've sworn I did download the latest zip (that you put here) but when I redownloaded & ran a compare on the file I have and the new one there where indeed some differences that I'd like to be in. Not sure how that happened. I'll take a look shortly. As for handling PR's in general, for everyone involved: I can imagine; source-control seems like it should be a solved problem, and yet, here we are. I'll try to squeeze in a look at the other one you mentioned as well, but I won't promise anything right now. |
See discussions in #15853 (on github) and (internally) tracking-ticket CURA-11520
It got caught so that's a good thing. That bug you caught needs to be caught again. |
Yes, I merged the new stuff with main already, I took care that my bugfix is still in there. Just so you don't have to search for what I did; the thing I changed (well, besides removing a spurious space somewhere) is the
|
I used a "try / except / pass" which I guess did the same thing. |
That's why I like working with QA -- you can never find it all as a solo dev. |
Advanced fan control post-processor. "By Layer" or "By Feature" for up to 4 fan circuits. This is in response to numerous requests such as #2149 , #5140 , #8527, #8777, #3624
September 10 commit adds an exit if the "print_sequence" is set to "One at a Time" in Cura.
September 14 commit removes the exit code and allows use with "One at a Time".
Description
A new post-processor to control layer cooling fans.
This fixes... OR This improves... -->
Type of change
How Has This Been Tested?
Test Configuration:
Checklist: