FilamentChange.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. # Copyright (c) 2021 Ultimaker B.V.
  2. # The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
  3. # Modification 06.09.2020
  4. # add checkbox, now you can choose and use configuration from the firmware itself.
  5. from typing import List
  6. from ..Script import Script
  7. from UM.Application import Application #To get the current printer's settings.
  8. class FilamentChange(Script):
  9. _layer_keyword = ";LAYER:"
  10. def __init__(self):
  11. super().__init__()
  12. def getSettingDataString(self):
  13. return """{
  14. "name": "Filament Change",
  15. "key": "FilamentChange",
  16. "metadata": {},
  17. "version": 2,
  18. "settings":
  19. {
  20. "layer_number":
  21. {
  22. "label": "Layer",
  23. "description": "At what layer should color change occur. This will be before the layer starts printing. Specify multiple color changes with a comma.",
  24. "unit": "",
  25. "type": "str",
  26. "default_value": "1"
  27. },
  28. "firmware_config":
  29. {
  30. "label": "Use Firmware Configuration",
  31. "description": "Use the settings in your firmware, or customise the parameters of the filament change here.",
  32. "type": "bool",
  33. "default_value": false
  34. },
  35. "initial_retract":
  36. {
  37. "label": "Initial Retraction",
  38. "description": "Initial filament retraction distance. The filament will be retracted with this amount before moving the nozzle away from the ongoing print.",
  39. "unit": "mm",
  40. "type": "float",
  41. "default_value": 30.0,
  42. "enabled": "not firmware_config"
  43. },
  44. "later_retract":
  45. {
  46. "label": "Later Retraction Distance",
  47. "description": "Later filament retraction distance for removal. The filament will be retracted all the way out of the printer so that you can change the filament.",
  48. "unit": "mm",
  49. "type": "float",
  50. "default_value": 300.0,
  51. "enabled": "not firmware_config"
  52. },
  53. "x_position":
  54. {
  55. "label": "X Position",
  56. "description": "Extruder X position. The print head will move here for filament change.",
  57. "unit": "mm",
  58. "type": "float",
  59. "default_value": 0,
  60. "enabled": "not firmware_config"
  61. },
  62. "y_position":
  63. {
  64. "label": "Y Position",
  65. "description": "Extruder Y position. The print head will move here for filament change.",
  66. "unit": "mm",
  67. "type": "float",
  68. "default_value": 0,
  69. "enabled": "not firmware_config"
  70. },
  71. "z_position":
  72. {
  73. "label": "Z Position (relative)",
  74. "description": "Extruder relative Z position. Move the print head up for filament change.",
  75. "unit": "mm",
  76. "type": "float",
  77. "default_value": 0,
  78. "minimum_value": 0
  79. },
  80. "retract_method":
  81. {
  82. "label": "Retract method",
  83. "description": "The gcode variant to use for retract.",
  84. "type": "enum",
  85. "options": {"U": "Marlin (M600 U)", "L": "Reprap (M600 L)"},
  86. "default_value": "U",
  87. "value": "\\\"L\\\" if machine_gcode_flavor==\\\"RepRap (RepRap)\\\" else \\\"U\\\"",
  88. "enabled": "not firmware_config"
  89. },
  90. "machine_gcode_flavor":
  91. {
  92. "label": "G-code flavor",
  93. "description": "The type of g-code to be generated. This setting is controlled by the script and will not be visible.",
  94. "type": "enum",
  95. "options":
  96. {
  97. "RepRap (Marlin/Sprinter)": "Marlin",
  98. "RepRap (Volumetric)": "Marlin (Volumetric)",
  99. "RepRap (RepRap)": "RepRap",
  100. "UltiGCode": "Ultimaker 2",
  101. "Griffin": "Griffin",
  102. "Makerbot": "Makerbot",
  103. "BFB": "Bits from Bytes",
  104. "MACH3": "Mach3",
  105. "Repetier": "Repetier"
  106. },
  107. "default_value": "RepRap (Marlin/Sprinter)",
  108. "enabled": "false"
  109. }
  110. }
  111. }"""
  112. ## Copy machine name and gcode flavor from global stack so we can use their value in the script stack
  113. def initialize(self) -> None:
  114. super().initialize()
  115. global_container_stack = Application.getInstance().getGlobalContainerStack()
  116. if global_container_stack is None or self._instance is None:
  117. return
  118. for key in ["machine_gcode_flavor"]:
  119. self._instance.setProperty(key, "value", global_container_stack.getProperty(key, "value"))
  120. def execute(self, data: List[str]):
  121. """Inserts the filament change g-code at specific layer numbers.
  122. :param data: A list of layers of g-code.
  123. :return: A similar list, with filament change commands inserted.
  124. """
  125. layer_nums = self.getSettingValueByKey("layer_number")
  126. initial_retract = self.getSettingValueByKey("initial_retract")
  127. later_retract = self.getSettingValueByKey("later_retract")
  128. x_pos = self.getSettingValueByKey("x_position")
  129. y_pos = self.getSettingValueByKey("y_position")
  130. z_pos = self.getSettingValueByKey("z_position")
  131. firmware_config = self.getSettingValueByKey("firmware_config")
  132. color_change = "M600"
  133. if not firmware_config:
  134. if initial_retract is not None and initial_retract > 0.:
  135. color_change = color_change + (" E%.2f" % initial_retract)
  136. if later_retract is not None and later_retract > 0.:
  137. # Reprap uses 'L': https://reprap.org/wiki/G-code#M600:_Filament_change_pause
  138. # Marlin uses 'U' https://marlinfw.org/docs/gcode/M600.html
  139. retract_method = self.getSettingValueByKey("retract_method")
  140. color_change = color_change + (" %s%.2f" % (retract_method, later_retract))
  141. if x_pos is not None:
  142. color_change = color_change + (" X%.2f" % x_pos)
  143. if y_pos is not None:
  144. color_change = color_change + (" Y%.2f" % y_pos)
  145. if z_pos is not None and z_pos > 0.:
  146. color_change = color_change + (" Z%.2f" % z_pos)
  147. color_change = color_change + " ; Generated by FilamentChange plugin\n"
  148. layer_targets = layer_nums.split(",")
  149. if len(layer_targets) > 0:
  150. for layer_num in layer_targets:
  151. try:
  152. layer_num = int(layer_num.strip()) + 1 #Needs +1 because the 1st layer is reserved for start g-code.
  153. except ValueError: #Layer number is not an integer.
  154. continue
  155. if 0 < layer_num < len(data):
  156. data[layer_num] = color_change + data[layer_num]
  157. return data