From da0fe19c962c5e9b22c1b53949ca1d05b3addae5 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 31 Mar 2024 07:55:36 -0400 Subject: [PATCH 01/25] Update DisplayInfoOnLCD.py Bug fix for "remaining_time". Affected M118 and M73_time Update DisplayInfoOnLCD.py Add options for Time-to-pause to include Filament Change. Update DisplayInfoOnLCD.py Make M117 optional. Combine M73 R and M73 P lines into a single line. Add A and P parameters for M118 lines. Update DisplayInfoOnLCD A TouchUp. Update DisplayInfoOnLCD.py TouchUp Update DisplayInfoOnLCD.py TuneUp --- .../scripts/DisplayInfoOnLCD.py | 265 +++++++++++++----- .../scripts/DisplayInfoOnLCD.zip | Bin 0 -> 7911 bytes 2 files changed, 195 insertions(+), 70 deletions(-) create mode 100644 plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 63c1c8c788..870a64834d 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -7,7 +7,8 @@ # Cura Post-Process plugin # Combines 'Display Filename and Layer on the LCD' with 'Display Progress' # Combined and with additions by: GregValiant (Greg Foresi) -# Date: September 8, 2023 +# Date: September 8, 2023 +# Date: March 31, 2024 - Bug fix for problem with adding M118 lines if 'Remaining Time' was not checked. # NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete # Description: Display Filename and Layer options: # Status messages sent to the printer... @@ -34,9 +35,19 @@ import time import datetime import math from UM.Message import Message +import re class DisplayInfoOnLCD(Script): + def initialize(self) -> None: + super().initialize() + try: + if Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") == "all_at_once": + enable_countdown = True + self._instance.setProperty("enable_countdown", "value", enable_countdown) + except: + pass + def getSettingDataString(self): return """{ "name": "Display Info on LCD", @@ -77,7 +88,7 @@ class DisplayInfoOnLCD(Script): "label": "Initial layer number:", "description": "Choose which number you prefer for the initial layer, 0 or 1", "type": "int", - "default_value": 0, + "default_value": 1, "minimum_value": 0, "maximum_value": 1, "enabled": "display_option == 'filename_layer'" @@ -114,17 +125,40 @@ class DisplayInfoOnLCD(Script): "default_value": true, "enabled": "display_option == 'display_progress'" }, + "add_m117_line": + { + "label": "Add M117 Line", + "description": "M117 sends a message to the LCD screen. Some screen firmware will not accept or display messages.", + "type": "bool", + "default_value": true + }, "add_m118_line": { "label": "Add M118 Line", "description": "Adds M118 in addition to the M117. It will bounce the message back through the USB port to a computer print server (if a printer server like Octoprint or Pronterface is in use).", "type": "bool", - "default_value": false + "default_value": true + }, + "add_m118_a1": + { + "label": " Add A1 to M118 Line", + "description": "Adds A1 parameter. A1 adds a double foreslash '//' to the response. Octoprint may require this.", + "type": "bool", + "default_value": false, + "enabled": "add_m118_line" + }, + "add_m118_p0": + { + "label": " Add P0 to M118 Line", + "description": "Adds P0 parameter. P0 has the printer send the response out through all it's ports. Octoprint may require this.", + "type": "bool", + "default_value": false, + "enabled": "add_m118_line" }, "add_m73_line": { "label": "Add M73 Line(s)", - "description": "Adds M73 in addition to the M117. For some firmware this will set the printers time and or percentage.", + "description": "Adds M73 in addition to the M117. For some firmware this will set the printers time and or percentage. M75 is added to the beginning of the file and M77 is added to the end of the file. M73 will be added if one or both of the following options is chosen.", "type": "bool", "default_value": false, "enabled": "display_option == 'display_progress'" @@ -132,7 +166,7 @@ class DisplayInfoOnLCD(Script): "add_m73_percent": { "label": " Add M73 Percentage", - "description": "Adds M73 with the P parameter. For some firmware this will set the printers 'percentage' of layers completed and it will count upward.", + "description": "Adds M73 with the P parameter to the start of each layer. For some firmware this will set the printers 'percentage' of layers completed and it will count upward.", "type": "bool", "default_value": false, "enabled": "add_m73_line and display_option == 'display_progress'" @@ -140,10 +174,10 @@ class DisplayInfoOnLCD(Script): "add_m73_time": { "label": " Add M73 Time", - "description": "Adds M73 with the R parameter. For some firmware this will set the printers 'print time' and it will count downward.", + "description": "Adds M73 with the R parameter to the start of each layer. For some firmware this will set the printers 'print time' and it will count downward.", "type": "bool", "default_value": false, - "enabled": "add_m73_line and display_option == 'display_progress'" + "enabled": "add_m73_line and display_option == 'display_progress' and display_remaining_time" }, "speed_factor": { @@ -154,13 +188,29 @@ class DisplayInfoOnLCD(Script): "default_value": 100, "enabled": "enable_end_message or display_option == 'display_progress'" }, + "enable_countdown": + { + "label": "Enable Countdown to Pauses", + "description": "If print sequence is 'one_at_a_time' this is false. This setting is always hidden.", + "type": "bool", + "value": false, + "enabled": false + }, "countdown_to_pause": { "label": "Countdown to Pauses", - "description": "Instead of the remaining print time the LCD will show the estimated time to pause (TP).", + "description": "This must run AFTER any script that adds a pause. Instead of the remaining print time the LCD will show the estimated time to the next layer that has a pause (TP).", "type": "bool", "default_value": false, - "enabled": "display_option == 'display_progress'" + "enabled": "display_option == 'display_progress' and enable_countdown and display_remaining_time" + }, + "pause_cmd": + { + "label": " What pause command(s) are used?", + "description": "This might be M0, or M25 or M600 if Filament Change is used. If you have mixed commands then delimit them with a comma ',' (Ex: M0,M600). Spaces are not allowed.", + "type": "str", + "default_value": "M0", + "enabled": "countdown_to_pause and enable_countdown and display_remaining_time" }, "enable_end_message": { @@ -173,40 +223,57 @@ class DisplayInfoOnLCD(Script): "print_start_time": { "label": "Print Start Time (Ex 16:45)", - "description": "Use 'Military' time. 16:45 would be 4:45PM. 09:30 would be 9:30AM. If you leave this blank it will be assumed that the print will start Now. If you enter a guesstimate of your printer start time and that time is before 'Now' the guesstimate will consider that the print will start tomorrow at the entered time. ", + "description": "Use 'Military' time. 16:45 would be 4:45PM. 09:30 would be 9:30AM. If you leave this blank it will be assumed that the print will start Now. If you enter a guesstimate of your printer start time and that time is before 'Now' then the guesstimate will consider that the print will start tomorrow at the entered time. ", "type": "str", "default_value": "", "unit": "hrs ", "enabled": "enable_end_message" } - } }""" def execute(self, data): display_option = self.getSettingValueByKey("display_option") + add_m117_line = self.getSettingValueByKey("add_m117_line") add_m118_line = self.getSettingValueByKey("add_m118_line") + add_m118_a1 = self.getSettingValueByKey("add_m118_a1") + add_m118_p0 = self.getSettingValueByKey("add_m118_p0") + m118_text = "M118 " + m118_str = "M118 " + if add_m118_line: + if add_m118_a1 and not add_m118_p0: + m118_str = "M118 A1 " + if add_m118_p0 and not add_m118_a1: + m118_str = "M118 P0 " + if add_m118_p0 and add_m118_a1: + m118_str = "M118 A1 P0 " add_m73_line = self.getSettingValueByKey("add_m73_line") add_m73_time = self.getSettingValueByKey("add_m73_time") add_m73_percent = self.getSettingValueByKey("add_m73_percent") + m73_str = "" # This is Display Filename and Layer on LCD--------------------------------------------------------- if display_option == "filename_layer": max_layer = 0 lcd_text = "M117 " + octo_text = "M118 " if self.getSettingValueByKey("file_name") != "": file_name = self.getSettingValueByKey("file_name") else: file_name = Application.getInstance().getPrintInformation().jobName if self.getSettingValueByKey("addPrefixPrinting"): lcd_text += "Printing " + octo_text += "Printing " if not self.getSettingValueByKey("scroll"): lcd_text += "Layer " + octo_text += "Layer " else: lcd_text += file_name + " - Layer " + octo_text += file_name + " - Layer " i = self.getSettingValueByKey("startNum") for layer in data: display_text = lcd_text + str(i) + m118_text = octo_text + str(i) layer_index = data.index(layer) lines = layer.split("\n") for line in lines: @@ -217,18 +284,29 @@ class DisplayInfoOnLCD(Script): max_layer = str(int(max_layer) - 1) if line.startswith(";LAYER:"): if self.getSettingValueByKey("maxlayer"): - display_text = display_text + " of " + max_layer + display_text += " of " + max_layer + m118_text += " of " + max_layer if not self.getSettingValueByKey("scroll"): - display_text = display_text + " " + file_name + display_text += " " + file_name + m118_text += " " + file_name else: if not self.getSettingValueByKey("scroll"): - display_text = display_text + " " + file_name + "!" + display_text += " " + file_name + "!" + m118_text += " " + file_name + "!" else: - display_text = display_text + "!" + display_text += "!" + m118_text += "!" line_index = lines.index(line) - lines.insert(line_index + 1, display_text) + if add_m117_line: + lines.insert(line_index + 1, display_text) if add_m118_line: - lines.insert(line_index + 2, str(display_text.replace("M117", "M118", 1))) + if add_m118_a1 and not add_m118_p0: + m118_str = m118_text.replace("M118 ","M118 A1 ") + if add_m118_p0 and not add_m118_a1: + m118_str = m118_text.replace("M118 ","M118 P0 ") + if add_m118_p0 and add_m118_a1: + m118_str = m118_text.replace("M118 ","M118 A1 P0 ") + lines.insert(line_index + 2, m118_str) i += 1 final_lines = "\n".join(lines) data[layer_index] = final_lines @@ -239,7 +317,13 @@ class DisplayInfoOnLCD(Script): # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- elif display_option == "display_progress": - # get settings + print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") + ## Add the Initial Layer Height just below Layer Height in data[0] + init_layer_hgt_line = ";Initial Layer Height: " + str(Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")) + nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) + match = re.search(";Layer height: (\d\.\d*)", data[0])[0] + data[0] = re.sub(match, match + "\n" + init_layer_hgt_line + "\n" + nozzle_size_line, data[0]) + ## Get settings display_total_layers = self.getSettingValueByKey("display_total_layers") display_remaining_time = self.getSettingValueByKey("display_remaining_time") speed_factor = self.getSettingValueByKey("speed_factor") / 100 @@ -249,12 +333,16 @@ class DisplayInfoOnLCD(Script): m73_time = True if add_m73_line and add_m73_percent: m73_percent = True - # initialize global variables + if add_m73_line: + data[1] = "M75\n" + data[1] + data[len(data)-1] += "M77\n" + ## Initialize some variables first_layer_index = 0 - time_total = 0 + time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) number_of_layers = 0 time_elapsed = 0 - # if at least one of the settings is disabled, there is enough room on the display to display "layer" + + ## If at least one of the settings is disabled, there is enough room on the display to display "layer" first_section = data[0] lines = first_section.split("\n") for line in lines: @@ -268,28 +356,40 @@ class DisplayInfoOnLCD(Script): orig_hhh = cura_time/3600 orig_hr = round(orig_hhh // 1) orig_mmm = math.floor((orig_hhh % 1) * 60) - orig_sec = round((((orig_hhh % 1) * 60) % 1) * 60) - if add_m118_line: lines.insert(tindex + 3,"M118 Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") - lines.insert(tindex + 3,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") - # add M73 line at beginning + if add_m118_line: lines.insert(tindex + 5, m118_str + "Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") + if add_m117_line: lines.insert(tindex + 5,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") + ## Add M73 line at beginning mins = int(60 * hr + mmm) - if m73_time: - lines.insert(tindex + 3, "M73 R{}".format(mins)) - if m73_percent: - lines.insert(tindex + 3, "M73 P0") - # If Countdonw to pause is enabled then count the pauses + if add_m73_line and (add_m73_time or add_m73_percent): + if m73_time: + m73_str += " R{}".format(mins) + if m73_percent: + m73_str += " P0" + lines.insert(tindex + 4, "M73" + m73_str) + # If Countdown to pause is enabled then count the pauses pause_str = "" if bool(self.getSettingValueByKey("countdown_to_pause")): pause_count = 0 - for num in range(2,len(data) - 1, 1): - if "PauseAtHeight.py" in data[num]: - pause_count += 1 - pause_str = f" with {pause_count} pause(s)" - # This line goes in to convert seconds to hours and minutes - lines.insert(tindex + 3, f";Cura Time Estimate: {cura_time}sec = {orig_hr}hr {orig_mmm}min {orig_sec}sec {pause_str}") + pause_setting = self.getSettingValueByKey("pause_cmd").upper() + pause_cmd = [] + if "," in pause_setting: + pause_cmd = pause_setting.split(",") + else: + pause_cmd.append(pause_setting) + for q in range(0, len(pause_cmd)): + pause_cmd[q] = "\n" + pause_cmd[q] + for num in range(2,len(data) - 2, 1): + for q in range(0,len(pause_cmd)): + if pause_cmd[q] in data[num]: + pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) + pause_str = f" with {pause_count} pause(s)" + ## This line goes in to convert seconds to hours and minutes + lines.insert(tindex + 5, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") data[0] = "\n".join(lines) - data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" - if add_m118_line: data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" + if add_m117_line: + data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" + if add_m118_line: + data[len(data)-1] += m118_str + " Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" if not display_total_layers or not display_remaining_time: base_display_text = "layer " else: @@ -308,6 +408,11 @@ class DisplayInfoOnLCD(Script): for line in data_section.split("\n"): if line.startswith(";LAYER_COUNT:"): number_of_layers = int(line.split(":")[1]) + if print_sequence == "one_at_a_time": + number_of_layers = 1 + for lay in range(2,len(data)-1,1): + if ";LAYER:" in data[lay]: + number_of_layers += 1 elif line.startswith(";TIME:"): time_total = int(line.split(":")[1]) # for all layers... @@ -352,15 +457,26 @@ class DisplayInfoOnLCD(Script): # insert the text AFTER the first line of the layer (in case other scripts use ";LAYER:") for l_index, line in enumerate(lines): if line.startswith(";LAYER:"): - lines[l_index] += "\nM117 " + display_text - # add M73 line - mins = int(60 * h + m) - if m73_time: - lines[l_index] += "\nM73 R{}".format(mins) - if m73_percent: - lines[l_index] += "\nM73 P" + str(round(int(current_layer) / int(number_of_layers) * 100)) + if add_m117_line: + lines[l_index] += "\nM117 " + display_text if add_m118_line: - lines[l_index] += "\nM118 " + display_text + a1_str = "" + p0_str = "" + if add_m118_a1: + a1_str = "A1 " + if add_m118_p0: + p0_str = "P0 " + lines[l_index] += "\nM118 " + a1_str + p0_str + display_text + # add M73 line + if display_remaining_time: + mins = int(60 * h + m) + if add_m73_line and (add_m73_time or add_m73_percent): + m73_str = "" + if m73_time and display_remaining_time: + m73_str += " R{}".format(mins) + if m73_percent: + m73_str += " P" + str(round(int(current_layer) / int(number_of_layers) * 100)) + lines[l_index] += "\nM73" + m73_str break # overwrite the layer with the modified layer data[layer_index] = "\n".join(lines) @@ -381,34 +497,29 @@ class DisplayInfoOnLCD(Script): if line.startswith(";TIME_ELAPSED:"): this_time = (float(line.split(":")[1]))*speed_factor time_list.append(str(this_time)) - if "PauseAtHeight.py" in layer: - for qnum in range(num - 1, pause_index, -1): - time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" - pause_index = num-1 + for p_cmd in pause_cmd: + if p_cmd in layer: + for qnum in range(num - 1, pause_index, -1): + time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" + pause_index = num-1 + break # Make the adjustments to the M117 (and M118) lines that are prior to a pause for num in range (2, len(data) - 1,1): layer = data[num] lines = layer.split("\n") for line in lines: - if line.startswith("M117") and "|" in line and "P" in time_list[num]: - M117_line = line.split("|")[0] + "| TP " - alt_time = time_list[num][:-1] - hhh = int(float(alt_time) / 3600) - if hhh > 0: - hhr = str(hhh) + "h" - else: - hhr = "" - mmm = ((float(alt_time) / 3600) - (int(float(alt_time) / 3600))) * 60 - sss = int((mmm - int(mmm)) * 60) - mmm = str(round(mmm)) + "m" - time_to_go = str(hhr) + str(mmm) - if hhr == "": time_to_go = time_to_go + str(sss) + "s" - M117_line = M117_line + time_to_go - layer = layer.replace(line, M117_line) - if line.startswith("M118") and "|" in line and "P" in time_list[num]: - M118_line = line.split("|")[0] + "| TP " + time_to_go - layer = layer.replace(line, M118_line) + try: + if line.startswith("M117") and "|" in line and "P" in time_list[num]: + time_to_go = self.get_time_to_go(time_list[num]) + M117_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M117_line) + if line.startswith("M118") and "|" in line and "P" in time_list[num]: + time_to_go = self.get_time_to_go(time_list[num]) + M118_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M118_line) + except: + continue data[num] = layer setting_data = "" if bool(self.getSettingValueByKey("enable_end_message")): @@ -476,8 +587,22 @@ class DisplayInfoOnLCD(Script): if print_start_time != "": print_start_str = "Print Start Time................." + str(print_start_time) + "hrs" else: - print_start_str = "Print Start Time.................Now." + print_start_str = "Print Start Time.................Now" estimate_str = "Cura Time Estimate.........." + str(print_time) adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) - return finish_str, estimate_str, adjusted_str, print_start_str \ No newline at end of file + return finish_str, estimate_str, adjusted_str, print_start_str + + def get_time_to_go(self, time_str: str): + alt_time = time_str[:-1] + hhh = int(float(alt_time) / 3600) + if hhh > 0: + hhr = str(hhh) + "h" + else: + hhr = "" + mmm = ((float(alt_time) / 3600) - (int(float(alt_time) / 3600))) * 60 + sss = int((mmm - int(mmm)) * 60) + mmm = str(round(mmm)) + "m" + time_to_go = str(hhr) + str(mmm) + if hhr == "": time_to_go = time_to_go + str(sss) + "s" + return time_to_go \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip new file mode 100644 index 0000000000000000000000000000000000000000..fd9e5d90ae894ed7d61fce36a2fb771d58f0c026 GIT binary patch literal 7911 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 literal 0 HcmV?d00001 From 9fe36482f7978e87288d0994711412dc1be0473a Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 7 Apr 2024 09:03:46 -0400 Subject: [PATCH 02/25] Delete DisplayInfoOnLCD.zip Should not have been included. --- .../scripts/DisplayInfoOnLCD.zip | Bin 7911 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.zip deleted file mode 100644 index fd9e5d90ae894ed7d61fce36a2fb771d58f0c026..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7911 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 From e7a1bf89ec94397c5952377de4e47272991a96e0 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Mon, 30 Dec 2024 16:35:02 -0500 Subject: [PATCH 03/25] Update DisplayInfoOnLCD.py Revised the M118 lines and insertion point in the gcode. Revised M117 same. Added nozzle size and filament type to data[0] --- .../scripts/DisplayInfoOnLCD.py | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 870a64834d..ed226c08f3 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -47,7 +47,7 @@ class DisplayInfoOnLCD(Script): self._instance.setProperty("enable_countdown", "value", enable_countdown) except: pass - + def getSettingDataString(self): return """{ "name": "Display Info on LCD", @@ -238,15 +238,6 @@ class DisplayInfoOnLCD(Script): add_m118_line = self.getSettingValueByKey("add_m118_line") add_m118_a1 = self.getSettingValueByKey("add_m118_a1") add_m118_p0 = self.getSettingValueByKey("add_m118_p0") - m118_text = "M118 " - m118_str = "M118 " - if add_m118_line: - if add_m118_a1 and not add_m118_p0: - m118_str = "M118 A1 " - if add_m118_p0 and not add_m118_a1: - m118_str = "M118 P0 " - if add_m118_p0 and add_m118_a1: - m118_str = "M118 A1 P0 " add_m73_line = self.getSettingValueByKey("add_m73_line") add_m73_time = self.getSettingValueByKey("add_m73_time") add_m73_percent = self.getSettingValueByKey("add_m73_percent") @@ -318,12 +309,22 @@ class DisplayInfoOnLCD(Script): # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- elif display_option == "display_progress": print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") - ## Add the Initial Layer Height just below Layer Height in data[0] + # Add the Initial Layer Height just below Layer Height in data[0] + extruder_count = Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) - match = re.search(";Layer height: (\d\.\d*)", data[0])[0] - data[0] = re.sub(match, match + "\n" + init_layer_hgt_line + "\n" + nozzle_size_line, data[0]) - ## Get settings + nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) + filament_type = "\n;Filament type for T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("material_type", "value")) + if extruder_count > 1: + nozzle_size_line += "\n;Nozzle Size T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("machine_nozzle_size", "value")) + filament_type += "\n;Filament type for T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("material_type", "value")) + lines = data[0].split("\n") + for index, line in enumerate(lines): + if line.startswith(";Layer height:"): + lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line + if line.startswith(";Filament used"): + lines[index] += filament_type + data[0] = "\n".join(lines) + # Get settings display_total_layers = self.getSettingValueByKey("display_total_layers") display_remaining_time = self.getSettingValueByKey("display_remaining_time") speed_factor = self.getSettingValueByKey("speed_factor") / 100 @@ -336,13 +337,13 @@ class DisplayInfoOnLCD(Script): if add_m73_line: data[1] = "M75\n" + data[1] data[len(data)-1] += "M77\n" - ## Initialize some variables + # Initialize some variables first_layer_index = 0 time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) number_of_layers = 0 time_elapsed = 0 - ## If at least one of the settings is disabled, there is enough room on the display to display "layer" + # If at least one of the settings is disabled, there is enough room on the display to display "layer" first_section = data[0] lines = first_section.split("\n") for line in lines: @@ -356,10 +357,10 @@ class DisplayInfoOnLCD(Script): orig_hhh = cura_time/3600 orig_hr = round(orig_hhh // 1) orig_mmm = math.floor((orig_hhh % 1) * 60) - if add_m118_line: lines.insert(tindex + 5, m118_str + "Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") - if add_m117_line: lines.insert(tindex + 5,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") - ## Add M73 line at beginning - mins = int(60 * hr + mmm) + if add_m118_line: lines.insert(tindex + 6,"M118 Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") + if add_m117_line: lines.insert(tindex + 6,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") + # Add M73 line at beginning + mins = int(60 * hr + mmm) if add_m73_line and (add_m73_time or add_m73_percent): if m73_time: m73_str += " R{}".format(mins) @@ -383,13 +384,13 @@ class DisplayInfoOnLCD(Script): if pause_cmd[q] in data[num]: pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) pause_str = f" with {pause_count} pause(s)" - ## This line goes in to convert seconds to hours and minutes - lines.insert(tindex + 5, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") + # This line goes in to convert seconds to hours and minutes + lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") data[0] = "\n".join(lines) if add_m117_line: data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" if add_m118_line: - data[len(data)-1] += m118_str + " Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" + data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" if not display_total_layers or not display_remaining_time: base_display_text = "layer " else: @@ -463,7 +464,7 @@ class DisplayInfoOnLCD(Script): a1_str = "" p0_str = "" if add_m118_a1: - a1_str = "A1 " + a1_str = "A1 " if add_m118_p0: p0_str = "P0 " lines[l_index] += "\nM118 " + a1_str + p0_str + display_text @@ -592,8 +593,8 @@ class DisplayInfoOnLCD(Script): adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) return finish_str, estimate_str, adjusted_str, print_start_str - - def get_time_to_go(self, time_str: str): + + def get_time_to_go(self, time_str: str): alt_time = time_str[:-1] hhh = int(float(alt_time) / 3600) if hhh > 0: From da0b99cb8273b5e50a6bd3c994af73800f7d3f72 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 8 Jan 2025 07:46:42 -0500 Subject: [PATCH 04/25] Update DisplayInfoOnLCD.py Added "global_stack" variable. --- .../scripts/DisplayInfoOnLCD.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index ed226c08f3..c4f7ecf55c 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -308,15 +308,16 @@ class DisplayInfoOnLCD(Script): # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- elif display_option == "display_progress": - print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") + global_stack = Application.getInstance().getGlobalContainerStack() + print_sequence = global_stack.getProperty("print_sequence", "value") # Add the Initial Layer Height just below Layer Height in data[0] - extruder_count = Application.getInstance().getGlobalContainerStack().getProperty("machine_extruder_count", "value") - init_layer_hgt_line = ";Initial Layer Height: " + str(Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament type for T0: " + str(Application.getInstance().getGlobalContainerStack().extruderList[0].getProperty("material_type", "value")) + extruder_count = global_stack.getProperty("machine_extruder_count", "value") + init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) + nozzle_size_line = ";Nozzle Size T0: " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) + filament_type = "\n;Filament type for T0: " + str(global_stack.extruderList[0].getProperty("material_type", "value")) if extruder_count > 1: - nozzle_size_line += "\n;Nozzle Size T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type for T1: " + str(Application.getInstance().getGlobalContainerStack().extruderList[1].getProperty("material_type", "value")) + nozzle_size_line += "\n;Nozzle Size T1: " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) + filament_type += "\n;Filament type for T1: " + str(global_stack.extruderList[1].getProperty("material_type", "value")) lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): From 984c19decc764ca51a3ea68a78df3808517bbc92 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 8 Jan 2025 23:01:19 -0500 Subject: [PATCH 05/25] Update DisplayInfoOnLCD.py Bug fix. --- .../scripts/DisplayInfoOnLCD.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index c4f7ecf55c..fc3b22a7a6 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -238,12 +238,14 @@ class DisplayInfoOnLCD(Script): add_m118_line = self.getSettingValueByKey("add_m118_line") add_m118_a1 = self.getSettingValueByKey("add_m118_a1") add_m118_p0 = self.getSettingValueByKey("add_m118_p0") + m118_str = "M118 " + m118_text = "M118 " add_m73_line = self.getSettingValueByKey("add_m73_line") add_m73_time = self.getSettingValueByKey("add_m73_time") add_m73_percent = self.getSettingValueByKey("add_m73_percent") m73_str = "" - # This is Display Filename and Layer on LCD--------------------------------------------------------- + # This is from the original Display Filename and Layer on LCD if display_option == "filename_layer": max_layer = 0 lcd_text = "M117 " @@ -256,7 +258,7 @@ class DisplayInfoOnLCD(Script): lcd_text += "Printing " octo_text += "Printing " if not self.getSettingValueByKey("scroll"): - lcd_text += "Layer " + lcd_text += "Lay " octo_text += "Layer " else: lcd_text += file_name + " - Layer " @@ -275,15 +277,15 @@ class DisplayInfoOnLCD(Script): max_layer = str(int(max_layer) - 1) if line.startswith(";LAYER:"): if self.getSettingValueByKey("maxlayer"): - display_text += " of " + max_layer - m118_text += " of " + max_layer + display_text += "/" + max_layer + m118_text += "/" + max_layer if not self.getSettingValueByKey("scroll"): - display_text += " " + file_name - m118_text += " " + file_name + display_text += "|" + file_name + m118_text += " | " + file_name else: if not self.getSettingValueByKey("scroll"): - display_text += " " + file_name + "!" - m118_text += " " + file_name + "!" + display_text += "|" + file_name + "!" + m118_text += " | " + file_name + "!" else: display_text += "!" m118_text += "!" @@ -291,6 +293,8 @@ class DisplayInfoOnLCD(Script): if add_m117_line: lines.insert(line_index + 1, display_text) if add_m118_line: + if not (add_m118_p0 and add_m118_a1): + m118_str = m118_text if add_m118_a1 and not add_m118_p0: m118_str = m118_text.replace("M118 ","M118 A1 ") if add_m118_p0 and not add_m118_a1: @@ -306,7 +310,7 @@ class DisplayInfoOnLCD(Script): Message(title = "Display Info on LCD - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() return data - # Display Progress (from 'Show Progress' and 'Display Progress on LCD')--------------------------------------- + # This is from 'Show Progress on LCD' elif display_option == "display_progress": global_stack = Application.getInstance().getGlobalContainerStack() print_sequence = global_stack.getProperty("print_sequence", "value") From 043afdb6ed7fbaa672c383ca2337c19564254177 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:01:44 -0500 Subject: [PATCH 06/25] Update DisplayInfoOnLCD.py Update. Remove vestigial line of code at line 530. --- .../scripts/DisplayInfoOnLCD.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index fc3b22a7a6..38649ed6ce 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -377,18 +377,21 @@ class DisplayInfoOnLCD(Script): if bool(self.getSettingValueByKey("countdown_to_pause")): pause_count = 0 pause_setting = self.getSettingValueByKey("pause_cmd").upper() - pause_cmd = [] - if "," in pause_setting: - pause_cmd = pause_setting.split(",") + if pause_setting != "": + pause_cmd = [] + if "," in pause_setting: + pause_cmd = pause_setting.split(",") + else: + pause_cmd.append(pause_setting) + for q in range(0, len(pause_cmd)): + pause_cmd[q] = "\n" + pause_cmd[q] + for num in range(2,len(data) - 2, 1): + for q in range(0,len(pause_cmd)): + if pause_cmd[q] in data[num]: + pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) + pause_str = f"with {pause_count} pause(s)" else: - pause_cmd.append(pause_setting) - for q in range(0, len(pause_cmd)): - pause_cmd[q] = "\n" + pause_cmd[q] - for num in range(2,len(data) - 2, 1): - for q in range(0,len(pause_cmd)): - if pause_cmd[q] in data[num]: - pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) - pause_str = f" with {pause_count} pause(s)" + pause_str = "" # This line goes in to convert seconds to hours and minutes lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") data[0] = "\n".join(lines) @@ -527,7 +530,6 @@ class DisplayInfoOnLCD(Script): except: continue data[num] = layer - setting_data = "" if bool(self.getSettingValueByKey("enable_end_message")): message_str = self.message_to_user(speed_factor) Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() From a8849f7081ca8c84a85469f225ed3c0cf464fb79 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:26:43 -0500 Subject: [PATCH 07/25] Update DisplayInfoOnLCD.py Added a condition so the pause_cmd setting box is hidden unless the 'display_option' == "display_progress". --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 38649ed6ce..399578fef5 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -210,7 +210,7 @@ class DisplayInfoOnLCD(Script): "description": "This might be M0, or M25 or M600 if Filament Change is used. If you have mixed commands then delimit them with a comma ',' (Ex: M0,M600). Spaces are not allowed.", "type": "str", "default_value": "M0", - "enabled": "countdown_to_pause and enable_countdown and display_remaining_time" + "enabled": "display_option == 'display_progress' and countdown_to_pause and enable_countdown and display_remaining_time" }, "enable_end_message": { From 02847714302bd026de3ddd7a50e8c47b1bb90ec5 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 11 Jan 2025 10:12:42 -0500 Subject: [PATCH 08/25] Update DisplayInfoOnLCD.py Split functions from Execute. Added function "Add Settings" so it also works with the "filename_layer" option. --- .../scripts/DisplayInfoOnLCD.py | 688 +++++++++--------- 1 file changed, 358 insertions(+), 330 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 399578fef5..2177f91f3b 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -1,32 +1,35 @@ -# Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 -# Modified: Joshua Pope-Lewis on November 16, 2018 -# Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 -# Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. -#--------------------------------------------------------------- -# DisplayNameOrProgressOnLCD.py -# Cura Post-Process plugin -# Combines 'Display Filename and Layer on the LCD' with 'Display Progress' -# Combined and with additions by: GregValiant (Greg Foresi) -# Date: September 8, 2023 -# Date: March 31, 2024 - Bug fix for problem with adding M118 lines if 'Remaining Time' was not checked. -# NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete -# Description: Display Filename and Layer options: -# Status messages sent to the printer... -# - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. -# - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here -# - Start Num: Choose which number you prefer for the initial layer, 0 or 1 -# - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) -# - Add prefix 'Printing': Enabling this will add the prefix 'Printing' -# - Example Line on LCD: Printing Layer 0 of 395 3DBenchy -# Display Progress options: -# - Display Total Layer Count -# - Disply Time Remaining for the print -# - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). -# - Example line on LCD: 1/479 | ET 2h13m -# - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m -# - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. -# - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) -# - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It takes into account the Time Fudge Factor. The user may enter a print start time. This is also available for Display Filename. +""" +Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 + Modified: Joshua Pope-Lewis on November 16, 2018 + Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 + Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. +--------------------------------------------------------------- + DisplayNameOrProgressOnLCD.py + Cura Post-Process plugin + Combines 'Display Filename and Layer on the LCD' with 'Display Progress' + Combined and with additions by: GregValiant (Greg Foresi) + Date: September 8, 2023 + Date: March 31, 2024 - Bug fix for problem with adding M118 lines if 'Remaining Time' was not checked. + NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete + Description: Display Filename and Layer options: + Status messages sent to the printer... + - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. + - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here + - Start Num: Choose which number you prefer for the initial layer, 0 or 1 + - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) + - Add prefix 'Printing': Enabling this will add the prefix 'Printing' + - Example Line on LCD: Printing Layer 0 of 395 3DBenchy + Display Progress options: + - Display Total Layer Count + - Disply Time Remaining for the print + - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. + This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). + - Example line on LCD: 1/479 | ET 2h13m + - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m + - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. + - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) + - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. +""" from ..Script import Script from UM.Application import Application @@ -47,7 +50,7 @@ class DisplayInfoOnLCD(Script): self._instance.setProperty("enable_countdown", "value", enable_countdown) except: pass - + def getSettingDataString(self): return """{ "name": "Display Info on LCD", @@ -234,308 +237,301 @@ class DisplayInfoOnLCD(Script): def execute(self, data): display_option = self.getSettingValueByKey("display_option") - add_m117_line = self.getSettingValueByKey("add_m117_line") - add_m118_line = self.getSettingValueByKey("add_m118_line") - add_m118_a1 = self.getSettingValueByKey("add_m118_a1") - add_m118_p0 = self.getSettingValueByKey("add_m118_p0") - m118_str = "M118 " - m118_text = "M118 " - add_m73_line = self.getSettingValueByKey("add_m73_line") - add_m73_time = self.getSettingValueByKey("add_m73_time") - add_m73_percent = self.getSettingValueByKey("add_m73_percent") - m73_str = "" - - # This is from the original Display Filename and Layer on LCD + self.add_m117_line = self.getSettingValueByKey("add_m117_line") + self.add_m118_line = self.getSettingValueByKey("add_m118_line") + self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") + self.add_m118_p0 = self.getSettingValueByKey("add_m118_p0") + self.m118_str = "M118 " + self.m118_text = "M118 " + self.add_m73_line = self.getSettingValueByKey("add_m73_line") + self.add_m73_time = self.getSettingValueByKey("add_m73_time") + self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") + self.m73_str = "" if display_option == "filename_layer": - max_layer = 0 - lcd_text = "M117 " - octo_text = "M118 " - if self.getSettingValueByKey("file_name") != "": - file_name = self.getSettingValueByKey("file_name") - else: - file_name = Application.getInstance().getPrintInformation().jobName - if self.getSettingValueByKey("addPrefixPrinting"): - lcd_text += "Printing " - octo_text += "Printing " - if not self.getSettingValueByKey("scroll"): - lcd_text += "Lay " - octo_text += "Layer " - else: - lcd_text += file_name + " - Layer " - octo_text += file_name + " - Layer " - i = self.getSettingValueByKey("startNum") - for layer in data: - display_text = lcd_text + str(i) - m118_text = octo_text + str(i) - layer_index = data.index(layer) - lines = layer.split("\n") - for line in lines: - if line.startswith(";LAYER_COUNT:"): - max_layer = line - max_layer = max_layer.split(":")[1] - if self.getSettingValueByKey("startNum") == 0: - max_layer = str(int(max_layer) - 1) - if line.startswith(";LAYER:"): - if self.getSettingValueByKey("maxlayer"): - display_text += "/" + max_layer - m118_text += "/" + max_layer - if not self.getSettingValueByKey("scroll"): - display_text += "|" + file_name - m118_text += " | " + file_name - else: - if not self.getSettingValueByKey("scroll"): - display_text += "|" + file_name + "!" - m118_text += " | " + file_name + "!" - else: - display_text += "!" - m118_text += "!" - line_index = lines.index(line) - if add_m117_line: - lines.insert(line_index + 1, display_text) - if add_m118_line: - if not (add_m118_p0 and add_m118_a1): - m118_str = m118_text - if add_m118_a1 and not add_m118_p0: - m118_str = m118_text.replace("M118 ","M118 A1 ") - if add_m118_p0 and not add_m118_a1: - m118_str = m118_text.replace("M118 ","M118 P0 ") - if add_m118_p0 and add_m118_a1: - m118_str = m118_text.replace("M118 ","M118 A1 P0 ") - lines.insert(line_index + 2, m118_str) - i += 1 - final_lines = "\n".join(lines) - data[layer_index] = final_lines - if bool(self.getSettingValueByKey("enable_end_message")): - message_str = self.message_to_user(self.getSettingValueByKey("speed_factor") / 100) - Message(title = "Display Info on LCD - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() - return data - - # This is from 'Show Progress on LCD' - elif display_option == "display_progress": - global_stack = Application.getInstance().getGlobalContainerStack() - print_sequence = global_stack.getProperty("print_sequence", "value") - # Add the Initial Layer Height just below Layer Height in data[0] - extruder_count = global_stack.getProperty("machine_extruder_count", "value") - init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size T0: " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament type for T0: " + str(global_stack.extruderList[0].getProperty("material_type", "value")) - if extruder_count > 1: - nozzle_size_line += "\n;Nozzle Size T1: " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type for T1: " + str(global_stack.extruderList[1].getProperty("material_type", "value")) - lines = data[0].split("\n") - for index, line in enumerate(lines): - if line.startswith(";Layer height:"): - lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line - if line.startswith(";Filament used"): - lines[index] += filament_type - data[0] = "\n".join(lines) - # Get settings - display_total_layers = self.getSettingValueByKey("display_total_layers") - display_remaining_time = self.getSettingValueByKey("display_remaining_time") - speed_factor = self.getSettingValueByKey("speed_factor") / 100 - m73_time = False - m73_percent = False - if add_m73_line and add_m73_time: - m73_time = True - if add_m73_line and add_m73_percent: - m73_percent = True - if add_m73_line: - data[1] = "M75\n" + data[1] - data[len(data)-1] += "M77\n" - # Initialize some variables - first_layer_index = 0 - time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) - number_of_layers = 0 - time_elapsed = 0 - - # If at least one of the settings is disabled, there is enough room on the display to display "layer" - first_section = data[0] - lines = first_section.split("\n") + data = self._display_filename_layer(data) + else: + data = self._display_progress(data) + return data + # This is from the original 'Display Filename and Layer on LCD' + def _display_filename_layer(self, data: str) -> str: + data[0] = self._add_stats(data) + max_layer = 0 + lcd_text = "M117 " + octo_text = "M118 " + if self.getSettingValueByKey("file_name") != "": + file_name = self.getSettingValueByKey("file_name") + else: + file_name = Application.getInstance().getPrintInformation().jobName + if self.getSettingValueByKey("addPrefixPrinting"): + lcd_text += "Printing " + octo_text += "Printing " + if not self.getSettingValueByKey("scroll"): + lcd_text += "Lay " + octo_text += "Layer " + else: + lcd_text += file_name + " - Layer " + octo_text += file_name + " - Layer " + i = self.getSettingValueByKey("startNum") + for layer in data: + display_text = lcd_text + str(i) + self.m118_text = octo_text + str(i) + layer_index = data.index(layer) + lines = layer.split("\n") for line in lines: - if line.startswith(";TIME:"): - tindex = lines.index(line) - cura_time = int(line.split(":")[1]) - print_time = cura_time * speed_factor - hhh = print_time/3600 - hr = round(hhh // 1) - mmm = round((hhh % 1) * 60) - orig_hhh = cura_time/3600 - orig_hr = round(orig_hhh // 1) - orig_mmm = math.floor((orig_hhh % 1) * 60) - if add_m118_line: lines.insert(tindex + 6,"M118 Adjusted Print Time " + str(hr) + "hr " + str(mmm) + "min") - if add_m117_line: lines.insert(tindex + 6,"M117 ET " + str(hr) + "hr " + str(mmm) + "min") - # Add M73 line at beginning - mins = int(60 * hr + mmm) - if add_m73_line and (add_m73_time or add_m73_percent): - if m73_time: - m73_str += " R{}".format(mins) - if m73_percent: - m73_str += " P0" - lines.insert(tindex + 4, "M73" + m73_str) - # If Countdown to pause is enabled then count the pauses - pause_str = "" - if bool(self.getSettingValueByKey("countdown_to_pause")): - pause_count = 0 - pause_setting = self.getSettingValueByKey("pause_cmd").upper() - if pause_setting != "": - pause_cmd = [] - if "," in pause_setting: - pause_cmd = pause_setting.split(",") - else: - pause_cmd.append(pause_setting) - for q in range(0, len(pause_cmd)): - pause_cmd[q] = "\n" + pause_cmd[q] - for num in range(2,len(data) - 2, 1): - for q in range(0,len(pause_cmd)): - if pause_cmd[q] in data[num]: - pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) - pause_str = f"with {pause_count} pause(s)" - else: - pause_str = "" - # This line goes in to convert seconds to hours and minutes - lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") - data[0] = "\n".join(lines) - if add_m117_line: - data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" - if add_m118_line: - data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" - if not display_total_layers or not display_remaining_time: - base_display_text = "layer " - else: - base_display_text = "" - layer = data[len(data)-1] - data[len(data)-1] = layer.replace(";End of Gcode" + "\n", "") - data[len(data)-1] += ";End of Gcode" + "\n" - # Search for the number of layers and the total time from the start code - for index in range(len(data)): - data_section = data[index] - # We have everything we need, save the index of the first layer and exit the loop - if ";LAYER:" in data_section: - first_layer_index = index - break - else: - for line in data_section.split("\n"): - if line.startswith(";LAYER_COUNT:"): - number_of_layers = int(line.split(":")[1]) - if print_sequence == "one_at_a_time": - number_of_layers = 1 - for lay in range(2,len(data)-1,1): - if ";LAYER:" in data[lay]: - number_of_layers += 1 - elif line.startswith(";TIME:"): - time_total = int(line.split(":")[1]) - # for all layers... - current_layer = 0 - for layer_counter in range(len(data)-2): - current_layer += 1 - layer_index = first_layer_index + layer_counter - display_text = base_display_text - display_text += str(current_layer) - # create a list where each element is a single line of code within the layer - lines = data[layer_index].split("\n") - if not ";LAYER:" in data[layer_index]: - current_layer -= 1 - continue - # add the total number of layers if this option is checked - if display_total_layers: - display_text += "/" + str(number_of_layers) - # if display_remaining_time is checked, it is calculated in this loop - if display_remaining_time: - time_remaining_display = " | ET " # initialize the time display - m = (time_total - time_elapsed) // 60 # estimated time in minutes - m *= speed_factor # correct for printing time - m = int(m) - h, m = divmod(m, 60) # convert to hours and minutes - # add the time remaining to the display_text - if h > 0: # if it's more than 1 hour left, display format = xhxxm - time_remaining_display += str(h) + "h" - if m < 10: # add trailing zero if necessary - time_remaining_display += "0" - time_remaining_display += str(m) + "m" + if line.startswith(";LAYER_COUNT:"): + max_layer = line + max_layer = max_layer.split(":")[1] + if self.getSettingValueByKey("startNum") == 0: + max_layer = str(int(max_layer) - 1) + if line.startswith(";LAYER:"): + if self.getSettingValueByKey("maxlayer"): + display_text += "/" + max_layer + self.m118_text += "/" + max_layer + if not self.getSettingValueByKey("scroll"): + display_text += "|" + file_name + self.m118_text += " | " + file_name else: - time_remaining_display += str(m) + "m" - display_text += time_remaining_display - # find time_elapsed at the end of the layer (used to calculate the remaining time of the next layer) - if not current_layer == number_of_layers: - for line_index in range(len(lines) - 1, -1, -1): - line = lines[line_index] - if line.startswith(";TIME_ELAPSED:"): - # update time_elapsed for the NEXT layer and exit the loop - time_elapsed = int(float(line.split(":")[1])) - break - # insert the text AFTER the first line of the layer (in case other scripts use ";LAYER:") - for l_index, line in enumerate(lines): - if line.startswith(";LAYER:"): - if add_m117_line: - lines[l_index] += "\nM117 " + display_text - if add_m118_line: - a1_str = "" - p0_str = "" - if add_m118_a1: - a1_str = "A1 " - if add_m118_p0: - p0_str = "P0 " - lines[l_index] += "\nM118 " + a1_str + p0_str + display_text - # add M73 line - if display_remaining_time: - mins = int(60 * h + m) - if add_m73_line and (add_m73_time or add_m73_percent): - m73_str = "" - if m73_time and display_remaining_time: - m73_str += " R{}".format(mins) - if m73_percent: - m73_str += " P" + str(round(int(current_layer) / int(number_of_layers) * 100)) - lines[l_index] += "\nM73" + m73_str - break - # overwrite the layer with the modified layer - data[layer_index] = "\n".join(lines) - - # If enabled then change the ET to TP for 'Time To Pause' - if bool(self.getSettingValueByKey("countdown_to_pause")): - time_list = [] - time_list.append("0") - time_list.append("0") - this_time = 0 - pause_index = 1 - - # Get the layer times - for num in range(2,len(data) - 1): - layer = data[num] - lines = layer.split("\n") - for line in lines: - if line.startswith(";TIME_ELAPSED:"): - this_time = (float(line.split(":")[1]))*speed_factor - time_list.append(str(this_time)) - for p_cmd in pause_cmd: - if p_cmd in layer: - for qnum in range(num - 1, pause_index, -1): - time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" - pause_index = num-1 - break - - # Make the adjustments to the M117 (and M118) lines that are prior to a pause - for num in range (2, len(data) - 1,1): - layer = data[num] - lines = layer.split("\n") - for line in lines: - try: - if line.startswith("M117") and "|" in line and "P" in time_list[num]: - time_to_go = self.get_time_to_go(time_list[num]) - M117_line = line.split("|")[0] + "| TP " + time_to_go - layer = layer.replace(line, M117_line) - if line.startswith("M118") and "|" in line and "P" in time_list[num]: - time_to_go = self.get_time_to_go(time_list[num]) - M118_line = line.split("|")[0] + "| TP " + time_to_go - layer = layer.replace(line, M118_line) - except: - continue - data[num] = layer - if bool(self.getSettingValueByKey("enable_end_message")): - message_str = self.message_to_user(speed_factor) - Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() + if not self.getSettingValueByKey("scroll"): + display_text += "|" + file_name + "!" + self.m118_text += " | " + file_name + "!" + else: + display_text += "!" + self.m118_text += "!" + line_index = lines.index(line) + if self.add_m117_line: + lines.insert(line_index + 1, display_text) + if self.add_m118_line: + if not (self.add_m118_p0 and self.add_m118_a1): + self.m118_str = self.m118_text + if self.add_m118_a1 and not self.add_m118_p0: + self.m118_str = self.m118_text.replace("M118 ","M118 A1 ") + if self.add_m118_p0 and not self.add_m118_a1: + self.m118_str = self.m118_text.replace("M118 ","M118 P0 ") + if self.add_m118_p0 and self.add_m118_a1: + self.m118_str = self.m118_text.replace("M118 ","M118 A1 P0 ") + lines.insert(line_index + 2, self.m118_str) + i += 1 + final_lines = "\n".join(lines) + data[layer_index] = final_lines + if bool(self.getSettingValueByKey("enable_end_message")): + message_str = self._message_to_user(self.getSettingValueByKey("speed_factor") / 100) + Message(title = "Display Info on LCD - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() return data - def message_to_user(self, speed_factor: float): + # This is from 'Show Progress on LCD' + def _display_progress(self, data: str) -> str: + # Add some print settings to the start of the gcode + data[0] = self._add_stats(data) + # Get settings + print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") + display_total_layers = self.getSettingValueByKey("display_total_layers") + display_remaining_time = self.getSettingValueByKey("display_remaining_time") + speed_factor = self.getSettingValueByKey("speed_factor") / 100 + m73_time = False + m73_percent = False + if self.add_m73_line and self.add_m73_time: + m73_time = True + if self.add_m73_line and self.add_m73_percent: + m73_percent = True + if self.add_m73_line: + data[1] = "M75\n" + data[1] + data[len(data)-1] += "M77\n" + # Initialize some variables + first_layer_index = 0 + time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) + number_of_layers = 0 + time_elapsed = 0 + + # If at least one of the settings is disabled, there is enough room on the display to display "layer" + first_section = data[0] + lines = first_section.split("\n") + for line in lines: + if line.startswith(";TIME:"): + tindex = lines.index(line) + cura_time = int(line.split(":")[1]) + print_time = cura_time * speed_factor + hhh = print_time/3600 + hr = round(hhh // 1) + mmm = round((hhh % 1) * 60) + orig_hhh = cura_time/3600 + orig_hr = round(orig_hhh // 1) + orig_mmm = math.floor((orig_hhh % 1) * 60) + if self.add_m118_line: + lines.insert(len(lines) - 2, f"M118 Adjusted Print Time: {hr} hr {mmm} min") + if self.add_m117_line: + lines.insert(len(lines) - 2, f"M117 ET {hr} hr {mmm} min") + # Add M73 line at beginning + mins = int(60 * hr + mmm) + if self.add_m73_line and (self.add_m73_time or self.add_m73_percent): + if m73_time: + self.m73_str += " R{}".format(mins) + if m73_percent: + self.m73_str += " P0" + lines.insert(tindex + 4, "M73" + self.m73_str) + # If Countdown to pause is enabled then count the pauses + pause_str = "" + if bool(self.getSettingValueByKey("countdown_to_pause")): + pause_count = 0 + pause_setting = self.getSettingValueByKey("pause_cmd").upper() + if pause_setting != "": + pause_cmd = [] + if "," in pause_setting: + pause_cmd = pause_setting.split(",") + else: + pause_cmd.append(pause_setting) + for q in range(0, len(pause_cmd)): + pause_cmd[q] = "\n" + pause_cmd[q] + for num in range(2,len(data) - 2, 1): + for q in range(0,len(pause_cmd)): + if pause_cmd[q] in data[num]: + pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) + pause_str = f"with {pause_count} pause(s)" + else: + pause_str = "" + # This line goes in to convert seconds to hours and minutes + lines.insert(tindex + 1, f";Cura Time Estimate: {orig_hr}hr {orig_mmm}min {pause_str}") + data[0] = "\n".join(lines) + if self.add_m117_line: + data[len(data)-1] += "M117 Orig Cura Est " + str(orig_hr) + "hr " + str(orig_mmm) + "min\n" + if self.add_m118_line: + data[len(data)-1] += "M118 Est w/FudgeFactor " + str(speed_factor * 100) + "% was " + str(hr) + "hr " + str(mmm) + "min\n" + if not display_total_layers or not display_remaining_time: + base_display_text = "layer " + else: + base_display_text = "" + layer = data[len(data)-1] + data[len(data)-1] = layer.replace(";End of Gcode" + "\n", "") + data[len(data)-1] += ";End of Gcode" + "\n" + # Search for the number of layers and the total time from the start code + for index in range(len(data)): + data_section = data[index] + # We have everything we need, save the index of the first layer and exit the loop + if ";LAYER:" in data_section: + first_layer_index = index + break + else: + for line in data_section.split("\n"): + if line.startswith(";LAYER_COUNT:"): + number_of_layers = int(line.split(":")[1]) + if print_sequence == "one_at_a_time": + number_of_layers = 1 + for lay in range(2,len(data)-1,1): + if ";LAYER:" in data[lay]: + number_of_layers += 1 + elif line.startswith(";TIME:"): + time_total = int(line.split(":")[1]) + # for all layers... + current_layer = 0 + for layer_counter in range(len(data)-2): + current_layer += 1 + layer_index = first_layer_index + layer_counter + display_text = base_display_text + display_text += str(current_layer) + # create a list where each element is a single line of code within the layer + lines = data[layer_index].split("\n") + if not ";LAYER:" in data[layer_index]: + current_layer -= 1 + continue + # add the total number of layers if this option is checked + if display_total_layers: + display_text += "/" + str(number_of_layers) + # if display_remaining_time is checked, it is calculated in this loop + if display_remaining_time: + time_remaining_display = " | ET " # initialize the time display + m = (time_total - time_elapsed) // 60 # estimated time in minutes + m *= speed_factor # correct for printing time + m = int(m) + h, m = divmod(m, 60) # convert to hours and minutes + # add the time remaining to the display_text + if h > 0: # if it's more than 1 hour left, display format = xhxxm + time_remaining_display += str(h) + "h" + if m < 10: # add trailing zero if necessary + time_remaining_display += "0" + time_remaining_display += str(m) + "m" + else: + time_remaining_display += str(m) + "m" + display_text += time_remaining_display + # find time_elapsed at the end of the layer (used to calculate the remaining time of the next layer) + if not current_layer == number_of_layers: + for line_index in range(len(lines) - 1, -1, -1): + line = lines[line_index] + if line.startswith(";TIME_ELAPSED:"): + # update time_elapsed for the NEXT layer and exit the loop + time_elapsed = int(float(line.split(":")[1])) + break + # insert the text AFTER the first line of the layer (in case other scripts use ";LAYER:") + for l_index, line in enumerate(lines): + if line.startswith(";LAYER:"): + if self.add_m117_line: + lines[l_index] += "\nM117 " + display_text + if self.add_m118_line: + a1_str = "" + p0_str = "" + if self.add_m118_a1: + a1_str = "A1 " + if self.add_m118_p0: + p0_str = "P0 " + lines[l_index] += "\nM118 " + a1_str + p0_str + display_text + # add M73 line + if display_remaining_time: + mins = int(60 * h + m) + if self.add_m73_line and (self.add_m73_time or self.add_m73_percent): + self.m73_str = "" + if m73_time and display_remaining_time: + self.m73_str += " R{}".format(mins) + if m73_percent: + self.m73_str += " P" + str(round(int(current_layer) / int(number_of_layers) * 100)) + lines[l_index] += "\nM73" + self.m73_str + break + # overwrite the layer with the modified layer + data[layer_index] = "\n".join(lines) + + # If enabled then change the ET to TP for 'Time To Pause' + if bool(self.getSettingValueByKey("countdown_to_pause")): + time_list = [] + time_list.append("0") + time_list.append("0") + this_time = 0 + pause_index = 1 + + # Get the layer times + for num in range(2,len(data) - 1): + layer = data[num] + lines = layer.split("\n") + for line in lines: + if line.startswith(";TIME_ELAPSED:"): + this_time = (float(line.split(":")[1]))*speed_factor + time_list.append(str(this_time)) + for p_cmd in pause_cmd: + if p_cmd in layer: + for qnum in range(num - 1, pause_index, -1): + time_list[qnum] = str(float(this_time) - float(time_list[qnum])) + "P" + pause_index = num-1 + break + + # Make the adjustments to the M117 (and M118) lines that are prior to a pause + for num in range (2, len(data) - 1,1): + layer = data[num] + lines = layer.split("\n") + for line in lines: + try: + if line.startswith("M117") and "|" in line and "P" in time_list[num]: + time_to_go = self._get_time_to_go(time_list[num]) + M117_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M117_line) + if line.startswith("M118") and "|" in line and "P" in time_list[num]: + time_to_go = self._get_time_to_go(time_list[num]) + M118_line = line.split("|")[0] + "| TP " + time_to_go + layer = layer.replace(line, M118_line) + except: + continue + data[num] = layer + if bool(self.getSettingValueByKey("enable_end_message")): + message_str = self._message_to_user(speed_factor) + Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() + return data + + def _message_to_user(self, speed_factor: float): # Message the user of the projected finish time of the print print_time = Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601) print_start_time = self.getSettingValueByKey("print_start_time") @@ -600,8 +596,8 @@ class DisplayInfoOnLCD(Script): adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) return finish_str, estimate_str, adjusted_str, print_start_str - - def get_time_to_go(self, time_str: str): + + def _get_time_to_go(self, time_str: str): alt_time = time_str[:-1] hhh = int(float(alt_time) / 3600) if hhh > 0: @@ -613,4 +609,36 @@ class DisplayInfoOnLCD(Script): mmm = str(round(mmm)) + "m" time_to_go = str(hhr) + str(mmm) if hhr == "": time_to_go = time_to_go + str(sss) + "s" - return time_to_go \ No newline at end of file + return time_to_go + + def _add_stats(self, data: str) -> str: + global_stack = Application.getInstance().getGlobalContainerStack() + # Create a list of the models in the file + model_list = [] + for mdex, layer in enumerate(data): + layer = data[mdex].split("\n") + for line in layer: + if line.startswith(";MESH:") and "NONMESH" not in line: + model_name = line.split(":")[1] + if not model_name in model_list: + model_list.append(model_name) + # Add the Initial Layer Height just below Layer Height in data[0]model_list = [] + extruder_count = global_stack.getProperty("machine_extruder_count", "value") + init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) + nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) + filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].getProperty("material_type", "value")) + print_temperature_line = ";Print Temperature (T0): " + str(global_stack.extruderList[0].getProperty("material_print_temperature", "value")) + if extruder_count > 1: + nozzle_size_line += "\n;Nozzle Size (T1): " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) + filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].getProperty("material_type", "value")) + print_temperature_line += "\n;Print Temperature (T1): " + str(global_stack.extruderList[1].getProperty("material_print_temperature", "value")) + lines = data[0].split("\n") + for index, line in enumerate(lines): + if line.startswith(";Layer height:"): + lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line + "\n" + print_temperature_line + if line.startswith(";Filament used"): + lines[index] += filament_type + if "MINX" in line or "MIN.X" in line: + # Add the model list + lines[index - 1] += f"\n;Model List: {str(model_list)}" + return "\n".join(lines) \ No newline at end of file From 017a05fff7067a4f8740c482dc2dd6da1cc0ddc1 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 2 Feb 2025 08:02:59 -0500 Subject: [PATCH 09/25] Update DisplayInfoOnLCD.py Changed the fialment type 'get' from: 'getProperty' to 'material.getMetaDataEntry' --- .../PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 2177f91f3b..b19f222f2a 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -202,7 +202,7 @@ class DisplayInfoOnLCD(Script): "countdown_to_pause": { "label": "Countdown to Pauses", - "description": "This must run AFTER any script that adds a pause. Instead of the remaining print time the LCD will show the estimated time to the next layer that has a pause (TP).", + "description": "This must run AFTER any script that adds a pause. Instead of the remaining print time the LCD will show the estimated time to the next layer that has a pause (TP). Countdown to Pause is not available when in One-at-a-Time' mode.", "type": "bool", "default_value": false, "enabled": "display_option == 'display_progress' and enable_countdown and display_remaining_time" @@ -252,7 +252,8 @@ class DisplayInfoOnLCD(Script): else: data = self._display_progress(data) return data - # This is from the original 'Display Filename and Layer on LCD' + + # This is from the original 'Display Filename and Layer on LCD' def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) max_layer = 0 @@ -385,7 +386,7 @@ class DisplayInfoOnLCD(Script): for q in range(0,len(pause_cmd)): if pause_cmd[q] in data[num]: pause_count += data[num].count(pause_cmd[q], 0, len(data[num])) - pause_str = f"with {pause_count} pause(s)" + pause_str = f"with {pause_count} pause" + ("s" if pause_count > 1 else "") else: pause_str = "" # This line goes in to convert seconds to hours and minutes @@ -626,11 +627,11 @@ class DisplayInfoOnLCD(Script): extruder_count = global_stack.getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].getProperty("material_type", "value")) + filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].material.getMetaDataEntry("material", "")) print_temperature_line = ";Print Temperature (T0): " + str(global_stack.extruderList[0].getProperty("material_print_temperature", "value")) if extruder_count > 1: nozzle_size_line += "\n;Nozzle Size (T1): " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].getProperty("material_type", "value")) + filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].material.getMetaDataEntry("material", "")) print_temperature_line += "\n;Print Temperature (T1): " + str(global_stack.extruderList[1].getProperty("material_print_temperature", "value")) lines = data[0].split("\n") for index, line in enumerate(lines): From 416b159a7ea3c82516aaf88cf6cd145fb1d2e921 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 22 Mar 2025 11:18:30 -0400 Subject: [PATCH 10/25] Update DisplayInfoOnLCD.py Added the "time to pause" to the user message. Update DisplayInfoOnLCD.py update --- .../scripts/DisplayInfoOnLCD.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index b19f222f2a..49222882bc 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -488,8 +488,8 @@ class DisplayInfoOnLCD(Script): data[layer_index] = "\n".join(lines) # If enabled then change the ET to TP for 'Time To Pause' + time_list = [] if bool(self.getSettingValueByKey("countdown_to_pause")): - time_list = [] time_list.append("0") time_list.append("0") this_time = 0 @@ -528,11 +528,11 @@ class DisplayInfoOnLCD(Script): continue data[num] = layer if bool(self.getSettingValueByKey("enable_end_message")): - message_str = self._message_to_user(speed_factor) + message_str = self._message_to_user(data, speed_factor, pause_cmd) Message(title = "[Display Info on LCD] - Estimated Finish Time", text = message_str[0] + "\n\n" + message_str[1] + "\n" + message_str[2] + "\n" + message_str[3]).show() return data - def _message_to_user(self, speed_factor: float): + def _message_to_user(self, data: str, speed_factor: float, pause_cmd: str) -> str: # Message the user of the projected finish time of the print print_time = Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601) print_start_time = self.getSettingValueByKey("print_start_time") @@ -596,6 +596,15 @@ class DisplayInfoOnLCD(Script): estimate_str = "Cura Time Estimate.........." + str(print_time) adjusted_str = "Adjusted Time Estimate..." + str(time_change) finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) + + # If there are pauses and if countdown is enabled, then add the time-to-pause to the message. + if bool(self.getSettingValueByKey("countdown_to_pause")): + num = 1 + for layer in data: + for p_cmd in pause_cmd: + if p_cmd in layer or "Do the actual pause" in layer: + adjusted_str += "\n" + self._get_time_to_go(layer.split("TIME_ELAPSED:")[1].split("\n")[0]) + " ET from start to pause #" + str(num) + num += 1 return finish_str, estimate_str, adjusted_str, print_start_str def _get_time_to_go(self, time_str: str): @@ -623,7 +632,7 @@ class DisplayInfoOnLCD(Script): model_name = line.split(":")[1] if not model_name in model_list: model_list.append(model_name) - # Add the Initial Layer Height just below Layer Height in data[0]model_list = [] + # Add some settings to data[0] extruder_count = global_stack.getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) From ee5c37bd808d4e15dea6306b5deaf0038f9885df Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 23 Mar 2025 07:09:04 -0400 Subject: [PATCH 11/25] Update DisplayInfoOnLCD.py Fixed the m118_str/m118_text confusion. --- .../scripts/DisplayInfoOnLCD.py | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 49222882bc..6315e28af1 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -241,7 +241,6 @@ class DisplayInfoOnLCD(Script): self.add_m118_line = self.getSettingValueByKey("add_m118_line") self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") self.add_m118_p0 = self.getSettingValueByKey("add_m118_p0") - self.m118_str = "M118 " self.m118_text = "M118 " self.add_m73_line = self.getSettingValueByKey("add_m73_line") self.add_m73_time = self.getSettingValueByKey("add_m73_time") @@ -302,15 +301,11 @@ class DisplayInfoOnLCD(Script): if self.add_m117_line: lines.insert(line_index + 1, display_text) if self.add_m118_line: - if not (self.add_m118_p0 and self.add_m118_a1): - self.m118_str = self.m118_text - if self.add_m118_a1 and not self.add_m118_p0: - self.m118_str = self.m118_text.replace("M118 ","M118 A1 ") - if self.add_m118_p0 and not self.add_m118_a1: - self.m118_str = self.m118_text.replace("M118 ","M118 P0 ") - if self.add_m118_p0 and self.add_m118_a1: - self.m118_str = self.m118_text.replace("M118 ","M118 A1 P0 ") - lines.insert(line_index + 2, self.m118_str) + if self.add_m118_a1: + self.m118_text = self.m118_text.replace("M118 ","M118 A1 ") + if self.add_m118_p0: + self.m118_text = self.m118_text.replace("M118 ","M118 P0 ") + lines.insert(line_index + 2, self.m118_text) i += 1 final_lines = "\n".join(lines) data[layer_index] = final_lines @@ -466,13 +461,12 @@ class DisplayInfoOnLCD(Script): if self.add_m117_line: lines[l_index] += "\nM117 " + display_text if self.add_m118_line: - a1_str = "" - p0_str = "" + m118_str = "\nM118 " if self.add_m118_a1: - a1_str = "A1 " + m118_str += "A1 " if self.add_m118_p0: - p0_str = "P0 " - lines[l_index] += "\nM118 " + a1_str + p0_str + display_text + m118_str += "P0 " + lines[l_index] += m118_str + display_text # add M73 line if display_remaining_time: mins = int(60 * h + m) From f0d198507a6acd7d1852eb06cecc8813eab96f43 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 23 Mar 2025 07:30:23 -0400 Subject: [PATCH 12/25] Update DisplayInfoOnLCD.py Requested changes --- .../scripts/DisplayInfoOnLCD.py | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 6315e28af1..85b9744856 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -38,7 +38,6 @@ import time import datetime import math from UM.Message import Message -import re class DisplayInfoOnLCD(Script): @@ -48,7 +47,11 @@ class DisplayInfoOnLCD(Script): if Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") == "all_at_once": enable_countdown = True self._instance.setProperty("enable_countdown", "value", enable_countdown) - except: + except AttributeError: + # Handle cases where the global container stack or its properties are not accessible + pass + except KeyError: + # Handle cases where the "print_sequence" property is missing pass def getSettingDataString(self): @@ -461,12 +464,12 @@ class DisplayInfoOnLCD(Script): if self.add_m117_line: lines[l_index] += "\nM117 " + display_text if self.add_m118_line: - m118_str = "\nM118 " + m118_text = "\nM118 " if self.add_m118_a1: - m118_str += "A1 " + m118_text += "A1 " if self.add_m118_p0: - m118_str += "P0 " - lines[l_index] += m118_str + display_text + m118_text += "P0 " + lines[l_index] += m118_text + display_text # add M73 line if display_remaining_time: mins = int(60 * h + m) @@ -589,7 +592,7 @@ class DisplayInfoOnLCD(Script): print_start_str = "Print Start Time.................Now" estimate_str = "Cura Time Estimate.........." + str(print_time) adjusted_str = "Adjusted Time Estimate..." + str(time_change) - finish_str = week_day + " " + str(mo_str) + " " + str(new_time.strftime("%d")) + ", " + str(new_time.strftime("%Y")) + " at " + str(show_hr) + str(new_time.strftime("%M")) + str(show_ampm) + finish_str = f"{week_day} {mo_str} {new_time.strftime('%d')}, {new_time.strftime('%Y')} at {show_hr}{new_time.strftime('%M')}{show_ampm}" # If there are pauses and if countdown is enabled, then add the time-to-pause to the message. if bool(self.getSettingValueByKey("countdown_to_pause")): @@ -602,17 +605,20 @@ class DisplayInfoOnLCD(Script): return finish_str, estimate_str, adjusted_str, print_start_str def _get_time_to_go(self, time_str: str): + """ + Converts a time string in seconds to a human-readable format (e.g., "2h30m"). + :param time_str: The time string in seconds. + :return: A formatted string representing the time. + """ alt_time = time_str[:-1] - hhh = int(float(alt_time) / 3600) - if hhh > 0: - hhr = str(hhh) + "h" - else: - hhr = "" - mmm = ((float(alt_time) / 3600) - (int(float(alt_time) / 3600))) * 60 - sss = int((mmm - int(mmm)) * 60) - mmm = str(round(mmm)) + "m" - time_to_go = str(hhr) + str(mmm) - if hhr == "": time_to_go = time_to_go + str(sss) + "s" + total_seconds = float(alt_time) + hours = int(total_seconds // 3600) + minutes = int((total_seconds % 3600) // 60) + seconds = int(total_seconds % 60) + time_to_go = f"{hours}h" if hours > 0 else "" + time_to_go += f"{minutes}m" + if hours == 0: + time_to_go += f"{seconds}s" return time_to_go def _add_stats(self, data: str) -> str: From e1246beb67966b035492bd217a93af532a4e0509 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 12 Apr 2025 14:11:09 -0400 Subject: [PATCH 13/25] Update DisplayInfoOnLCD.py Minor changes to the statistics added to the beginning of the gcode. --- .../scripts/DisplayInfoOnLCD.py | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 85b9744856..abff57c804 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -319,7 +319,7 @@ class DisplayInfoOnLCD(Script): # This is from 'Show Progress on LCD' def _display_progress(self, data: str) -> str: - # Add some print settings to the start of the gcode + # Add some common print settings to the start of the gcode data[0] = self._add_stats(data) # Get settings print_sequence = Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") @@ -344,6 +344,7 @@ class DisplayInfoOnLCD(Script): # If at least one of the settings is disabled, there is enough room on the display to display "layer" first_section = data[0] lines = first_section.split("\n") + pause_cmd = [] for line in lines: if line.startswith(";TIME:"): tindex = lines.index(line) @@ -530,7 +531,9 @@ class DisplayInfoOnLCD(Script): return data def _message_to_user(self, data: str, speed_factor: float, pause_cmd: str) -> str: - # Message the user of the projected finish time of the print + """ + Message the user of the projected finish time of the print and when any pauses might occur + """ print_time = Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601) print_start_time = self.getSettingValueByKey("print_start_time") # If the user entered a print start time make sure it is in the correct format or ignore it. @@ -623,7 +626,10 @@ class DisplayInfoOnLCD(Script): def _add_stats(self, data: str) -> str: global_stack = Application.getInstance().getGlobalContainerStack() - # Create a list of the models in the file + """ + Make a list of the models in the file. + Add some of the filament stats to the first section of the gcode. + """ model_list = [] for mdex, layer in enumerate(data): layer = data[mdex].split("\n") @@ -632,22 +638,34 @@ class DisplayInfoOnLCD(Script): model_name = line.split(":")[1] if not model_name in model_list: model_list.append(model_name) - # Add some settings to data[0] + # Filament stats extruder_count = global_stack.getProperty("machine_extruder_count", "value") init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) - nozzle_size_line = ";Nozzle Size (T0): " + str(global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")) - filament_type = "\n;Filament Type (T0): " + str(global_stack.extruderList[0].material.getMetaDataEntry("material", "")) - print_temperature_line = ";Print Temperature (T0): " + str(global_stack.extruderList[0].getProperty("material_print_temperature", "value")) + filament_line_t0 = ";Extruder 1 (T0)\n" + filament_amount = Application.getInstance().getPrintInformation().materialLengths + filament_line_t0 += f"; Filament used: {filament_amount[0]}m\n" + filament_line_t0 += f"; Filament Type: {global_stack.extruderList[0].material.getMetaDataEntry("material", "")}\n" + filament_line_t0 += f"; Filament Dia.: {global_stack.extruderList[0].getProperty("material_diameter", "value")}mm\n" + filament_line_t0 += f"; Nozzle Size : {global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")}mm\n" + filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°" + + # if there is more than one extruder then get the stats for the second one. + filament_line_t1 = "" if extruder_count > 1: - nozzle_size_line += "\n;Nozzle Size (T1): " + str(global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")) - filament_type += "\n;Filament type (T1): " + str(global_stack.extruderList[1].material.getMetaDataEntry("material", "")) - print_temperature_line += "\n;Print Temperature (T1): " + str(global_stack.extruderList[1].getProperty("material_print_temperature", "value")) + filament_line_t1 = "\n;Extruder 2 (T1)\n" + filament_line_t1 += f"; Filament used: {filament_amount[1]}m\n" + filament_line_t1 += f"; Filament Type: {global_stack.extruderList[1].material.getMetaDataEntry("material", "")}\n" + filament_line_t1 += f"; Filament Dia.: {global_stack.extruderList[1].getProperty("material_diameter", "value")}mm\n" + filament_line_t1 += f"; Nozzle Size : {global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")}mm\n" + filament_line_t1 += f"; Print Temp. : {global_stack.extruderList[1].getProperty("material_print_temperature", "value")}°" + + # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): - lines[index] += "\n" + init_layer_hgt_line + "\n" + nozzle_size_line + "\n" + print_temperature_line + lines[index] += "\n" + init_layer_hgt_line if line.startswith(";Filament used"): - lines[index] += filament_type + lines[index] = filament_line_t0 + filament_line_t1 if "MINX" in line or "MIN.X" in line: # Add the model list lines[index - 1] += f"\n;Model List: {str(model_list)}" From 1b518b8c926096d1835f50e64147d17b1cf6198b Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 12 Apr 2025 14:13:53 -0400 Subject: [PATCH 14/25] Update DisplayInfoOnLCD.py Changes to the print statistics entered into the gcode. --- .../scripts/DisplayInfoOnLCD.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index abff57c804..e68b4c92c8 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -1,5 +1,6 @@ """ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 +<<<<<<< Updated upstream Modified: Joshua Pope-Lewis on November 16, 2018 Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. @@ -29,6 +30,35 @@ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. +======= +Modified: Joshua Pope-Lewis on November 16, 2018 +Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 +Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. +--------------------------------------------------------------- +DisplayNameOrProgressOnLCD.py +Cura Post-Process plugin +Combines 'Display Filename and Layer on the LCD' with 'Display Progress' +Combined and with additions by: GregValiant (Greg Foresi) +Date: September 8, 2023 +NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete +Description: Display Filename and Layer options: + Status messages sent to the printer... + - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. + - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here + - Start Num: Choose which number you prefer for the initial layer, 0 or 1 + - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) + - Add prefix 'Printing': Enabling this will add the prefix 'Printing' + - Example Line on LCD: Printing Layer 0 of 395 3DBenchy + Display Progress options: + - Display Total Layer Count + - Disply Time Remaining for the print + - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). + - Example line on LCD: 1/479 | ET 2h13m + - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m + - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. + - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) + - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It takes into account the Time Fudge Factor. The user may enter a print start time. This is also available for Display Filename. +>>>>>>> Stashed changes """ from ..Script import Script @@ -240,6 +270,7 @@ class DisplayInfoOnLCD(Script): def execute(self, data): display_option = self.getSettingValueByKey("display_option") +<<<<<<< Updated upstream self.add_m117_line = self.getSettingValueByKey("add_m117_line") self.add_m118_line = self.getSettingValueByKey("add_m118_line") self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") @@ -249,12 +280,21 @@ class DisplayInfoOnLCD(Script): self.add_m73_time = self.getSettingValueByKey("add_m73_time") self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") self.m73_str = "" +======= + add_m118_line = self.getSettingValueByKey("add_m118_line") + add_m73_line = self.getSettingValueByKey("add_m73_line") + add_m73_time = self.getSettingValueByKey("add_m73_time") + add_m73_percent = self.getSettingValueByKey("add_m73_percent") + + # This is Display Filename and Layer on LCD +>>>>>>> Stashed changes if display_option == "filename_layer": data = self._display_filename_layer(data) else: data = self._display_progress(data) return data +<<<<<<< Updated upstream # This is from the original 'Display Filename and Layer on LCD' def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) @@ -280,6 +320,28 @@ class DisplayInfoOnLCD(Script): self.m118_text = octo_text + str(i) layer_index = data.index(layer) lines = layer.split("\n") +======= + # Display Progress (from 'Show Progress' and 'Display Progress on LCD') + elif display_option == "display_progress": + # get settings + display_total_layers = self.getSettingValueByKey("display_total_layers") + display_remaining_time = self.getSettingValueByKey("display_remaining_time") + speed_factor = self.getSettingValueByKey("speed_factor") / 100 + m73_time = False + m73_percent = False + if add_m73_line and add_m73_time: + m73_time = True + if add_m73_line and add_m73_percent: + m73_percent = True + # initialize global variables + first_layer_index = 0 + time_total = 0 + number_of_layers = 0 + time_elapsed = 0 + # if at least one of the settings is disabled, there is enough room on the display to display "layer" + first_section = data[0] + lines = first_section.split("\n") +>>>>>>> Stashed changes for line in lines: if line.startswith(";LAYER_COUNT:"): max_layer = line From bf8d31aa515e1be3a19525b689dec84fee7f7be9 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:04:34 -0400 Subject: [PATCH 15/25] Update DisplayInfoOnLCD.py Add the 'Quality Name' to the gcode with the other settings. Update DisplayInfoOnLCD.py Touchups. Update DisplayInfoOnLCD.py Minor change --- .../scripts/DisplayInfoOnLCD.py | 72 ++----------------- 1 file changed, 6 insertions(+), 66 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index e68b4c92c8..e016bbd3d6 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -1,6 +1,5 @@ """ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 -<<<<<<< Updated upstream Modified: Joshua Pope-Lewis on November 16, 2018 Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. @@ -30,35 +29,6 @@ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. -======= -Modified: Joshua Pope-Lewis on November 16, 2018 -Display Progress on LCD by Mathias Lyngklip Kjeldgaard, Alexander Gee, Kimmo Toivanen, Inigo Martinez on July 31, 2019 -Show Progress was adapted from Display Progress by Louis Wooters on January 6, 2020. His changes are included here. ---------------------------------------------------------------- -DisplayNameOrProgressOnLCD.py -Cura Post-Process plugin -Combines 'Display Filename and Layer on the LCD' with 'Display Progress' -Combined and with additions by: GregValiant (Greg Foresi) -Date: September 8, 2023 -NOTE: This combined post processor will make 'Display Filename and Layer on the LCD' and 'Display Progress' obsolete -Description: Display Filename and Layer options: - Status messages sent to the printer... - - Scrolling (SCROLL_LONG_FILENAMES) if enabled in Marlin and you aren't printing a small item select this option. - - Name: By default it will use the name generated by Cura (EG: TT_Test_Cube) - You may enter a custom name here - - Start Num: Choose which number you prefer for the initial layer, 0 or 1 - - Max Layer: Enabling this will show how many layers are in the entire print (EG: Layer 1 of 265!) - - Add prefix 'Printing': Enabling this will add the prefix 'Printing' - - Example Line on LCD: Printing Layer 0 of 395 3DBenchy - Display Progress options: - - Display Total Layer Count - - Disply Time Remaining for the print - - Time Fudge Factor % - Divide the Actual Print Time by the Cura Estimate. Enter as a percentage and the displayed time will be adjusted. This allows you to bring the displayed time closer to reality (Ex: Entering 87.5 would indicate an adjustment to 87.5% of the Cura estimate). - - Example line on LCD: 1/479 | ET 2h13m - - Time to Pauses changes the M117/M118 lines to countdown to the next pause as 1/479 | TP 2h36m - - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It takes into account the Time Fudge Factor. The user may enter a print start time. This is also available for Display Filename. ->>>>>>> Stashed changes """ from ..Script import Script @@ -270,7 +240,6 @@ class DisplayInfoOnLCD(Script): def execute(self, data): display_option = self.getSettingValueByKey("display_option") -<<<<<<< Updated upstream self.add_m117_line = self.getSettingValueByKey("add_m117_line") self.add_m118_line = self.getSettingValueByKey("add_m118_line") self.add_m118_a1 = self.getSettingValueByKey("add_m118_a1") @@ -280,21 +249,12 @@ class DisplayInfoOnLCD(Script): self.add_m73_time = self.getSettingValueByKey("add_m73_time") self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") self.m73_str = "" -======= - add_m118_line = self.getSettingValueByKey("add_m118_line") - add_m73_line = self.getSettingValueByKey("add_m73_line") - add_m73_time = self.getSettingValueByKey("add_m73_time") - add_m73_percent = self.getSettingValueByKey("add_m73_percent") - - # This is Display Filename and Layer on LCD ->>>>>>> Stashed changes if display_option == "filename_layer": data = self._display_filename_layer(data) else: data = self._display_progress(data) return data -<<<<<<< Updated upstream # This is from the original 'Display Filename and Layer on LCD' def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) @@ -320,28 +280,6 @@ class DisplayInfoOnLCD(Script): self.m118_text = octo_text + str(i) layer_index = data.index(layer) lines = layer.split("\n") -======= - # Display Progress (from 'Show Progress' and 'Display Progress on LCD') - elif display_option == "display_progress": - # get settings - display_total_layers = self.getSettingValueByKey("display_total_layers") - display_remaining_time = self.getSettingValueByKey("display_remaining_time") - speed_factor = self.getSettingValueByKey("speed_factor") / 100 - m73_time = False - m73_percent = False - if add_m73_line and add_m73_time: - m73_time = True - if add_m73_line and add_m73_percent: - m73_percent = True - # initialize global variables - first_layer_index = 0 - time_total = 0 - number_of_layers = 0 - time_elapsed = 0 - # if at least one of the settings is disabled, there is enough room on the display to display "layer" - first_section = data[0] - lines = first_section.split("\n") ->>>>>>> Stashed changes for line in lines: if line.startswith(";LAYER_COUNT:"): max_layer = line @@ -710,7 +648,7 @@ class DisplayInfoOnLCD(Script): filament_line_t0 += f"; Filament Dia.: {global_stack.extruderList[0].getProperty("material_diameter", "value")}mm\n" filament_line_t0 += f"; Nozzle Size : {global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")}mm\n" filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°" - + # if there is more than one extruder then get the stats for the second one. filament_line_t1 = "" if extruder_count > 1: @@ -720,15 +658,17 @@ class DisplayInfoOnLCD(Script): filament_line_t1 += f"; Filament Dia.: {global_stack.extruderList[1].getProperty("material_diameter", "value")}mm\n" filament_line_t1 += f"; Nozzle Size : {global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")}mm\n" filament_line_t1 += f"; Print Temp. : {global_stack.extruderList[1].getProperty("material_print_temperature", "value")}°" - + # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): - lines[index] += "\n" + init_layer_hgt_line + lines[index] += f"\n{init_layer_hgt_line}" + lines[index] += f"\n;Base Quality Name : '{global_stack.quality.getMetaDataEntry("name", "")}'" + lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" if line.startswith(";Filament used"): lines[index] = filament_line_t0 + filament_line_t1 if "MINX" in line or "MIN.X" in line: - # Add the model list + # Add the Object List lines[index - 1] += f"\n;Model List: {str(model_list)}" return "\n".join(lines) \ No newline at end of file From 61523062178e53c99651a8f6787302dc9c7cf468 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Thu, 22 May 2025 12:12:42 -0400 Subject: [PATCH 16/25] Update DisplayInfoOnLCD.py Made some changes to the print stats that are added to the gcode. Update DisplayInfoOnLCD.py --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index e016bbd3d6..0e3b52c81f 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -647,7 +647,8 @@ class DisplayInfoOnLCD(Script): filament_line_t0 += f"; Filament Type: {global_stack.extruderList[0].material.getMetaDataEntry("material", "")}\n" filament_line_t0 += f"; Filament Dia.: {global_stack.extruderList[0].getProperty("material_diameter", "value")}mm\n" filament_line_t0 += f"; Nozzle Size : {global_stack.extruderList[0].getProperty("machine_nozzle_size", "value")}mm\n" - filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°" + filament_line_t0 += f"; Print Temp. : {global_stack.extruderList[0].getProperty("material_print_temperature", "value")}°\n" + filament_line_t0 += f"; Bed Temp. : {global_stack.extruderList[0].getProperty("material_bed_temperature", "value")}°" # if there is more than one extruder then get the stats for the second one. filament_line_t1 = "" @@ -668,6 +669,11 @@ class DisplayInfoOnLCD(Script): lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" if line.startswith(";Filament used"): lines[index] = filament_line_t0 + filament_line_t1 + # The target machine "machine_name" is actually the printer model. This adds the user defined printer name to the "TARGET_MACHINE" line. + if line.startswith(";TARGET_MACHINE"): + machine_model = str(global_stack.getProperty("machine_name", "value")) + machine_name = str(global_stack.getName()) + lines[index] += f" / {machine_name}" if "MINX" in line or "MIN.X" in line: # Add the Object List lines[index - 1] += f"\n;Model List: {str(model_list)}" From e63243bca81e88655d09e3c20277f42315114216 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 7 Jun 2025 09:09:59 -0400 Subject: [PATCH 17/25] Update DisplayInfoOnLCD.py It turns out that some firmware doesn't like colons within M118 commands. --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 0e3b52c81f..89c76769c9 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -357,7 +357,7 @@ class DisplayInfoOnLCD(Script): orig_hr = round(orig_hhh // 1) orig_mmm = math.floor((orig_hhh % 1) * 60) if self.add_m118_line: - lines.insert(len(lines) - 2, f"M118 Adjusted Print Time: {hr} hr {mmm} min") + lines.insert(len(lines) - 2, f"M118 Adjusted Print Time is {hr} hr {mmm} min") if self.add_m117_line: lines.insert(len(lines) - 2, f"M117 ET {hr} hr {mmm} min") # Add M73 line at beginning From 3ad2c1b5788466412e17f23840deb9197ba9e19e Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Mon, 30 Jun 2025 21:39:03 -0400 Subject: [PATCH 18/25] Update DisplayInfoOnLCD.py Add "Electricity Cost" to the statistics added to the gcode. Update DisplayInfoOnLCD.py Formatting changes for layer heights --- .../scripts/DisplayInfoOnLCD.py | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index 89c76769c9..ddf292fb85 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -29,6 +29,7 @@ Display Filename and Layer on the LCD by Amanda de Castilho on August 28, 2018 - 'Add M118 Line' is available with either option. M118 will bounce the message back to a remote print server through the USB connection. - 'Add M73 Line' is used by 'Display Progress' only. There are options to incluse M73 P(percent) and M73 R(time remaining) - Enable 'Finish-Time' Message - when enabled, takes the Print Time and calculates when the print will end. It uses the Time Fudge Factor. The user may enter a print start time. +Date: June 30, 2025 Cost of electricity added to the other print statistics in '_add_stats'. """ from ..Script import Script @@ -37,6 +38,7 @@ from UM.Qt.Duration import DurationFormat import time import datetime import math +from UM.Preferences import Preferences from UM.Message import Message class DisplayInfoOnLCD(Script): @@ -234,7 +236,26 @@ class DisplayInfoOnLCD(Script): "default_value": "", "unit": "hrs ", "enabled": "enable_end_message" + }, + "electricity_cost": + { + "label": "Electricity Cost per kWh", + "description": "Cost of electricity per kilowatt-hour. This should be on your electric utility bill.", + "type": "float", + "default_value": 0.151, + "minimum_value": 0, + "unit": "€/kWh " + }, + "printer_power_usage": + { + "label": "Printer Power Usage", + "description": "Average power usage of the 3D printer in Watts. The actual wattage has many variables. 50% of the power supply rating would be a ballpark figure.", + "type": "float", + "default_value": 175, + "minimum_value": 0, + "unit": "Watts " } + } }""" @@ -249,6 +270,11 @@ class DisplayInfoOnLCD(Script): self.add_m73_time = self.getSettingValueByKey("add_m73_time") self.add_m73_percent = self.getSettingValueByKey("add_m73_percent") self.m73_str = "" + para_1 = data[0].split("\n") + for line in para_1: + if line.startswith(";TIME:"): + self.time_total = int(line.split(":")[1]) + break if display_option == "filename_layer": data = self._display_filename_layer(data) else: @@ -337,7 +363,6 @@ class DisplayInfoOnLCD(Script): data[len(data)-1] += "M77\n" # Initialize some variables first_layer_index = 0 - time_total = int(data[0].split(";TIME:")[1].split("\n")[0]) number_of_layers = 0 time_elapsed = 0 @@ -418,8 +443,6 @@ class DisplayInfoOnLCD(Script): for lay in range(2,len(data)-1,1): if ";LAYER:" in data[lay]: number_of_layers += 1 - elif line.startswith(";TIME:"): - time_total = int(line.split(":")[1]) # for all layers... current_layer = 0 for layer_counter in range(len(data)-2): @@ -438,7 +461,7 @@ class DisplayInfoOnLCD(Script): # if display_remaining_time is checked, it is calculated in this loop if display_remaining_time: time_remaining_display = " | ET " # initialize the time display - m = (time_total - time_elapsed) // 60 # estimated time in minutes + m = (self.time_total - time_elapsed) // 60 # estimated time in minutes m *= speed_factor # correct for printing time m = int(m) h, m = divmod(m, 60) # convert to hours and minutes @@ -640,7 +663,8 @@ class DisplayInfoOnLCD(Script): model_list.append(model_name) # Filament stats extruder_count = global_stack.getProperty("machine_extruder_count", "value") - init_layer_hgt_line = ";Initial Layer Height: " + str(global_stack.getProperty("layer_height_0", "value")) + layheight_0 = global_stack.getProperty("layer_height_0", "value") + init_layer_hgt_line = ";Initial Layer Height: " + f"{layheight_0:.2f}".format(layheight_0) filament_line_t0 = ";Extruder 1 (T0)\n" filament_amount = Application.getInstance().getPrintInformation().materialLengths filament_line_t0 += f"; Filament used: {filament_amount[0]}m\n" @@ -659,16 +683,23 @@ class DisplayInfoOnLCD(Script): filament_line_t1 += f"; Filament Dia.: {global_stack.extruderList[1].getProperty("material_diameter", "value")}mm\n" filament_line_t1 += f"; Nozzle Size : {global_stack.extruderList[1].getProperty("machine_nozzle_size", "value")}mm\n" filament_line_t1 += f"; Print Temp. : {global_stack.extruderList[1].getProperty("material_print_temperature", "value")}°" - + + # Calculate the cost of electricity for the print + electricity_cost = self.getSettingValueByKey("electricity_cost") + printer_power_usage = self.getSettingValueByKey("printer_power_usage") + currency_unit = Application.getInstance().getPreferences().getValue("cura/currency") + total_cost_electricity = (printer_power_usage / 1000) * (self.time_total / 3600) * electricity_cost + # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): if line.startswith(";Layer height:"): + lines[index] = ";Layer height: " + f"{float(line.split(":")[1]):.2f}".format(float(line.split(":")[1])) lines[index] += f"\n{init_layer_hgt_line}" lines[index] += f"\n;Base Quality Name : '{global_stack.quality.getMetaDataEntry("name", "")}'" lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" if line.startswith(";Filament used"): - lines[index] = filament_line_t0 + filament_line_t1 + lines[index] = filament_line_t0 + filament_line_t1 + f"\n;Electric Cost: {currency_unit}{total_cost_electricity:.2f}".format(total_cost_electricity) # The target machine "machine_name" is actually the printer model. This adds the user defined printer name to the "TARGET_MACHINE" line. if line.startswith(";TARGET_MACHINE"): machine_model = str(global_stack.getProperty("machine_name", "value")) From f6486bdffcf06984ea613fce22c3fac31be3bc79 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 1 Aug 2025 14:28:38 -0400 Subject: [PATCH 19/25] Update DisplayInfoOnLCD.py If the printer was a UM then the statistics and model list weren't being added. This is the fix. --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index ddf292fb85..a7578e3565 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -40,6 +40,7 @@ import datetime import math from UM.Preferences import Preferences from UM.Message import Message +from UM.Logger import Logger class DisplayInfoOnLCD(Script): @@ -272,7 +273,7 @@ class DisplayInfoOnLCD(Script): self.m73_str = "" para_1 = data[0].split("\n") for line in para_1: - if line.startswith(";TIME:"): + if line.startswith(";TIME:") or line.startswith(";PRINT.TIME:"): self.time_total = int(line.split(":")[1]) break if display_option == "filename_layer": @@ -693,8 +694,8 @@ class DisplayInfoOnLCD(Script): # Add the stats to the gcode file lines = data[0].split("\n") for index, line in enumerate(lines): - if line.startswith(";Layer height:"): - lines[index] = ";Layer height: " + f"{float(line.split(":")[1]):.2f}".format(float(line.split(":")[1])) + if line.startswith(";Layer height:") or line.startswith(";TARGET_MACHINE.NAME:"): + lines[index] = ";Layer height: " + f"{global_stack.getProperty("layer_height", "value")}" lines[index] += f"\n{init_layer_hgt_line}" lines[index] += f"\n;Base Quality Name : '{global_stack.quality.getMetaDataEntry("name", "")}'" lines[index] += f"\n;Custom Quality Name: '{global_stack.qualityChanges.getMetaDataEntry("name")}'" From 8c3c36b241819a662f4fc97346f62990cd3ed047 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:04:29 -0400 Subject: [PATCH 20/25] Update DisplayInfoOnLCD.py Changes per Reviewer request. --- plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py index a7578e3565..edfa9d8632 100644 --- a/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py +++ b/plugins/PostProcessingPlugin/scripts/DisplayInfoOnLCD.py @@ -38,9 +38,7 @@ from UM.Qt.Duration import DurationFormat import time import datetime import math -from UM.Preferences import Preferences from UM.Message import Message -from UM.Logger import Logger class DisplayInfoOnLCD(Script): @@ -286,6 +284,7 @@ class DisplayInfoOnLCD(Script): def _display_filename_layer(self, data: str) -> str: data[0] = self._add_stats(data) max_layer = 0 + format_option = self.getSettingValueByKey("format_option") lcd_text = "M117 " octo_text = "M118 " if self.getSettingValueByKey("file_name") != "": @@ -295,7 +294,7 @@ class DisplayInfoOnLCD(Script): if self.getSettingValueByKey("addPrefixPrinting"): lcd_text += "Printing " octo_text += "Printing " - if not self.getSettingValueByKey("scroll"): + if not format_option: lcd_text += "Lay " octo_text += "Layer " else: @@ -317,11 +316,11 @@ class DisplayInfoOnLCD(Script): if self.getSettingValueByKey("maxlayer"): display_text += "/" + max_layer self.m118_text += "/" + max_layer - if not self.getSettingValueByKey("scroll"): + if not format_option: display_text += "|" + file_name self.m118_text += " | " + file_name else: - if not self.getSettingValueByKey("scroll"): + if not format_option: display_text += "|" + file_name + "!" self.m118_text += " | " + file_name + "!" else: From 8353d55ce2b2d5e090ebf6a5922af5dffd2875dc Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:32:00 -0400 Subject: [PATCH 21/25] Create AnnealingOrDrying.py A new script. The user can hold the build plate and chamber temepratures to "anneal" a print. Optionally the heated be can be used to attempt to dry filament rolls. --- .../scripts/AnnealingOrDrying.py | 513 ++++++++++++++++++ 1 file changed, 513 insertions(+) create mode 100644 plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py diff --git a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py new file mode 100644 index 0000000000..6d6775c6ea --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py @@ -0,0 +1,513 @@ +""" +Copyright (c) 2025 GregValiant (Greg Foresi) + + When Annealing: + The user may elect to hold the build plate at a temperature for a period of time. When the hold expires, the 'Timed Cooldown' will begin. + If there is no 'Hold Time' then the 'Annealing' cooldown will begin when the print ends. In 'Annealing' cooldown the bed temperature drops in 3° increments across the time span. + G4 commands are used for the cooldown steps. + If there is a 'Heated Chamber' then the chamber will start to cool when the bed temperature reaches the chamber temperature. + + When drying filament: + The bed must be empty because the printer will auto-home before raising the Z to 'machine_height minus 20mm' and then park the head in the XY. + The bed will heat up to the set point. + G4 commands are used to keep the machine from turning the bed off until the Drying Time has expired. + If you happen to have an enclosure with a fan, the fan can be set up to run during the drying or annealing. + + NOTE: This script uses the G4 Dwell command as a timer. It cannot be canceled from the LCD. If you wish to ;excape' from G4 you might have to cancel the print from the LCD or cycle the printer on and off to reset. +""" + +from UM.Application import Application +from ..Script import Script +from UM.Message import Message + +class AnnealingOrDrying(Script): + + def initialize(self) -> None: + super().initialize() + # Get the Bed Temperature from Cura + bed_temp = str(Application.getInstance().getGlobalContainerStack().getProperty("material_bed_temperature", "value")) + self._instance.setProperty("startout_temp", "value", bed_temp) + # Get the Build Volume temperature if there is one + heated_build_volume = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) + curaApp = Application.getInstance().getGlobalContainerStack() + chamber_fan_nr = curaApp.getProperty("build_volume_fan_nr", "value") + extruder_count = curaApp.getProperty("machine_extruder_count", "value") + if heated_build_volume: + chamber_temp = curaApp.getProperty("build_volume_temperature", "value") + self._instance.setProperty("has_build_volume_heater", "value", heated_build_volume) + self._instance.setProperty("build_volume_temp", "value", chamber_temp) + try: + if chamber_fan_nr > 0: + self._instance.setProperty("enable_chamber_fan_setting", "value", True) + except: + pass + + def getSettingDataString(self): + return """{ + "name": "Annealing CoolDown or Filament Drying", + "key": "AnnealingOrDrying", + "metadata": {}, + "version": 2, + "settings": + { + "enable_annealing": + { + "label": "Enable the Script", + "description": "If it isn't enabled it doesn't run.", + "type": "bool", + "default_value": true, + "enabled": true + }, + "cycle_type": + { + "label": "Anneal Print or Dry Filament", + "description": "Whether to Anneal the Print (by keeping the bed hot for a period of time), or to use the bed as a Filament Dryer. If drying; you will still need to slice a model, but it will not print. The gcode will consist only of a short script to heat the bed, wait for a while, then turn the bed off. The 'Z' will move to the max height and XY park position so the filament can be covered. The 'Hold Time', 'Bed Start Temp' and (if applicable) the 'Chamber Temp' come from these settings rather than from the Cura settings. When annealing; the Timed Cooldown will commence when the print ends.", + "type": "enum", + "options": + { + + "anneal_cycle": "Anneal Print", + "dry_cycle": "Dry Filament"}, + "default_value": "anneal_cycle", + "enabled": true, + "enabled": "enable_annealing" + }, + "bed_and_chamber": + { + "label": "Hold the Temp for the:", + "description": "Select the 'Bed' for just the bed, or 'Bed and Chamber' if you want to include your 'Heated Build Volume'.", + "type": "enum", + "options": + { + "bed_only": "Bed", + "bed_chamber": "Bed and Chamber"}, + "default_value": "bed_only", + "enabled": "enable_annealing" + }, + "wait_time": + { + "label": "Hold Time at Temp(s)", + "description": "Hold the bed temp at the 'Bed Start Out Temperature' for this amount of time (in decimal hours). When this time expires then the Annealing cool down will start. This is also the 'Drying Time' used when 'Drying Filament'.", + "type": "float", + "default_value": 0.0, + "unit": "Decimal Hrs ", + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "dry_time": + { + "label": "Drying Time", + "description": "Hold the bed temp at the 'Bed Start Out Temperature' for this amount of time (in decimal hours). When this time expires the bed will shut off.", + "type": "float", + "default_value": 4.0, + "unit": "Decimal Hrs ", + "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + }, + "pause_cmd": + { + "label": "Pause Cmd for Auto-Home", + "description": "Not required when you are paying attention and the bed is empty; ELSE; Enter the pause command to use prior to the Auto-Home command. The pause insures that the user IS paying attention and clears the build plate for Auto-Home. If you leave the box empty then there won't be a pause.", + "type": "str", + "default_value": "", + "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + }, + "startout_temp": + { + "label": "Bed Start Out Temperature:", + "description": "Enter the temperature to start at. This is typically the bed temperature during the print but can be changed here. This is also the temperature used when drying filament.", + "type": "int", + "value": 30, + "unit": "Degrees ", + "minimum_value": 30, + "maximum_value": 110, + "maximum_value_warning": 100, + "enabled": "enable_annealing" + }, + "lowest_temp": + { + "label": "Shut-Off Temp:", + "description": "Enter the lowest temperature to control the cool down. This is the shut-off temperature for the build plate and (when applicable) the Heated Chamber. The minimum value is 30", + "type": "int", + "default_value": 30, + "unit": "Degrees ", + "minimum_value": 30, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "build_volume_temp": + { + "label": "Build Volume Temperature:", + "description": "Enter the temperature for the Build Volume (Heated Chamber). This is typically the temperature during the print but can be changed here.", + "type": "int", + "value": 24, + "unit": "Degrees ", + "minimum_value": 0, + "maximum_value": 90, + "maximum_value_warning": 75, + "enabled": "enable_annealing and has_build_volume_heater and bed_and_chamber == 'bed_chamber'" + }, + "enable_chamber_fan_setting": + { + "label": "Hidden Setting", + "description": "Enables chamber fan and speed.", + "type": "bool", + "default_value": false, + "enabled": false + }, + "chamber_fan_speed": + { + "label": "Chamber Fan Speed", + "description": "Set to % fan speed. Set to 0 to turn it off.", + "type": "int", + "default_value": 0, + "minimum_value": 0, + "maximum_value": 100, + "enabled": "enable_annealing and enable_chamber_fan_setting" + }, + "time_span": + { + "label": "Cool Down Time Span:", + "description": "The total amount of time (in decimal hours) to control the cool down. The build plate temperature will be dropped in 3° increments across this time span. 'Cool Down Time' starts at the end of the 'Hold Time' if you entered one.", + "type": "float", + "default_value": 1.0, + "unit": "Decimal Hrs ", + "minimum_value_warning": 0.25, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "park_head": + { + "label": "Park at MaxX and MaxY", + "description": "When unchecked, the park position is X0 Y0. Enable this setting to move the nozzle to the Max X and Max Y to allow access to the print.", + "type": "bool", + "default_value": false, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "park_max_z": + { + "label": "Move to MaxZ", + "description": "Enable this setting to move the nozzle to 'Machine_Height - 20' to allow the print to be covered.", + "type": "bool", + "default_value": false, + "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + }, + "beep_when_done": + { + "label": "Beep when done", + "description": "Add an annoying noise when the Cool Down completes.", + "type": "bool", + "default_value": true, + "enabled": "enable_annealing" + }, + "beep_duration": + { + "label": "Beep Duration", + "description": "The length of the buzzer sound. Units are in milliseconds so 1000ms = 1 second.", + "type": "int", + "unit": "milliseconds ", + "default_value": 1000, + "enabled": "beep_when_done and enable_annealing" + }, + "add_messages": + { + "label": "Include M117 and M118 messages", + "description": "Add messages to the LCD and any print server.", + "type": "bool", + "default_value": false, + "enabled": "enable_annealing" + }, + "has_build_volume_heater": + { + "label": "Hidden setting", + "description": "Hidden. This setting enables the build volume settings.", + "type": "bool", + "default_value": false, + "enabled": false + } + } + }""" + + def execute(self, data): + # Exit if there is no heated bed. + if not bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_bed", "value")): + Message(title = "[Anneal or Dry Filament]", text = "The script did not run because Heated Bed is disabled in Machine Settings.").show() + return data + # Enter a message in the gcode if the script is not enabled. + if not bool(self.getSettingValueByKey("enable_annealing")): + data[0] += "; [Anneal or Dry Filament] was not enabled\n" + return data + lowest_temp = int(self.getSettingValueByKey("lowest_temp")) + + # If the shutoff temp is under 30° then exit as a safety precaution so the bed doesn't stay on. + if lowest_temp < 30: + data[0] += "; Anneal or Dry Filament did not run. Shutoff Temp < 30\n" + Message(title = "[Anneal or Dry Filament]", text = "The script did not run because the Shutoff Temp is less than 30°.").show() + return data + self.global_stack = Application.getInstance().getGlobalContainerStack() + extruder = self.global_stack.extruderList + bed_temperature = int(self.getSettingValueByKey("startout_temp")) + heated_chamber = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) + anneal_type = self.getSettingValueByKey("bed_and_chamber") + + # Get the heated chamber temperature or set to 0 if no chamber + if heated_chamber: + chamber_temp = str(self.getSettingValueByKey("build_volume_temp")) + else: + anneal_type = "bed_only" + chamber_temp = "0" + + # For compatibility with earlier Cura versions + if self.global_stack.getProperty("build_volume_fan_nr", "value") is not None: + has_bv_fan = bool(self.global_stack.getProperty("build_volume_fan_nr", "value")) + bv_fan_nr = int(self.global_stack.getProperty("build_volume_fan_nr", "value")) + if bv_fan_nr > 0: + speed_bv_fan = int(self.getSettingValueByKey("chamber_fan_speed")) + else: + speed_bv_fan = 0 + + if bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: + speed_bv_fan = round(speed_bv_fan * .01) + else: + speed_bv_fan = round(speed_bv_fan * 2.55) + + if has_bv_fan and speed_bv_fan > 0: + self.bv_fan_on_str = f"M106 S{speed_bv_fan} P{bv_fan_nr} ; Build Chamber Fan On\n" + self.bv_fan_off_str = f"M106 S0 P{bv_fan_nr} ; Build Chamber Fan Off\n" + else: + self.bv_fan_on_str = "" + self.bv_fan_off_str = "" + else: + has_bv_fan = False + bv_fan_nr = 0 + speed_bv_fan = 0 + self.bv_fan_on_str = "" + self.bv_fan_off_str = "" + + # Park Head + max_y = str(self.global_stack.getProperty("machine_depth", "value")) + max_x = str(self.global_stack.getProperty("machine_width", "value")) + # Max_z is limited to 'machine_height - 20' just so the print head doesn't smack into anything. + max_z = str(int(self.global_stack.getProperty("machine_height", "value")) - 20) + speed_travel = str(round(extruder[0].getProperty("speed_travel", "value")*60)) + park_xy = bool(self.getSettingValueByKey("park_head")) + park_z = bool(self.getSettingValueByKey("park_max_z")) + cycle_type = self.getSettingValueByKey("cycle_type") + add_messages = bool(self.getSettingValueByKey("add_messages")) + + if cycle_type == "anneal_cycle": + data = self._anneal_print(data, park_xy, park_z, bed_temperature, lowest_temp, heated_chamber, chamber_temp, max_y, max_x, max_z, speed_travel, add_messages, anneal_type) + elif cycle_type == "dry_cycle": + data = self._dry_filament_only(data, anneal_type, heated_chamber, chamber_temp, bed_temperature, max_z, max_y, speed_travel) + return data + + def _anneal_print(self, anneal_data: str, park_xy: bool, park_z: bool, bed_temperature:int, lowest_temp: int, heated_chamber: bool, chamber_temp: str, max_x: str, max_y: str, max_z: str, speed_travel: str, add_messages: bool, anneal_type: str): + """ + The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. The bed is allowed to cool down over a period of time. + """ + # Put the head parking string together + time_minutes = 1 + time_span = int(float(self.getSettingValueByKey("time_span")) * 3600) + park_string = "" + if park_xy and not park_z: + park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nM84 X Y E ; Disable steppers except Z\n" + elif park_xy and park_z: + park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nG0 Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" + elif not park_xy and park_z: + park_string = f"G0 F{speed_travel} Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" + elif not park_xy and not park_z: + park_string = f"G91 ; Relative movement\nG0 F{speed_travel} Z5 ; Raise Z\nG90 ; Absolute movement\nG0 X0 Y0 ; Park\nM84 X Y E ; Disable steppers except Z\n" + + # Calculate the temperature differential + hysteresis = bed_temperature - lowest_temp + + # if the bed temp is below the shutoff temp then exit + if hysteresis <= 0: + anneal_data[0] += "; Anneal or Dry Filament did not run. Bed Temp < Shutoff Temp\n" + Message(title = "Anneal or Dry Filament", text = "Did not run because the Bed Temp < Shutoff Temp.").show() + return anneal_data + + # Drop the bed temperature in 3° increments. + num_steps = int(hysteresis / 3) + step_index = 2 + deg_per_step = int(hysteresis / num_steps) + time_per_step = int(time_span / num_steps) + step_down = bed_temperature + wait_time = int(float(self.getSettingValueByKey("wait_time")) * 3600) + + # Put the first lines of the anneal string together + anneal_string = ";\n;TYPE:CUSTOM ---------------- Anneal Print\n" + if add_messages: + anneal_string += "M117 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" + anneal_string += "M118 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" + anneal_string += self.bv_fan_on_str + if wait_time > 0: + # Move the head before the M190 + anneal_string += park_string + if anneal_type == "bed_only": + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n" + if anneal_type == "bed_chamber": + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n" + anneal_string += f"G4 S{wait_time} ; Hold for {round(wait_time / 3600,2)} hrs\n" + else: + # Move the head after the M140 + anneal_string += f"M140 S{step_down} ; Set bed temp\n" + anneal_string += park_string + anneal_string += f"G4 S{time_per_step} ; wait time in seconds\n" + step_down -= deg_per_step + + time_remaining = round(time_span/3600,2) + # Step the bed/chamber temps down and add each step to the anneal string. The chamber remains at it's temperature until the bed gets down to that temperature. + for num in range(bed_temperature, lowest_temp, -3): + anneal_string += f"M140 S{step_down} ; Step down bed\n" + if anneal_type == "bed_chamber" and int(step_down) < int(chamber_temp): + anneal_string += f"M141 S{step_down} ; Step down chamber\n" + anneal_string += f"G4 S{time_per_step} ; Wait\n" + #time_remaining = round((time_span-(step_index*time_per_step))/3600,2) + if time_remaining >= 1.00: + if add_messages: + anneal_string += f"M117 CoolDown - {round(time_remaining,1)}hr\n" + anneal_string += f"M118 CoolDown - {round(time_remaining,1)}hr\n" + elif time_minutes > 0: + time_minutes = round(time_remaining * 60,1) + if add_messages: + anneal_string += f"M117 CoolDown - {time_minutes}min\n" + anneal_string += f"M118 CoolDown - {time_minutes}min\n" + time_remaining = round((time_span-(step_index*time_per_step))/3600,2) + step_down -= deg_per_step + step_index += 1 + if step_down <= lowest_temp: + break + + # Beep line + if bool(self.getSettingValueByKey("beep_when_done")): + beep_string = "M300 S440 P" + str(self.getSettingValueByKey("beep_duration")) + " ; Beep\n" + else: + beep_string = "" + + # Close out the anneal string + anneal_string += "M140 S0 ; Shut off the bed heater" + "\n" + if anneal_type == "bed_chamber": + anneal_string += "M141 S0 ; Shut off the chamber heater\n" + anneal_string += self.bv_fan_off_str + anneal_string += beep_string + if add_messages: + anneal_string += "M117 CoolDown Complete\n" + anneal_string += "M118 CoolDown Complete\n" + anneal_string += ";TYPE:CUSTOM ---------------- End of Anneal\n;" + + # Format + anneal_lines = anneal_string.split("\n") + for index, line in enumerate(anneal_lines): + if not line.startswith(";") and ";" in line: + front_txt = anneal_lines[index].split(";")[0] + back_txt = anneal_lines[index].split(";")[1] + anneal_lines[index] = front_txt + str(" " * (30 - len(front_txt))) +";" + back_txt + anneal_string = "\n".join(anneal_lines) + "\n" + + layer = anneal_data[len(anneal_data)-1] + lines = layer.split("\n") + + # Comment out the M140 S0 line in the ending gcode. + for num in range(len(lines)-1,-1,-1): + if lines[num].startswith("M140 S0"): + lines[num] = ";M140 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[len(anneal_data)-1] = "\n".join(lines) + + # If there is a Heated Chamber and it's included then comment out the M141 S0 line + if anneal_type == "bed_chamber" and heated_chamber: + for num in range(0,len(lines)-1,1): + if lines[num].startswith("M141 S0"): + lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[len(anneal_data)-1] = "\n".join(lines) + + # If park head is enabled then dont let the steppers disable until the head is parked + disable_string = "" + for num in range(0,len(lines)-1,1): + if lines[num][:3] in ("M84", "M18"): + disable_string = lines[num] + "\n" + stepper_timeout = int(wait_time + time_span) + if stepper_timeout > 14400: stepper_timeout = 14400 + lines[num] = ";" + lines[num] + " ; Overide - Anneal or Dry Filament" + lines.insert(num, "M84 S" + str(stepper_timeout) + " ; Increase stepper timeout - Anneal or Dry Filament") + anneal_data[len(anneal_data)-1] = "\n".join(lines) + break + + # The Anneal string is the new end of the gcode so move the 'End of Gcode' comment line in case there are other scripts running + anneal_data[len(anneal_data)-1] = anneal_data[len(anneal_data)-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") + return anneal_data + + def _dry_filament_only(self, drydata: str, anneal_type: str, heated_chamber: bool, chamber_temp: int, bed_temperature: int, max_z:str, max_y:str, speed_travel: str) -> str: + """ + This procedure turns the bed on, homes the printer, parks the head. After the time period the bed is turned off. There is no actual print in the generated gcode, just a couple of moves to get the nozzle out of the way, and the bed heat (and possibly chamber heat) control. It allows a user to use the bed to warm up and hopefully dry a filament roll. + """ + for num in range(2, len(drydata)): + drydata[num] = "" + drydata[0] = drydata[0].split("\n")[0] + "\n" + add_messages = bool(self.getSettingValueByKey("add_messages")) + pause_cmd = self.getSettingValueByKey("pause_cmd").upper() + if pause_cmd != "": + pause_cmd = "M300 ; Beep\n" + pause_cmd + dry_time = self.getSettingValueByKey("dry_time") * 3600 + lines = drydata[1].split("\n") + drying_string = lines[0] + "\n" + ";............TYPE:CUSTOM: Dry Filament\n" + if add_messages: + drying_string += f"M117 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" + drying_string += f"M118 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" + # M113 sends messages to a print server as a 'Keep Alive' and can generate a lot of traffic over the USB + drying_string += "M113 S0 ; No echo\n" + drying_string += f"M84 S{round(dry_time)} ; Set stepper timeout\n" + drying_string += f"M140 S{bed_temperature} ; Heat bed\n" + drying_string += self.bv_fan_on_str + if heated_chamber and anneal_type == "bed_chamber": + drying_string += f"M141 S{chamber_temp} ; Chamber temp\n" + if pause_cmd == "M0": + pause_cmd = "M0 Clear bed and click...; Pause" + if pause_cmd != "": + drying_string += pause_cmd + " ; Pause\n" + drying_string += "G28 ; Auto-Home\n" + drying_string += f"G0 F{speed_travel} Z{max_z} ; Raise Z to 'ZMax - 20'\n" + drying_string += f"G0 F{speed_travel} X0 Y{max_y} ; Park print head\n" + if dry_time <= 3600: + if add_messages: + drying_string += f"M117 {dry_time/3600} hr remaining ; Message\n" + drying_string += f"M118 {dry_time/3600} hr remaining ; Message\n" + drying_string += f"G4 S{dry_time} ; Dry time\n" + elif dry_time > 3600: + temp_time = dry_time + while temp_time > 3600: + if add_messages: + drying_string += f"M117 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"M118 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"G4 S3600 ; Dry time split\n" + if temp_time > 3600: + temp_time -= 3600 + if temp_time > 0: + if add_messages: + drying_string += f"M117 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"M118 {temp_time/3600} hr remaining ; Message\n" + drying_string += f"G4 S{temp_time} ; Dry time\n" + if heated_chamber and anneal_type == "bed_chamber": + drying_string += f"M141 S0 ; Shut off chamber\n" + drying_string += "M140 S0 ; Shut off bed\n" + drying_string += self.bv_fan_off_str + if self.getSettingValueByKey("beep_when_done"): + beep_duration = self.getSettingValueByKey("beep_duration") + drying_string += f"M300 P{beep_duration} ; Beep\n" + if add_messages: + drying_string += "M117 End of drying cycle ; Message\n" + drying_string += "M118 End of drying cycle ; Message\n" + drying_string += "M84 X Y E ; Disable steppers except Z\n" + drying_string += ";End of Gcode" + + # Format + lines = drying_string.split("\n") + for index, line in enumerate(lines): + if not line.startswith(";") and ";" in line: + front_txt = lines[index].split(";")[0] + back_txt = lines[index].split(";")[1] + lines[index] = front_txt + str(" " * (30 - len(front_txt))) +";" + back_txt + drydata[1] = "\n".join(lines) + "\n" + dry_txt = "; Drying time ...................... " + str(self.getSettingValueByKey("dry_time")) + " hrs\n" + dry_txt += "; Drying temperature ........ " + str(bed_temperature) + "°\n" + if heated_chamber and anneal_type == "bed_chamber": + dry_txt += "; Chamber temperature ... " + str(chamber_temp) + "°\n" + Message(title = "[Dry Filament]", text = dry_txt).show() + drydata[0] = "; <<< This is a filament drying file only. There is no actual print. >>>\n;\n" + dry_txt + ";\n" + return drydata \ No newline at end of file From 47ad02bcf1baf4278e15a8879408641f23055fba Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sat, 2 Aug 2025 23:05:32 -0400 Subject: [PATCH 22/25] Update AnnealingOrDrying.py Changed some verbiage. Update AnnealingOrDrying.py Changes per the review, bug fixes, cleanup my code. Add more beeps. Update AnnealingOrDrying.py Fixed a typo --- .../scripts/AnnealingOrDrying.py | 170 +++++++++--------- 1 file changed, 88 insertions(+), 82 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py index 6d6775c6ea..496fc1cb42 100644 --- a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py +++ b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py @@ -3,7 +3,7 @@ Copyright (c) 2025 GregValiant (Greg Foresi) When Annealing: The user may elect to hold the build plate at a temperature for a period of time. When the hold expires, the 'Timed Cooldown' will begin. - If there is no 'Hold Time' then the 'Annealing' cooldown will begin when the print ends. In 'Annealing' cooldown the bed temperature drops in 3° increments across the time span. + If there is no 'Hold Time' then the 'Annealing' cooldown will begin when the print ends. In 'Annealing' the bed temperature drops in 3° increments across the time span. G4 commands are used for the cooldown steps. If there is a 'Heated Chamber' then the chamber will start to cool when the bed temperature reaches the chamber temperature. @@ -12,8 +12,8 @@ Copyright (c) 2025 GregValiant (Greg Foresi) The bed will heat up to the set point. G4 commands are used to keep the machine from turning the bed off until the Drying Time has expired. If you happen to have an enclosure with a fan, the fan can be set up to run during the drying or annealing. - - NOTE: This script uses the G4 Dwell command as a timer. It cannot be canceled from the LCD. If you wish to ;excape' from G4 you might have to cancel the print from the LCD or cycle the printer on and off to reset. + + NOTE: This script uses the G4 Dwell command as a timer. It cannot be canceled from the LCD. If you wish to 'escape' from G4 you might have to cancel the print from the LCD or cycle the printer on and off to reset. """ from UM.Application import Application @@ -25,15 +25,15 @@ class AnnealingOrDrying(Script): def initialize(self) -> None: super().initialize() # Get the Bed Temperature from Cura - bed_temp = str(Application.getInstance().getGlobalContainerStack().getProperty("material_bed_temperature", "value")) - self._instance.setProperty("startout_temp", "value", bed_temp) + self.global_stack = Application.getInstance().getGlobalContainerStack() + bed_temp_during_print = str(self.global_stack.getProperty("material_bed_temperature", "value")) + self._instance.setProperty("startout_temp", "value", bed_temp_during_print) # Get the Build Volume temperature if there is one - heated_build_volume = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) - curaApp = Application.getInstance().getGlobalContainerStack() - chamber_fan_nr = curaApp.getProperty("build_volume_fan_nr", "value") - extruder_count = curaApp.getProperty("machine_extruder_count", "value") + heated_build_volume = bool(self.global_stack.getProperty("machine_heated_build_volume", "value")) + chamber_fan_nr = self.global_stack.getProperty("build_volume_fan_nr", "value") + extruder_count = self.global_stack.getProperty("machine_extruder_count", "value") if heated_build_volume: - chamber_temp = curaApp.getProperty("build_volume_temperature", "value") + chamber_temp = self.global_stack.getProperty("build_volume_temperature", "value") self._instance.setProperty("has_build_volume_heater", "value", heated_build_volume) self._instance.setProperty("build_volume_temp", "value", chamber_temp) try: @@ -50,7 +50,7 @@ class AnnealingOrDrying(Script): "version": 2, "settings": { - "enable_annealing": + "enable_script": { "label": "Enable the Script", "description": "If it isn't enabled it doesn't run.", @@ -65,14 +65,14 @@ class AnnealingOrDrying(Script): "type": "enum", "options": { - "anneal_cycle": "Anneal Print", - "dry_cycle": "Dry Filament"}, + "dry_cycle": "Dry Filament" + }, "default_value": "anneal_cycle", "enabled": true, - "enabled": "enable_annealing" + "enabled": "enable_script" }, - "bed_and_chamber": + "heating_zone_selection": { "label": "Hold the Temp for the:", "description": "Select the 'Bed' for just the bed, or 'Bed and Chamber' if you want to include your 'Heated Build Volume'.", @@ -82,7 +82,7 @@ class AnnealingOrDrying(Script): "bed_only": "Bed", "bed_chamber": "Bed and Chamber"}, "default_value": "bed_only", - "enabled": "enable_annealing" + "enabled": "enable_script" }, "wait_time": { @@ -91,7 +91,7 @@ class AnnealingOrDrying(Script): "type": "float", "default_value": 0.0, "unit": "Decimal Hrs ", - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "dry_time": { @@ -100,7 +100,7 @@ class AnnealingOrDrying(Script): "type": "float", "default_value": 4.0, "unit": "Decimal Hrs ", - "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + "enabled": "enable_script and cycle_type == 'dry_cycle'" }, "pause_cmd": { @@ -108,7 +108,7 @@ class AnnealingOrDrying(Script): "description": "Not required when you are paying attention and the bed is empty; ELSE; Enter the pause command to use prior to the Auto-Home command. The pause insures that the user IS paying attention and clears the build plate for Auto-Home. If you leave the box empty then there won't be a pause.", "type": "str", "default_value": "", - "enabled": "enable_annealing and cycle_type == 'dry_cycle'" + "enabled": "enable_script and cycle_type == 'dry_cycle'" }, "startout_temp": { @@ -120,7 +120,7 @@ class AnnealingOrDrying(Script): "minimum_value": 30, "maximum_value": 110, "maximum_value_warning": 100, - "enabled": "enable_annealing" + "enabled": "enable_script" }, "lowest_temp": { @@ -130,7 +130,7 @@ class AnnealingOrDrying(Script): "default_value": 30, "unit": "Degrees ", "minimum_value": 30, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "build_volume_temp": { @@ -142,7 +142,7 @@ class AnnealingOrDrying(Script): "minimum_value": 0, "maximum_value": 90, "maximum_value_warning": 75, - "enabled": "enable_annealing and has_build_volume_heater and bed_and_chamber == 'bed_chamber'" + "enabled": "enable_script and has_build_volume_heater and heating_zone_selection == 'bed_chamber'" }, "enable_chamber_fan_setting": { @@ -160,7 +160,8 @@ class AnnealingOrDrying(Script): "default_value": 0, "minimum_value": 0, "maximum_value": 100, - "enabled": "enable_annealing and enable_chamber_fan_setting" + "unit": "% ", + "enabled": "enable_script and enable_chamber_fan_setting" }, "time_span": { @@ -170,7 +171,7 @@ class AnnealingOrDrying(Script): "default_value": 1.0, "unit": "Decimal Hrs ", "minimum_value_warning": 0.25, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "park_head": { @@ -178,7 +179,7 @@ class AnnealingOrDrying(Script): "description": "When unchecked, the park position is X0 Y0. Enable this setting to move the nozzle to the Max X and Max Y to allow access to the print.", "type": "bool", "default_value": false, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "park_max_z": { @@ -186,7 +187,7 @@ class AnnealingOrDrying(Script): "description": "Enable this setting to move the nozzle to 'Machine_Height - 20' to allow the print to be covered.", "type": "bool", "default_value": false, - "enabled": "enable_annealing and cycle_type == 'anneal_cycle'" + "enabled": "enable_script and cycle_type == 'anneal_cycle'" }, "beep_when_done": { @@ -194,7 +195,7 @@ class AnnealingOrDrying(Script): "description": "Add an annoying noise when the Cool Down completes.", "type": "bool", "default_value": true, - "enabled": "enable_annealing" + "enabled": "enable_script" }, "beep_duration": { @@ -203,7 +204,7 @@ class AnnealingOrDrying(Script): "type": "int", "unit": "milliseconds ", "default_value": 1000, - "enabled": "beep_when_done and enable_annealing" + "enabled": "beep_when_done and enable_script" }, "add_messages": { @@ -211,7 +212,7 @@ class AnnealingOrDrying(Script): "description": "Add messages to the LCD and any print server.", "type": "bool", "default_value": false, - "enabled": "enable_annealing" + "enabled": "enable_script" }, "has_build_volume_heater": { @@ -226,11 +227,11 @@ class AnnealingOrDrying(Script): def execute(self, data): # Exit if there is no heated bed. - if not bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_bed", "value")): + if not bool(self.global_stack.getProperty("machine_heated_bed", "value")): Message(title = "[Anneal or Dry Filament]", text = "The script did not run because Heated Bed is disabled in Machine Settings.").show() return data # Enter a message in the gcode if the script is not enabled. - if not bool(self.getSettingValueByKey("enable_annealing")): + if not bool(self.getSettingValueByKey("enable_script")): data[0] += "; [Anneal or Dry Filament] was not enabled\n" return data lowest_temp = int(self.getSettingValueByKey("lowest_temp")) @@ -240,11 +241,10 @@ class AnnealingOrDrying(Script): data[0] += "; Anneal or Dry Filament did not run. Shutoff Temp < 30\n" Message(title = "[Anneal or Dry Filament]", text = "The script did not run because the Shutoff Temp is less than 30°.").show() return data - self.global_stack = Application.getInstance().getGlobalContainerStack() - extruder = self.global_stack.extruderList + extruders = self.global_stack.extruderList bed_temperature = int(self.getSettingValueByKey("startout_temp")) - heated_chamber = bool(Application.getInstance().getGlobalContainerStack().getProperty("machine_heated_build_volume", "value")) - anneal_type = self.getSettingValueByKey("bed_and_chamber") + heated_chamber = bool(self.global_stack.getProperty("machine_heated_build_volume", "value")) + anneal_type = self.getSettingValueByKey("heating_zone_selection") # Get the heated chamber temperature or set to 0 if no chamber if heated_chamber: @@ -253,6 +253,13 @@ class AnnealingOrDrying(Script): anneal_type = "bed_only" chamber_temp = "0" + # Beep line + if bool(self.getSettingValueByKey("beep_when_done")): + beep_duration = self.getSettingValueByKey("beep_duration") + self.beep_string = f"M300 S440 P{beep_duration} ; Beep\n" + else: + self.beep_string = "" + # For compatibility with earlier Cura versions if self.global_stack.getProperty("build_volume_fan_nr", "value") is not None: has_bv_fan = bool(self.global_stack.getProperty("build_volume_fan_nr", "value")) @@ -262,7 +269,7 @@ class AnnealingOrDrying(Script): else: speed_bv_fan = 0 - if bool(extruder[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: + if bool(extruders[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: speed_bv_fan = round(speed_bv_fan * .01) else: speed_bv_fan = round(speed_bv_fan * 2.55) @@ -283,9 +290,10 @@ class AnnealingOrDrying(Script): # Park Head max_y = str(self.global_stack.getProperty("machine_depth", "value")) max_x = str(self.global_stack.getProperty("machine_width", "value")) + # Max_z is limited to 'machine_height - 20' just so the print head doesn't smack into anything. max_z = str(int(self.global_stack.getProperty("machine_height", "value")) - 20) - speed_travel = str(round(extruder[0].getProperty("speed_travel", "value")*60)) + speed_travel = str(round(extruders[0].getProperty("speed_travel", "value")*60)) park_xy = bool(self.getSettingValueByKey("park_head")) park_z = bool(self.getSettingValueByKey("park_max_z")) cycle_type = self.getSettingValueByKey("cycle_type") @@ -295,6 +303,7 @@ class AnnealingOrDrying(Script): data = self._anneal_print(data, park_xy, park_z, bed_temperature, lowest_temp, heated_chamber, chamber_temp, max_y, max_x, max_z, speed_travel, add_messages, anneal_type) elif cycle_type == "dry_cycle": data = self._dry_filament_only(data, anneal_type, heated_chamber, chamber_temp, bed_temperature, max_z, max_y, speed_travel) + return data def _anneal_print(self, anneal_data: str, park_xy: bool, park_z: bool, bed_temperature:int, lowest_temp: int, heated_chamber: bool, chamber_temp: str, max_x: str, max_y: str, max_z: str, speed_travel: str, add_messages: bool, anneal_type: str): @@ -302,17 +311,17 @@ class AnnealingOrDrying(Script): The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. The bed is allowed to cool down over a period of time. """ # Put the head parking string together + bed_temp_during_print = int(self.global_stack.getProperty("material_bed_temperature", "value")) time_minutes = 1 time_span = int(float(self.getSettingValueByKey("time_span")) * 3600) park_string = "" - if park_xy and not park_z: - park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nM84 X Y E ; Disable steppers except Z\n" - elif park_xy and park_z: - park_string = f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\nG0 Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" - elif not park_xy and park_z: - park_string = f"G0 F{speed_travel} Z{max_z} ; Raise Z to 'ZMax - 20'\nM84 X Y E ; Disable steppers except Z\n" - elif not park_xy and not park_z: - park_string = f"G91 ; Relative movement\nG0 F{speed_travel} Z5 ; Raise Z\nG90 ; Absolute movement\nG0 X0 Y0 ; Park\nM84 X Y E ; Disable steppers except Z\n" + if park_xy: + park_string += f"G0 F{speed_travel} X{max_x} Y{max_y} ; Park XY\n" + if park_z: + park_string += f"G0 Z{max_z} ; Raise Z to 'ZMax - 20'\n" + if not park_xy and not park_z: + park_string += f"G91 ; Relative movement\nG0 F{speed_travel} Z5 ; Raise Z\nG90 ; Absolute movement\nG0 X0 Y0 ; Park\n" + park_string += "M84 X Y E ; Disable steppers except Z\n" # Calculate the temperature differential hysteresis = bed_temperature - lowest_temp @@ -333,33 +342,35 @@ class AnnealingOrDrying(Script): # Put the first lines of the anneal string together anneal_string = ";\n;TYPE:CUSTOM ---------------- Anneal Print\n" + if bed_temperature == bed_temp_during_print: + anneal_string += self.beep_string if add_messages: anneal_string += "M117 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" anneal_string += "M118 Cool Down for " + str(round((wait_time + time_span)/3600,2)) + "hr\n" anneal_string += self.bv_fan_on_str if wait_time > 0: - # Move the head before the M190 + # Add the parking string BEFORE the M190 anneal_string += park_string if anneal_type == "bed_only": - anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n" + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n{self.beep_string}" if anneal_type == "bed_chamber": - anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n" + anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n{self.beep_string}" anneal_string += f"G4 S{wait_time} ; Hold for {round(wait_time / 3600,2)} hrs\n" else: - # Move the head after the M140 + # Add the parking string AFTER the M140 anneal_string += f"M140 S{step_down} ; Set bed temp\n" anneal_string += park_string anneal_string += f"G4 S{time_per_step} ; wait time in seconds\n" - step_down -= deg_per_step + step_down -= deg_per_step time_remaining = round(time_span/3600,2) + # Step the bed/chamber temps down and add each step to the anneal string. The chamber remains at it's temperature until the bed gets down to that temperature. for num in range(bed_temperature, lowest_temp, -3): anneal_string += f"M140 S{step_down} ; Step down bed\n" if anneal_type == "bed_chamber" and int(step_down) < int(chamber_temp): anneal_string += f"M141 S{step_down} ; Step down chamber\n" anneal_string += f"G4 S{time_per_step} ; Wait\n" - #time_remaining = round((time_span-(step_index*time_per_step))/3600,2) if time_remaining >= 1.00: if add_messages: anneal_string += f"M117 CoolDown - {round(time_remaining,1)}hr\n" @@ -375,24 +386,18 @@ class AnnealingOrDrying(Script): if step_down <= lowest_temp: break - # Beep line - if bool(self.getSettingValueByKey("beep_when_done")): - beep_string = "M300 S440 P" + str(self.getSettingValueByKey("beep_duration")) + " ; Beep\n" - else: - beep_string = "" - # Close out the anneal string anneal_string += "M140 S0 ; Shut off the bed heater" + "\n" if anneal_type == "bed_chamber": anneal_string += "M141 S0 ; Shut off the chamber heater\n" anneal_string += self.bv_fan_off_str - anneal_string += beep_string + anneal_string += self.beep_string if add_messages: anneal_string += "M117 CoolDown Complete\n" anneal_string += "M118 CoolDown Complete\n" anneal_string += ";TYPE:CUSTOM ---------------- End of Anneal\n;" - # Format + # Format the inserted lines. anneal_lines = anneal_string.split("\n") for index, line in enumerate(anneal_lines): if not line.startswith(";") and ";" in line: @@ -401,36 +406,36 @@ class AnnealingOrDrying(Script): anneal_lines[index] = front_txt + str(" " * (30 - len(front_txt))) +";" + back_txt anneal_string = "\n".join(anneal_lines) + "\n" - layer = anneal_data[len(anneal_data)-1] - lines = layer.split("\n") + end_gcode = anneal_data[-1] + end_lines = end_gcode.split("\n") - # Comment out the M140 S0 line in the ending gcode. - for num in range(len(lines)-1,-1,-1): - if lines[num].startswith("M140 S0"): - lines[num] = ";M140 S0 ; Shutoff Overide - Anneal or Dry Filament" - anneal_data[len(anneal_data)-1] = "\n".join(lines) + # Comment out the existing M140 S0 lines in the ending gcode. + for num in range(len(end_lines)-1,-1,-1): + if end_lines[num].startswith("M140 S0"): + end_lines[num] = ";M140 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[-1] = "\n".join(end_lines) # If there is a Heated Chamber and it's included then comment out the M141 S0 line if anneal_type == "bed_chamber" and heated_chamber: - for num in range(0,len(lines)-1,1): - if lines[num].startswith("M141 S0"): - lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" - anneal_data[len(anneal_data)-1] = "\n".join(lines) + for num in range(0,len(end_lines)-1): + if end_lines[num].startswith("M141 S0"): + end_lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" + anneal_data[-1] = "\n".join(end_lines) # If park head is enabled then dont let the steppers disable until the head is parked disable_string = "" - for num in range(0,len(lines)-1,1): - if lines[num][:3] in ("M84", "M18"): - disable_string = lines[num] + "\n" + for num in range(0,len(end_lines)-1): + if end_lines[num][:3] in ("M84", "M18"): + disable_string = end_lines[num] + "\n" stepper_timeout = int(wait_time + time_span) if stepper_timeout > 14400: stepper_timeout = 14400 - lines[num] = ";" + lines[num] + " ; Overide - Anneal or Dry Filament" - lines.insert(num, "M84 S" + str(stepper_timeout) + " ; Increase stepper timeout - Anneal or Dry Filament") - anneal_data[len(anneal_data)-1] = "\n".join(lines) + end_lines[num] = ";" + end_lines[num] + " ; Overide - Anneal or Dry Filament" + end_lines.insert(num, "M84 S" + str(stepper_timeout) + " ; Increase stepper timeout - Anneal or Dry Filament") + anneal_data[-1] = "\n".join(end_lines) break # The Anneal string is the new end of the gcode so move the 'End of Gcode' comment line in case there are other scripts running - anneal_data[len(anneal_data)-1] = anneal_data[len(anneal_data)-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") + anneal_data[-1] = anneal_data[-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") return anneal_data def _dry_filament_only(self, drydata: str, anneal_type: str, heated_chamber: bool, chamber_temp: int, bed_temperature: int, max_z:str, max_y:str, speed_travel: str) -> str: @@ -441,15 +446,16 @@ class AnnealingOrDrying(Script): drydata[num] = "" drydata[0] = drydata[0].split("\n")[0] + "\n" add_messages = bool(self.getSettingValueByKey("add_messages")) - pause_cmd = self.getSettingValueByKey("pause_cmd").upper() + pause_cmd = self.getSettingValueByKey("pause_cmd") if pause_cmd != "": - pause_cmd = "M300 ; Beep\n" + pause_cmd + pause_cmd = self.beep_string + pause_cmd dry_time = self.getSettingValueByKey("dry_time") * 3600 lines = drydata[1].split("\n") - drying_string = lines[0] + "\n" + ";............TYPE:CUSTOM: Dry Filament\n" + drying_string = lines[0] + f"\n;............TYPE:CUSTOM: Dry Filament\n{self.beep_string}" if add_messages: drying_string += f"M117 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" drying_string += f"M118 Cool Down for {round(dry_time/3600,2)} hr ; Message\n" + # M113 sends messages to a print server as a 'Keep Alive' and can generate a lot of traffic over the USB drying_string += "M113 S0 ; No echo\n" drying_string += f"M84 S{round(dry_time)} ; Set stepper timeout\n" @@ -489,14 +495,14 @@ class AnnealingOrDrying(Script): drying_string += self.bv_fan_off_str if self.getSettingValueByKey("beep_when_done"): beep_duration = self.getSettingValueByKey("beep_duration") - drying_string += f"M300 P{beep_duration} ; Beep\n" + drying_string += self.beep_string if add_messages: drying_string += "M117 End of drying cycle ; Message\n" drying_string += "M118 End of drying cycle ; Message\n" drying_string += "M84 X Y E ; Disable steppers except Z\n" drying_string += ";End of Gcode" - # Format + # Format the lines lines = drying_string.split("\n") for index, line in enumerate(lines): if not line.startswith(";") and ";" in line: From 4006272fee2f6b90af4ac78cbf7e071aa39f7746 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 5 Aug 2025 00:45:48 +0200 Subject: [PATCH 23/25] Some housekeeping - anneal_type -> heating_zone: lines up the variable name with intent. - Sort the variable inputs of the functions (annealing / drying) - Add description for parameters in both functions (annealing / drying) --- .../scripts/AnnealingOrDrying.py | 94 ++++++++++++++----- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py index 496fc1cb42..1841a8b62b 100644 --- a/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py +++ b/plugins/PostProcessingPlugin/scripts/AnnealingOrDrying.py @@ -67,7 +67,7 @@ class AnnealingOrDrying(Script): { "anneal_cycle": "Anneal Print", "dry_cycle": "Dry Filament" - }, + }, "default_value": "anneal_cycle", "enabled": true, "enabled": "enable_script" @@ -80,7 +80,8 @@ class AnnealingOrDrying(Script): "options": { "bed_only": "Bed", - "bed_chamber": "Bed and Chamber"}, + "bed_chamber": "Bed and Chamber" + }, "default_value": "bed_only", "enabled": "enable_script" }, @@ -244,13 +245,13 @@ class AnnealingOrDrying(Script): extruders = self.global_stack.extruderList bed_temperature = int(self.getSettingValueByKey("startout_temp")) heated_chamber = bool(self.global_stack.getProperty("machine_heated_build_volume", "value")) - anneal_type = self.getSettingValueByKey("heating_zone_selection") + heating_zone = self.getSettingValueByKey("heating_zone_selection") # Get the heated chamber temperature or set to 0 if no chamber if heated_chamber: chamber_temp = str(self.getSettingValueByKey("build_volume_temp")) else: - anneal_type = "bed_only" + heating_zone = "bed_only" chamber_temp = "0" # Beep line @@ -270,7 +271,7 @@ class AnnealingOrDrying(Script): speed_bv_fan = 0 if bool(extruders[0].getProperty("machine_scale_fan_speed_zero_to_one", "value")) and has_bv_fan: - speed_bv_fan = round(speed_bv_fan * .01) + speed_bv_fan = round(speed_bv_fan * 0.01) else: speed_bv_fan = round(speed_bv_fan * 2.55) @@ -300,15 +301,45 @@ class AnnealingOrDrying(Script): add_messages = bool(self.getSettingValueByKey("add_messages")) if cycle_type == "anneal_cycle": - data = self._anneal_print(data, park_xy, park_z, bed_temperature, lowest_temp, heated_chamber, chamber_temp, max_y, max_x, max_z, speed_travel, add_messages, anneal_type) + data = self._anneal_print(add_messages, data, bed_temperature, chamber_temp, heated_chamber, heating_zone, lowest_temp, max_x, max_y, max_z, park_xy, park_z, speed_travel) elif cycle_type == "dry_cycle": - data = self._dry_filament_only(data, anneal_type, heated_chamber, chamber_temp, bed_temperature, max_z, max_y, speed_travel) + data = self._dry_filament_only(data, bed_temperature, chamber_temp, heated_chamber, heating_zone, max_y, max_z, speed_travel) return data - def _anneal_print(self, anneal_data: str, park_xy: bool, park_z: bool, bed_temperature:int, lowest_temp: int, heated_chamber: bool, chamber_temp: str, max_x: str, max_y: str, max_z: str, speed_travel: str, add_messages: bool, anneal_type: str): + def _anneal_print( + self, + add_messages: bool, + anneal_data: str, + bed_temperature: int, + chamber_temp: str, + heated_chamber: bool, + heating_zone: str, + lowest_temp: int, + max_x: str, + max_y: str, + max_z: str, + park_xy: bool, + park_z: bool, + speed_travel: str) -> str: """ - The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. The bed is allowed to cool down over a period of time. + The procedure disables the M140 (and M141) lines at the end of the print, and adds additional bed (and chamber) temperature commands to the end of the G-Code file. + The bed is allowed to cool down over a period of time. + + :param add_messages: Whether to include M117 and M118 messages for LCD and print server + :param anneal_data: The G-code data to be modified with annealing commands + :param bed_temperature: Starting bed temperature in degrees Celsius + :param chamber_temp: Chamber/build volume temperature in degrees Celsius as string + :param heated_chamber: Whether the printer has a heated build volume/chamber + :param heating_zone: Zone selection - "bed_only" or "bed_chamber" + :param lowest_temp: Final shutdown temperature in degrees Celsius + :param max_x: Maximum X axis position for parking as string + :param max_y: Maximum Y axis position for parking as string + :param max_z: Maximum Z axis position (machine height - 20mm) as string + :param park_xy: Whether to park the print head at max X and Y positions + :param park_z: Whether to raise Z to maximum safe height + :param speed_travel: Travel speed for positioning moves in mm/min as string + :return: Modified G-code data with annealing cooldown sequence """ # Put the head parking string together bed_temp_during_print = int(self.global_stack.getProperty("material_bed_temperature", "value")) @@ -326,7 +357,7 @@ class AnnealingOrDrying(Script): # Calculate the temperature differential hysteresis = bed_temperature - lowest_temp - # if the bed temp is below the shutoff temp then exit + # Exit if the bed temp is below the shutoff temp if hysteresis <= 0: anneal_data[0] += "; Anneal or Dry Filament did not run. Bed Temp < Shutoff Temp\n" Message(title = "Anneal or Dry Filament", text = "Did not run because the Bed Temp < Shutoff Temp.").show() @@ -351,9 +382,9 @@ class AnnealingOrDrying(Script): if wait_time > 0: # Add the parking string BEFORE the M190 anneal_string += park_string - if anneal_type == "bed_only": + if heating_zone == "bed_only": anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\n{self.beep_string}" - if anneal_type == "bed_chamber": + if heating_zone == "bed_chamber": anneal_string += f"M190 S{bed_temperature} ; Set the bed temp\nM141 S{chamber_temp} ; Set the chamber temp\n{self.beep_string}" anneal_string += f"G4 S{wait_time} ; Hold for {round(wait_time / 3600,2)} hrs\n" else: @@ -368,7 +399,7 @@ class AnnealingOrDrying(Script): # Step the bed/chamber temps down and add each step to the anneal string. The chamber remains at it's temperature until the bed gets down to that temperature. for num in range(bed_temperature, lowest_temp, -3): anneal_string += f"M140 S{step_down} ; Step down bed\n" - if anneal_type == "bed_chamber" and int(step_down) < int(chamber_temp): + if heating_zone == "bed_chamber" and int(step_down) < int(chamber_temp): anneal_string += f"M141 S{step_down} ; Step down chamber\n" anneal_string += f"G4 S{time_per_step} ; Wait\n" if time_remaining >= 1.00: @@ -388,7 +419,7 @@ class AnnealingOrDrying(Script): # Close out the anneal string anneal_string += "M140 S0 ; Shut off the bed heater" + "\n" - if anneal_type == "bed_chamber": + if heating_zone == "bed_chamber": anneal_string += "M141 S0 ; Shut off the chamber heater\n" anneal_string += self.bv_fan_off_str anneal_string += self.beep_string @@ -416,7 +447,7 @@ class AnnealingOrDrying(Script): anneal_data[-1] = "\n".join(end_lines) # If there is a Heated Chamber and it's included then comment out the M141 S0 line - if anneal_type == "bed_chamber" and heated_chamber: + if heating_zone == "bed_chamber" and heated_chamber: for num in range(0,len(end_lines)-1): if end_lines[num].startswith("M141 S0"): end_lines[num] = ";M141 S0 ; Shutoff Overide - Anneal or Dry Filament" @@ -438,9 +469,30 @@ class AnnealingOrDrying(Script): anneal_data[-1] = anneal_data[-1].replace(";End of Gcode", anneal_string + disable_string + ";End of Gcode") return anneal_data - def _dry_filament_only(self, drydata: str, anneal_type: str, heated_chamber: bool, chamber_temp: int, bed_temperature: int, max_z:str, max_y:str, speed_travel: str) -> str: + def _dry_filament_only( + self, + bed_temperature: int, + chamber_temp: int, + drydata: str, + heated_chamber: bool, + heating_zone: str, + max_y: str, + max_z: str, + speed_travel: str) -> str: """ - This procedure turns the bed on, homes the printer, parks the head. After the time period the bed is turned off. There is no actual print in the generated gcode, just a couple of moves to get the nozzle out of the way, and the bed heat (and possibly chamber heat) control. It allows a user to use the bed to warm up and hopefully dry a filament roll. + This procedure turns the bed on, homes the printer, parks the head. After the time period the bed is turned off. + There is no actual print in the generated gcode, just a couple of moves to get the nozzle out of the way, and the bed heat (and possibly chamber heat) control. + It allows a user to use the bed to warm up and hopefully dry a filament roll. + + :param bed_temperature: Bed temperature for drying in degrees Celsius + :param chamber_temp: Chamber/build volume temperature for drying in degrees Celsius + :param drydata: The G-code data to be replaced with filament drying commands + :param heated_chamber: Whether the printer has a heated build volume/chamber + :param heating_zone: Zone selection - "bed_only" or "bed_chamber" + :param max_y: Maximum Y axis position for parking as string + :param max_z: Maximum Z axis position (machine height - 20mm) as string + :param speed_travel: Travel speed for positioning moves in mm/min as string + :return: Modified G-code data containing only filament drying sequence """ for num in range(2, len(drydata)): drydata[num] = "" @@ -461,7 +513,7 @@ class AnnealingOrDrying(Script): drying_string += f"M84 S{round(dry_time)} ; Set stepper timeout\n" drying_string += f"M140 S{bed_temperature} ; Heat bed\n" drying_string += self.bv_fan_on_str - if heated_chamber and anneal_type == "bed_chamber": + if heated_chamber and heating_zone == "bed_chamber": drying_string += f"M141 S{chamber_temp} ; Chamber temp\n" if pause_cmd == "M0": pause_cmd = "M0 Clear bed and click...; Pause" @@ -489,7 +541,7 @@ class AnnealingOrDrying(Script): drying_string += f"M117 {temp_time/3600} hr remaining ; Message\n" drying_string += f"M118 {temp_time/3600} hr remaining ; Message\n" drying_string += f"G4 S{temp_time} ; Dry time\n" - if heated_chamber and anneal_type == "bed_chamber": + if heated_chamber and heating_zone == "bed_chamber": drying_string += f"M141 S0 ; Shut off chamber\n" drying_string += "M140 S0 ; Shut off bed\n" drying_string += self.bv_fan_off_str @@ -512,8 +564,8 @@ class AnnealingOrDrying(Script): drydata[1] = "\n".join(lines) + "\n" dry_txt = "; Drying time ...................... " + str(self.getSettingValueByKey("dry_time")) + " hrs\n" dry_txt += "; Drying temperature ........ " + str(bed_temperature) + "°\n" - if heated_chamber and anneal_type == "bed_chamber": + if heated_chamber and heating_zone == "bed_chamber": dry_txt += "; Chamber temperature ... " + str(chamber_temp) + "°\n" Message(title = "[Dry Filament]", text = dry_txt).show() drydata[0] = "; <<< This is a filament drying file only. There is no actual print. >>>\n;\n" + dry_txt + ";\n" - return drydata \ No newline at end of file + return drydata From 969cbf09e3c7ce62b1df80925f673074f36efa1e Mon Sep 17 00:00:00 2001 From: THeijmans Date: Thu, 21 Aug 2025 15:22:59 +0200 Subject: [PATCH 24/25] PP-650 R3 --- resources/definitions/ultimaker_s8.def.json | 11 ++++--- ...aa_plus_0.4_abs_0.2mm_engineering.inst.cfg | 3 ++ ...um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg | 5 +++ ...us_0.4_cpe-plus_0.2mm_engineering.inst.cfg | 3 ++ ...aa_plus_0.4_cpe_0.2mm_engineering.inst.cfg | 3 ++ ..._aa_plus_0.4_pc_0.2mm_engineering.inst.cfg | 3 ++ ...a_plus_0.4_petg_0.2mm_engineering.inst.cfg | 3 ++ ...m_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg | 5 +++ ...aa_plus_0.4_pla_0.2mm_engineering.inst.cfg | 3 ++ ...um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg | 5 +++ ...s_0.4_tough-pla_0.2mm_engineering.inst.cfg | 3 ++ ...aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg | 5 +++ ...us_0.4_cpe-plus_0.2mm_engineering.inst.cfg | 3 ++ ..._nylon-cf-slide_0.2mm_engineering.inst.cfg | 3 ++ ..._cc_plus_0.4_pc_0.2mm_engineering.inst.cfg | 3 ++ ..._plus_0.4_petcf_0.2mm_engineering.inst.cfg | 3 ++ ..._nylon-cf-slide_0.2mm_engineering.inst.cfg | 3 ++ ..._plus_0.6_petcf_0.2mm_engineering.inst.cfg | 3 ++ .../um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg | 3 ++ .../um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg | 3 ++ .../um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg | 3 ++ .../um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg | 3 ++ .../um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg | 3 ++ ...m_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg | 3 ++ ...um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg | 3 ++ ...um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg | 3 ++ ..._cc_plus_0.4_nylon-cf-slide_0.2mm.inst.cfg | 31 ++++++++++++++++++- .../um_s8_cc_plus_0.4_petcf_0.2mm.inst.cfg | 31 +++++++++++++++++++ 28 files changed, 151 insertions(+), 5 deletions(-) diff --git a/resources/definitions/ultimaker_s8.def.json b/resources/definitions/ultimaker_s8.def.json index cbd6e255f8..48f89a5502 100644 --- a/resources/definitions/ultimaker_s8.def.json +++ b/resources/definitions/ultimaker_s8.def.json @@ -237,7 +237,9 @@ "default_material_print_temperature": { "maximum_value_warning": 320 }, "extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" }, "flooring_layer_count": { "value": 1 }, - "gradual_flow_enabled": { "value": false }, + "flooring_material_flow": { "value": "skin_material_flow * 110/93" }, + "gradual_flow_discretisation_step_size": { "value": 1 }, + "gradual_flow_enabled": { "value": true }, "hole_xy_offset": { "value": 0.075 }, "infill_material_flow": { "value": "material_flow if infill_sparse_density < 95 else 95" }, "infill_overlap": { "value": 10 }, @@ -428,7 +430,7 @@ }, "material_print_temperature": { "maximum_value_warning": 320 }, "material_print_temperature_layer_0": { "maximum_value_warning": 320 }, - "max_flow_acceleration": { "value": 8.0 }, + "max_flow_acceleration": { "value": 1.5 }, "max_skin_angle_for_expansion": { "value": 45 }, "meshfix_maximum_resolution": { "value": 0.4 }, "min_infill_area": { "default_value": 10 }, @@ -444,6 +446,7 @@ "retraction_hop_enabled": { "value": true }, "retraction_min_travel": { "value": "2.5 if support_enable and support_structure=='tree' else line_width * 2.5" }, "retraction_prime_speed": { "value": 15 }, + "seam_overhang_angle": { "value": 35 }, "skin_edge_support_thickness": { "value": 0 }, "skin_material_flow": { "value": 93 }, "skin_outline_count": { "value": 0 }, @@ -543,12 +546,12 @@ "speed_wall": { "maximum_value_warning": 300, - "value": "speed_print*2/3" + "value": "speed_print*1/2" }, "speed_wall_0": { "maximum_value_warning": 300, - "value": "speed_wall" + "value": "speed_wall*60/75" }, "speed_wall_0_flooring": { diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_engineering.inst.cfg index 1d1cae70e6..7bbf373b2e 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = AA+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg index 9889424797..fe4b0497e1 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm_quick.inst.cfg @@ -16,7 +16,12 @@ cool_min_layer_time = 5 cool_min_layer_time_overhang = 9 cool_min_speed = 6 cool_min_temperature = =material_print_temperature - 15 +gradual_flow_enable = False +hole_xy_offset = 0.075 +inset_direction = outside-in +speed_wall = =speed_print speed_wall_x = =speed_print speed_wall_x_roofing = =speed_wall wall_line_width_x = =wall_line_width +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg index 21e814e112..d01f907d33 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = AA+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe_0.2mm_engineering.inst.cfg index f52cdf8124..7a96aa3f79 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_cpe_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = AA+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pc_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pc_0.2mm_engineering.inst.cfg index 8332ecacbc..1b666e4d83 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pc_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pc_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = AA+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_engineering.inst.cfg index 4c4490876f..3dd4ef5f01 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = AA+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg index ae38c02395..0fe5944438 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm_quick.inst.cfg @@ -16,7 +16,12 @@ cool_min_layer_time = 5 cool_min_layer_time_overhang = 9 cool_min_speed = 6 cool_min_temperature = =material_print_temperature - 15 +gradual_flow_enable = False +hole_xy_offset = 0.075 +inset_direction = outside-in +speed_wall = =speed_print speed_wall_x = =speed_print speed_wall_x_roofing = =speed_wall wall_line_width_x = =wall_line_width +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_engineering.inst.cfg index 484b9536a6..d2bbcf226e 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = AA+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg index 4509317076..a4730213de 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm_quick.inst.cfg @@ -16,7 +16,12 @@ cool_min_layer_time = 5 cool_min_layer_time_overhang = 9 cool_min_speed = 6 cool_min_temperature = =material_print_temperature - 15 +gradual_flow_enable = False +hole_xy_offset = 0.075 +inset_direction = outside-in +speed_wall = =speed_print speed_wall_x = =speed_print speed_wall_x_roofing = =speed_wall wall_line_width_x = =wall_line_width +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_engineering.inst.cfg index c5b81e4a4c..ed68baf7b1 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = AA+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg index 4f75b631df..908ecae7ed 100644 --- a/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm_quick.inst.cfg @@ -16,7 +16,12 @@ cool_min_layer_time = 5 cool_min_layer_time_overhang = 9 cool_min_speed = 6 cool_min_temperature = =material_print_temperature - 15 +gradual_flow_enable = False +hole_xy_offset = 0.075 +inset_direction = outside-in +speed_wall = =speed_print speed_wall_x = =speed_print speed_wall_x_roofing = =speed_wall wall_line_width_x = =wall_line_width +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg index 832912a022..0252cd6eb5 100644 --- a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_cpe-plus_0.2mm_engineering.inst.cfg @@ -13,7 +13,10 @@ type = intent variant = CC+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm_engineering.inst.cfg index a0e65969e9..2ce40b3df1 100644 --- a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm_engineering.inst.cfg @@ -13,7 +13,10 @@ type = intent variant = CC+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_pc_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_pc_0.2mm_engineering.inst.cfg index f40d2509b6..cb3c7bbac2 100644 --- a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_pc_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_pc_0.2mm_engineering.inst.cfg @@ -13,7 +13,10 @@ type = intent variant = CC+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm_engineering.inst.cfg index 824018a1d5..706c77e91a 100644 --- a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm_engineering.inst.cfg @@ -13,7 +13,10 @@ type = intent variant = CC+ 0.4 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_nylon-cf-slide_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_nylon-cf-slide_0.2mm_engineering.inst.cfg index 8cbb513108..57dfaa8f45 100644 --- a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_nylon-cf-slide_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_nylon-cf-slide_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = CC+ 0.6 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_petcf_0.2mm_engineering.inst.cfg b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_petcf_0.2mm_engineering.inst.cfg index 5384f380ac..9f2ddc6be5 100644 --- a/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_petcf_0.2mm_engineering.inst.cfg +++ b/resources/intent/ultimaker_s8/um_s8_cc_plus_0.6_petcf_0.2mm_engineering.inst.cfg @@ -12,7 +12,10 @@ type = intent variant = CC+ 0.6 [values] +hole_xy_offset = 0.075 infill_sparse_density = 20 +inset_direction = outside-in top_bottom_thickness = =wall_thickness wall_thickness = =line_width * 4 +xy_offset = 0.075 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg index cc5e850220..23863493e9 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg @@ -15,9 +15,12 @@ weight = -2 cool_min_layer_time = 4 cool_min_layer_time_fan_speed_max = 9 cool_min_temperature = =material_print_temperature - 20 +hole_xy_offset = 0.1 +inset_direction = inside-out retraction_prime_speed = 15 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg index 9abcd5ddd2..c739be3112 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg @@ -13,9 +13,12 @@ weight = -2 [values] cool_min_layer_time = 4 +hole_xy_offset = 0.1 +inset_direction = inside-out material_print_temperature = =default_material_print_temperature + 5 retraction_prime_speed = 15 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg index 9feab61e0e..e206c6ca7c 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg @@ -13,6 +13,8 @@ weight = -1 [values] cool_min_temperature = =material_print_temperature - 20 +hole_xy_offset = 0.1 +inset_direction = inside-out material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed @@ -20,4 +22,5 @@ speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg index 8431bb9c43..19575814fd 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg @@ -13,6 +13,8 @@ weight = 0 [values] cool_min_temperature = =material_print_temperature - 20 +hole_xy_offset = 0.1 +inset_direction = inside-out material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed @@ -21,4 +23,5 @@ speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree top_bottom_thickness = =round(6*layer_height,3) wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg index 7a5d19dc2c..72132baab2 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg @@ -13,6 +13,8 @@ weight = -2 [values] cool_min_temperature = =material_print_temperature - 20 +hole_xy_offset = 0.1 +inset_direction = inside-out material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed @@ -20,4 +22,5 @@ speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg index f17d3fde40..c7daafbcf6 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg @@ -13,10 +13,13 @@ weight = -1 [values] cool_min_temperature = =material_print_temperature - 20 +hole_xy_offset = 0.1 +inset_direction = inside-out retraction_prime_speed = =retraction_speed retraction_speed = 25 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg index 672eae3e4a..ffcdbf79e3 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg @@ -13,10 +13,13 @@ weight = 0 [values] cool_min_temperature = =material_print_temperature - 20 +hole_xy_offset = 0.1 +inset_direction = inside-out retraction_prime_speed = =retraction_speed speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree top_bottom_thickness = =round(6*layer_height,3) wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg index 716765aac5..9dc8f752d8 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg @@ -13,9 +13,12 @@ weight = -2 [values] cool_min_temperature = =material_print_temperature - 20 +hole_xy_offset = 0.1 +inset_direction = inside-out retraction_prime_speed = =retraction_speed speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree wall_line_width_x = =wall_line_width * 1.25 +xy_offset = 0.025 diff --git a/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm.inst.cfg index 5f3180ef4e..04249a0af3 100644 --- a/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_nylon-cf-slide_0.2mm.inst.cfg @@ -13,12 +13,41 @@ variant = CC+ 0.4 weight = -2 [values] +acceleration_roofing = =acceleration_topbottom/2 +bridge_enable_more_layers = True +bridge_skin_density = 70 bridge_skin_material_flow = 100 +bridge_skin_material_flow_2 = 70 bridge_skin_speed = 30 +bridge_skin_speed_2 = =speed_print*2/3 bridge_wall_material_flow = 100 +bridge_wall_min_length = 2 bridge_wall_speed = 30 +cool_min_layer_time = 6 cool_min_layer_time_fan_speed_max = 11 -retraction_prime_speed = 15 +cool_min_layer_time_overhang = 11 +cool_min_temperature = =material_print_temperature-10 +flooring_monotonic = False +infill_material_flow = =material_flow if infill_sparse_density < 95 else 95 +infill_pattern = ='zigzag' if infill_sparse_density > 50 else 'grid' +jerk_roofing = =jerk_print +material_flow = 95 +retraction_hop_enabled = False +retraction_prime_speed = 25 +roofing_material_flow = =skin_material_flow +roofing_monotonic = False +skin_material_flow = =0.95*material_flow +skin_outline_count = 0 +support_bottom_distance = =support_z_distance support_structure = tree +support_tree_tip_diameter = 2.0 +support_tree_top_rate = 10 +support_xy_distance = 1.2 +support_xy_distance_overhang = =1.5*machine_nozzle_size +support_z_distance = =min(2*layer_height, 0.4) +top_bottom_thickness = =wall_thickness +wall_0_inset = =0.05 wall_overhang_speed_factors = [100,90,80,70,60,50] +wall_x_material_flow = =material_flow +xy_offset = 0.075 diff --git a/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm.inst.cfg index 3467ed5ded..664748835f 100644 --- a/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_cc_plus_0.4_petcf_0.2mm.inst.cfg @@ -13,12 +13,43 @@ variant = CC+ 0.4 weight = -2 [values] +acceleration_roofing = =acceleration_topbottom/2 adhesion_type = skirt +bridge_enable_more_layers = True +bridge_skin_density = 70 bridge_skin_material_flow = 100 +bridge_skin_material_flow_2 = 70 bridge_skin_speed = 30 +bridge_skin_speed_2 = =speed_print*2/3 bridge_wall_material_flow = 100 +bridge_wall_min_length = 2 bridge_wall_speed = 30 +cool_min_layer_time = 6 +cool_min_layer_time_overhang = 11 +cool_min_temperature = =material_print_temperature-10 +flooring_monotonic = False +infill_material_flow = =material_flow if infill_sparse_density < 95 else 95 +infill_pattern = ='zigzag' if infill_sparse_density > 50 else 'grid' +jerk_roofing = =jerk_print +material_pressure_advance_factor = 0.25 +retraction_hop_enabled = False +retraction_prime_speed = 15 +roofing_material_flow = =skin_material_flow +roofing_monotonic = False +skin_material_flow = =0.95*material_flow +skin_outline_count = 0 +skirt_height = 5 +support_bottom_distance = =support_z_distance support_structure = tree +support_tree_tip_diameter = 2.0 +support_tree_top_rate = 10 +support_xy_distance = 1.2 +support_xy_distance_overhang = =1.5*machine_nozzle_size +support_z_distance = =min(2*layer_height, 0.4) switch_extruder_retraction_amount = 16 +top_bottom_thickness = =wall_thickness +wall_0_inset = =0.05 wall_overhang_speed_factors = [100,90,80,70,60,50] +wall_x_material_flow = =material_flow +xy_offset = 0.075 From 28f2e4fb499b47fbe28f2899400a296f23e0cd7f Mon Sep 17 00:00:00 2001 From: THeijmans Date: Fri, 29 Aug 2025 14:36:59 +0200 Subject: [PATCH 25/25] PP-650 R5 --- resources/definitions/ultimaker_s8.def.json | 5 ++++- .../ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg | 1 + .../ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg | 1 + .../ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg | 1 + .../ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg | 1 + .../ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg | 1 + .../ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg | 1 + .../ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg | 1 + .../ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg | 1 + 9 files changed, 12 insertions(+), 1 deletion(-) diff --git a/resources/definitions/ultimaker_s8.def.json b/resources/definitions/ultimaker_s8.def.json index 48f89a5502..165a7719b2 100644 --- a/resources/definitions/ultimaker_s8.def.json +++ b/resources/definitions/ultimaker_s8.def.json @@ -238,6 +238,7 @@ "extra_infill_lines_to_support_skins": { "value": "'walls_and_lines'" }, "flooring_layer_count": { "value": 1 }, "flooring_material_flow": { "value": "skin_material_flow * 110/93" }, + "flooring_monotonic": { "value": false }, "gradual_flow_discretisation_step_size": { "value": 1 }, "gradual_flow_enabled": { "value": true }, "hole_xy_offset": { "value": 0.075 }, @@ -446,11 +447,13 @@ "retraction_hop_enabled": { "value": true }, "retraction_min_travel": { "value": "2.5 if support_enable and support_structure=='tree' else line_width * 2.5" }, "retraction_prime_speed": { "value": 15 }, + "roofing_monotonic": { "value": false }, + "roofing_pattern": { "value": "'zigzag'" }, "seam_overhang_angle": { "value": 35 }, "skin_edge_support_thickness": { "value": 0 }, "skin_material_flow": { "value": 93 }, "skin_outline_count": { "value": 0 }, - "skin_overlap": { "value": 0 }, + "skin_overlap": { "value": 20 }, "skin_preshrink": { "value": 0 }, "skirt_brim_minimal_length": { "value": 1000 }, "skirt_brim_speed": diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg index 23863493e9..014a2012c8 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_abs_0.2mm.inst.cfg @@ -18,6 +18,7 @@ cool_min_temperature = =material_print_temperature - 20 hole_xy_offset = 0.1 inset_direction = inside-out retraction_prime_speed = 15 +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg index c739be3112..9e9320d45d 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_petg_0.2mm.inst.cfg @@ -17,6 +17,7 @@ hole_xy_offset = 0.1 inset_direction = inside-out material_print_temperature = =default_material_print_temperature + 5 retraction_prime_speed = 15 +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 wall_line_width_x = =wall_line_width * 1.25 diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg index e206c6ca7c..a63f0371b4 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.15mm.inst.cfg @@ -18,6 +18,7 @@ inset_direction = inside-out material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg index 19575814fd..b9ed1a649a 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.1mm.inst.cfg @@ -18,6 +18,7 @@ inset_direction = inside-out material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg index 72132baab2..8ab383a08d 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_pla_0.2mm.inst.cfg @@ -18,6 +18,7 @@ inset_direction = inside-out material_final_print_temperature = =material_print_temperature - 15 material_initial_print_temperature = =material_print_temperature - 15 retraction_prime_speed = =retraction_speed +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg index c7daafbcf6..2f48c95b7b 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.15mm.inst.cfg @@ -17,6 +17,7 @@ hole_xy_offset = 0.1 inset_direction = inside-out retraction_prime_speed = =retraction_speed retraction_speed = 25 +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg index ffcdbf79e3..d32f2466ea 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.1mm.inst.cfg @@ -16,6 +16,7 @@ cool_min_temperature = =material_print_temperature - 20 hole_xy_offset = 0.1 inset_direction = inside-out retraction_prime_speed = =retraction_speed +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree diff --git a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg index 9dc8f752d8..a7eebb69be 100644 --- a/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg +++ b/resources/quality/ultimaker_s8/um_s8_aa_plus_0.4_tough-pla_0.2mm.inst.cfg @@ -16,6 +16,7 @@ cool_min_temperature = =material_print_temperature - 20 hole_xy_offset = 0.1 inset_direction = inside-out retraction_prime_speed = =retraction_speed +speed_roofing = =speed_topbottom * 1/3 speed_wall_x = =speed_wall speed_wall_x_roofing = =speed_wall * 0.8 support_structure = tree