mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 15:59:02 +08:00
Merge remote-tracking branch 'origin/main' into PP-71_improved-minimum-layer-time-behaviour
This commit is contained in:
commit
aed56a489a
@ -1,8 +1,12 @@
|
|||||||
# Copyright (c) 2021 Ultimaker B.V.
|
# Copyright (c) 2023 UltiMaker
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from ..Script import Script
|
# Revised by GregValiant 10-17-2022
|
||||||
|
# Changed "extrude" line to before the nozzle moves back to the print (if not Repetier or Griffin).
|
||||||
|
# Add M104 option for Resume temperature
|
||||||
|
|
||||||
|
from ..Script import Script
|
||||||
|
import re
|
||||||
from UM.Application import Application #To get the current printer's settings.
|
from UM.Application import Application #To get the current printer's settings.
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
|
||||||
@ -42,7 +46,7 @@ class PauseAtHeight(Script):
|
|||||||
"pause_layer":
|
"pause_layer":
|
||||||
{
|
{
|
||||||
"label": "Pause Layer",
|
"label": "Pause Layer",
|
||||||
"description": "At what layer should the pause occur?",
|
"description": "Enter the Number of the LAST layer you want to finish prior to the pause (from the Cura preview).",
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"value": "math.floor((pause_height - 0.27) / 0.1) + 1",
|
"value": "math.floor((pause_height - 0.27) / 0.1) + 1",
|
||||||
"minimum_value": "0",
|
"minimum_value": "0",
|
||||||
@ -156,6 +160,14 @@ class PauseAtHeight(Script):
|
|||||||
"type": "bool",
|
"type": "bool",
|
||||||
"default_value": false
|
"default_value": false
|
||||||
},
|
},
|
||||||
|
"standby_wait_for_temperature_enabled":
|
||||||
|
{
|
||||||
|
"label": "Use M109 for standby temperature? (M104 when false)",
|
||||||
|
"description": "Wait for hot end after Resume? (If your standby temperature is lower than the Printing temperature CHECK and use M109",
|
||||||
|
"type": "bool",
|
||||||
|
"default_value": true,
|
||||||
|
"enabled": "pause_method not in [\\\"griffin\\\", \\\"repetier\\\"]"
|
||||||
|
},
|
||||||
"standby_temperature":
|
"standby_temperature":
|
||||||
{
|
{
|
||||||
"label": "Standby Temperature",
|
"label": "Standby Temperature",
|
||||||
@ -220,14 +232,14 @@ class PauseAtHeight(Script):
|
|||||||
"custom_gcode_before_pause":
|
"custom_gcode_before_pause":
|
||||||
{
|
{
|
||||||
"label": "G-code Before Pause",
|
"label": "G-code Before Pause",
|
||||||
"description": "Any custom g-code to run before the pause, for example, M300 S440 P200 to beep.",
|
"description": "Custom g-code to run before the pause. EX: M300 to beep. Use a comma to separate multiple commands. EX: M400,M300,M117 Pause",
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"default_value": ""
|
"default_value": ""
|
||||||
},
|
},
|
||||||
"custom_gcode_after_pause":
|
"custom_gcode_after_pause":
|
||||||
{
|
{
|
||||||
"label": "G-code After Pause",
|
"label": "G-code After Pause",
|
||||||
"description": "Any custom g-code to run after the pause, for example, M300 S440 P200 to beep.",
|
"description": "Custom g-code to run after the pause. Use a comma to separate multiple commands. EX: M204 X8 Y8,M106 S0,M117 Resume",
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"default_value": ""
|
"default_value": ""
|
||||||
}
|
}
|
||||||
@ -279,13 +291,14 @@ class PauseAtHeight(Script):
|
|||||||
move_z = self.getSettingValueByKey("head_move_z")
|
move_z = self.getSettingValueByKey("head_move_z")
|
||||||
layers_started = False
|
layers_started = False
|
||||||
redo_layer = self.getSettingValueByKey("redo_layer")
|
redo_layer = self.getSettingValueByKey("redo_layer")
|
||||||
|
standby_wait_for_temperature_enabled = self.getSettingValueByKey("standby_wait_for_temperature_enabled")
|
||||||
standby_temperature = self.getSettingValueByKey("standby_temperature")
|
standby_temperature = self.getSettingValueByKey("standby_temperature")
|
||||||
firmware_retract = Application.getInstance().getGlobalContainerStack().getProperty("machine_firmware_retract", "value")
|
firmware_retract = Application.getInstance().getGlobalContainerStack().getProperty("machine_firmware_retract", "value")
|
||||||
control_temperatures = Application.getInstance().getGlobalContainerStack().getProperty("machine_nozzle_temp_enabled", "value")
|
control_temperatures = Application.getInstance().getGlobalContainerStack().getProperty("machine_nozzle_temp_enabled", "value")
|
||||||
initial_layer_height = Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")
|
initial_layer_height = Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")
|
||||||
display_text = self.getSettingValueByKey("display_text")
|
display_text = self.getSettingValueByKey("display_text")
|
||||||
gcode_before = self.getSettingValueByKey("custom_gcode_before_pause")
|
gcode_before = re.sub("\\s*,\\s*", "\n", self.getSettingValueByKey("custom_gcode_before_pause"))
|
||||||
gcode_after = self.getSettingValueByKey("custom_gcode_after_pause")
|
gcode_after = re.sub("\\s*,\\s*", "\n", self.getSettingValueByKey("custom_gcode_after_pause"))
|
||||||
beep_at_pause = self.getSettingValueByKey("beep_at_pause")
|
beep_at_pause = self.getSettingValueByKey("beep_at_pause")
|
||||||
beep_length = self.getSettingValueByKey("beep_length")
|
beep_length = self.getSettingValueByKey("beep_length")
|
||||||
|
|
||||||
@ -477,14 +490,14 @@ class PauseAtHeight(Script):
|
|||||||
|
|
||||||
# Set a custom GCODE section before pause
|
# Set a custom GCODE section before pause
|
||||||
if gcode_before:
|
if gcode_before:
|
||||||
prepend_gcode += gcode_before.replace(";","\n") + "\n"
|
prepend_gcode += gcode_before + "\n"
|
||||||
|
|
||||||
# Wait till the user continues printing
|
# Wait till the user continues printing
|
||||||
prepend_gcode += pause_command + " ; Do the actual pause\n"
|
prepend_gcode += pause_command + " ; Do the actual pause\n"
|
||||||
|
|
||||||
# Set a custom GCODE section after pause
|
# Set a custom GCODE section after pause
|
||||||
if gcode_after:
|
if gcode_after:
|
||||||
prepend_gcode += gcode_after.replace(";","\n") + "\n"
|
prepend_gcode += gcode_after + "\n"
|
||||||
|
|
||||||
if pause_method == "repetier":
|
if pause_method == "repetier":
|
||||||
#Push the filament back,
|
#Push the filament back,
|
||||||
@ -530,19 +543,23 @@ class PauseAtHeight(Script):
|
|||||||
elif pause_method != "griffin":
|
elif pause_method != "griffin":
|
||||||
if control_temperatures:
|
if control_temperatures:
|
||||||
# Set extruder resume temperature
|
# Set extruder resume temperature
|
||||||
prepend_gcode += self.putValue(M = 109, S = int(target_temperature.get(current_t, 0))) + " ; resume temperature\n"
|
if standby_wait_for_temperature_enabled:
|
||||||
|
WFT_numeric = 109
|
||||||
|
Temp_resume_Text = " ; WAIT for resume temperature\n"
|
||||||
|
else:
|
||||||
|
WFT_numeric = 104
|
||||||
|
Temp_resume_Text = " ; resume temperature\n"
|
||||||
|
|
||||||
|
prepend_gcode += self.putValue(M=WFT_numeric,
|
||||||
|
S=int(target_temperature.get(current_t, 0))) + Temp_resume_Text
|
||||||
|
|
||||||
if extrude_amount != 0: # Need to prime after the pause.
|
if extrude_amount != 0: # Need to prime after the pause.
|
||||||
# Push the filament back.
|
# Push the filament back.
|
||||||
if retraction_amount != 0:
|
if extrude_speed == 0:
|
||||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
|
extrude_speed = 25
|
||||||
|
|
||||||
# Prime the material.
|
if extrude_amount != 0:
|
||||||
prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = extrude_speed * 60) + "; Extra extrude after the unpause\n"
|
prepend_gcode += self.putValue(G=1, E=extrude_amount, F=extrude_speed * 60) + "\n"
|
||||||
|
|
||||||
# And retract again to make the movements back to the starting position.
|
|
||||||
if retraction_amount != 0:
|
|
||||||
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
|
|
||||||
|
|
||||||
# Move the head back
|
# Move the head back
|
||||||
if park_enabled:
|
if park_enabled:
|
||||||
@ -556,8 +573,6 @@ class PauseAtHeight(Script):
|
|||||||
retraction_count = 1 if control_temperatures else 3 #Retract more if we don't control the temperature.
|
retraction_count = 1 if control_temperatures else 3 #Retract more if we don't control the temperature.
|
||||||
for i in range(retraction_count):
|
for i in range(retraction_count):
|
||||||
prepend_gcode += self.putValue(G = 11) + "\n"
|
prepend_gcode += self.putValue(G = 11) + "\n"
|
||||||
else:
|
|
||||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
|
|
||||||
|
|
||||||
if current_extrusion_f != 0:
|
if current_extrusion_f != 0:
|
||||||
prepend_gcode += self.putValue(G = 1, F = current_extrusion_f) + " ; restore extrusion feedrate\n"
|
prepend_gcode += self.putValue(G = 1, F = current_extrusion_f) + " ; restore extrusion feedrate\n"
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
# Copyright (c) 2019 Ultimaker B.V.
|
# Copyright (c) 2023 UltiMaker B.V.
|
||||||
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
|
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
from ..Script import Script
|
from ..Script import Script
|
||||||
|
|
||||||
|
from UM.Application import Application # To get current absolute/relative setting.
|
||||||
|
from UM.Math.Vector import Vector
|
||||||
|
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
|
|
||||||
class RetractContinue(Script):
|
class RetractContinue(Script):
|
||||||
"""Continues retracting during all travel moves."""
|
"""Continues retracting during all travel moves."""
|
||||||
|
|
||||||
def getSettingDataString(self):
|
def getSettingDataString(self) -> str:
|
||||||
return """{
|
return """{
|
||||||
"name": "Retract Continue",
|
"name": "Retract Continue",
|
||||||
"key": "RetractContinue",
|
"key": "RetractContinue",
|
||||||
@ -27,58 +30,90 @@ class RetractContinue(Script):
|
|||||||
}
|
}
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
def execute(self, data):
|
def _getTravelMove(self, travel_move: str, default_pos: Vector) -> Tuple[Vector, float]:
|
||||||
current_e = 0
|
travel = Vector(
|
||||||
current_x = 0
|
self.getValue(travel_move, "X", default_pos.x),
|
||||||
current_y = 0
|
self.getValue(travel_move, "Y", default_pos.y),
|
||||||
current_z = 0
|
self.getValue(travel_move, "Z", default_pos.z)
|
||||||
|
)
|
||||||
|
f = self.getValue(travel_move, "F", -1.0)
|
||||||
|
return travel, f
|
||||||
|
|
||||||
|
def _travelMoveString(self, travel: Vector, f: float, e: float) -> str:
|
||||||
|
# Note that only G1 moves are written, since extrusion is included.
|
||||||
|
if f <= 0.0:
|
||||||
|
return f"G1 X{travel.x:.5f} Y{travel.y:.5f} Z{travel.z:.5f} E{e:.5f}"
|
||||||
|
else:
|
||||||
|
return f"G1 F{f:.5f} X{travel.x:.5f} Y{travel.y:.5f} Z{travel.z:.5f} E{e:.5f}"
|
||||||
|
|
||||||
|
def execute(self, data: List[str]) -> List[str]:
|
||||||
|
current_e = 0.0
|
||||||
|
to_compensate = 0 # Used when extrusion mode is relative.
|
||||||
|
is_active = False # Whether retract-continue is in effect.
|
||||||
|
|
||||||
|
current_pos = Vector(0.0, 0.0, 0.0)
|
||||||
|
last_pos = Vector(0.0, 0.0, 0.0)
|
||||||
|
|
||||||
extra_retraction_speed = self.getSettingValueByKey("extra_retraction_speed")
|
extra_retraction_speed = self.getSettingValueByKey("extra_retraction_speed")
|
||||||
|
relative_extrusion = Application.getInstance().getGlobalContainerStack().getProperty(
|
||||||
|
"relative_extrusion", "value"
|
||||||
|
)
|
||||||
|
|
||||||
for layer_number, layer in enumerate(data):
|
for layer_number, layer in enumerate(data):
|
||||||
lines = layer.split("\n")
|
lines = layer.split("\n")
|
||||||
for line_number, line in enumerate(lines):
|
for line_number, line in enumerate(lines):
|
||||||
if self.getValue(line, "G") in {0, 1}: # Track X,Y,Z location.
|
|
||||||
current_x = self.getValue(line, "X", current_x)
|
|
||||||
current_y = self.getValue(line, "Y", current_y)
|
|
||||||
current_z = self.getValue(line, "Z", current_z)
|
|
||||||
if self.getValue(line, "G") == 1:
|
|
||||||
if not self.getValue(line, "E"): # Either None or 0: Not a retraction then.
|
|
||||||
continue
|
|
||||||
new_e = self.getValue(line, "E")
|
|
||||||
if new_e - current_e >= -0.0001: # Not a retraction. Account for floating point rounding errors.
|
|
||||||
current_e = new_e
|
|
||||||
continue
|
|
||||||
# A retracted travel move may consist of multiple commands, due to combing.
|
|
||||||
# This continues retracting over all of these moves and only unretracts at the end.
|
|
||||||
delta_line = 1
|
|
||||||
dx = current_x # Track the difference in X for this move only to compute the length of the travel.
|
|
||||||
dy = current_y
|
|
||||||
dz = current_z
|
|
||||||
while line_number + delta_line < len(lines) and self.getValue(lines[line_number + delta_line], "G") != 1:
|
|
||||||
travel_move = lines[line_number + delta_line]
|
|
||||||
if self.getValue(travel_move, "G") != 0:
|
|
||||||
delta_line += 1
|
|
||||||
continue
|
|
||||||
travel_x = self.getValue(travel_move, "X", dx)
|
|
||||||
travel_y = self.getValue(travel_move, "Y", dy)
|
|
||||||
travel_z = self.getValue(travel_move, "Z", dz)
|
|
||||||
f = self.getValue(travel_move, "F", "no f")
|
|
||||||
length = math.sqrt((travel_x - dx) * (travel_x - dx) + (travel_y - dy) * (travel_y - dy) + (travel_z - dz) * (travel_z - dz)) # Length of the travel move.
|
|
||||||
new_e -= length * extra_retraction_speed # New retraction is by ratio of this travel move.
|
|
||||||
if f == "no f":
|
|
||||||
new_travel_move = "G1 X{travel_x} Y{travel_y} Z{travel_z} E{new_e}".format(travel_x = travel_x, travel_y = travel_y, travel_z = travel_z, new_e = new_e)
|
|
||||||
else:
|
|
||||||
new_travel_move = "G1 F{f} X{travel_x} Y{travel_y} Z{travel_z} E{new_e}".format(f = f, travel_x = travel_x, travel_y = travel_y, travel_z = travel_z, new_e = new_e)
|
|
||||||
lines[line_number + delta_line] = new_travel_move
|
|
||||||
|
|
||||||
delta_line += 1
|
# Focus on move-type lines.
|
||||||
dx = travel_x
|
code_g = self.getValue(line, "G")
|
||||||
dy = travel_y
|
if code_g not in [0, 1]:
|
||||||
dz = travel_z
|
continue
|
||||||
|
|
||||||
current_e = new_e
|
# Track X,Y,Z location.
|
||||||
|
last_pos = last_pos.set(current_pos.x, current_pos.y, current_pos.z)
|
||||||
|
current_pos = current_pos.set(
|
||||||
|
self.getValue(line, "X", current_pos.x),
|
||||||
|
self.getValue(line, "Y", current_pos.y),
|
||||||
|
self.getValue(line, "Z", current_pos.z)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Track extrusion 'axis' position.
|
||||||
|
last_e = current_e
|
||||||
|
e_value = self.getValue(line, "E")
|
||||||
|
if e_value:
|
||||||
|
current_e = (current_e if relative_extrusion else 0) + e_value
|
||||||
|
|
||||||
|
# Handle lines: Detect retractions and compensate relative if G1, potential retract-continue if G0.
|
||||||
|
if code_g == 1:
|
||||||
|
if last_e > (current_e + 0.0001): # Account for floating point inaccuracies.
|
||||||
|
|
||||||
|
# There is a retraction, each following G0 command needs to continue the retraction.
|
||||||
|
is_active = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif relative_extrusion and is_active:
|
||||||
|
|
||||||
|
# If 'relative', the first G1 command after the total retraction will have to compensate more.
|
||||||
|
travel, f = self._getTravelMove(lines[line_number], current_pos)
|
||||||
|
lines[line_number] = self._travelMoveString(travel, f, to_compensate + e_value)
|
||||||
|
to_compensate = 0.0
|
||||||
|
|
||||||
|
# There is no retraction (see continue in the retract-clause) and everything else has been handled.
|
||||||
|
is_active = False
|
||||||
|
|
||||||
|
elif code_g == 0:
|
||||||
|
if not is_active:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# The retract-continue is active, so each G0 until the next extrusion needs to continue retraction.
|
||||||
|
travel, f = self._getTravelMove(lines[line_number], current_pos)
|
||||||
|
travel_length = (current_pos - last_pos).length()
|
||||||
|
extra_retract = travel_length * extra_retraction_speed
|
||||||
|
new_e = (0 if relative_extrusion else current_e) - extra_retract
|
||||||
|
to_compensate += extra_retract
|
||||||
|
current_e -= extra_retract
|
||||||
|
lines[line_number] = self._travelMoveString(travel, f, new_e)
|
||||||
|
|
||||||
new_layer = "\n".join(lines)
|
new_layer = "\n".join(lines)
|
||||||
data[layer_number] = new_layer
|
data[layer_number] = new_layer
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
BIN
plugins/UM3NetworkPrinting/resources/png/Ultimaker S7.png
Normal file
BIN
plugins/UM3NetworkPrinting/resources/png/Ultimaker S7.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 735 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user