FilamentChange.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. "enable_before_macro":
  111. {
  112. "label": "Enable macro Before filament change",
  113. "description": "Use this to insert a custom G-code macro before the filament change happens",
  114. "type": "bool",
  115. "default_value": false
  116. },
  117. "before_macro":
  118. {
  119. "label": "G-code Before",
  120. "description": "Any custom G-code to run before the filament change happens, for example, M300 S1000 P10000 for a long beep.",
  121. "unit": "",
  122. "type": "str",
  123. "default_value": "M300 S1000 P10000",
  124. "enabled": "enable_before_macro"
  125. },
  126. "enable_after_macro":
  127. {
  128. "label": "Enable macro After filament change",
  129. "description": "Use this to insert a custom G-code macro after the filament change",
  130. "type": "bool",
  131. "default_value": false
  132. },
  133. "after_macro":
  134. {
  135. "label": "G-code After",
  136. "description": "Any custom G-code to run after the filament has been changed right before continuing the print, for example, you can add a sequence to purge filament and wipe the nozzle.",
  137. "unit": "",
  138. "type": "str",
  139. "default_value": "M300 S440 P500",
  140. "enabled": "enable_after_macro"
  141. }
  142. }
  143. }"""
  144. ## Copy machine name and gcode flavor from global stack so we can use their value in the script stack
  145. def initialize(self) -> None:
  146. super().initialize()
  147. global_container_stack = Application.getInstance().getGlobalContainerStack()
  148. if global_container_stack is None or self._instance is None:
  149. return
  150. for key in ["machine_gcode_flavor"]:
  151. self._instance.setProperty(key, "value", global_container_stack.getProperty(key, "value"))
  152. def execute(self, data: List[str]):
  153. """Inserts the filament change g-code at specific layer numbers.
  154. :param data: A list of layers of g-code.
  155. :return: A similar list, with filament change commands inserted.
  156. """
  157. layer_nums = self.getSettingValueByKey("layer_number")
  158. initial_retract = self.getSettingValueByKey("initial_retract")
  159. later_retract = self.getSettingValueByKey("later_retract")
  160. x_pos = self.getSettingValueByKey("x_position")
  161. y_pos = self.getSettingValueByKey("y_position")
  162. z_pos = self.getSettingValueByKey("z_position")
  163. firmware_config = self.getSettingValueByKey("firmware_config")
  164. enable_before_macro = self.getSettingValueByKey("enable_before_macro")
  165. before_macro = self.getSettingValueByKey("before_macro")
  166. enable_after_macro = self.getSettingValueByKey("enable_after_macro")
  167. after_macro = self.getSettingValueByKey("after_macro")
  168. color_change = ";BEGIN FilamentChange plugin"
  169. if enable_before_macro:
  170. color_change = color_change + "\n" + before_macro
  171. color_change = color_change + "\n" + "M600"
  172. if not firmware_config:
  173. if initial_retract is not None and initial_retract > 0.:
  174. color_change = color_change + (" E%.2f" % initial_retract)
  175. if later_retract is not None and later_retract > 0.:
  176. # Reprap uses 'L': https://reprap.org/wiki/G-code#M600:_Filament_change_pause
  177. # Marlin uses 'U' https://marlinfw.org/docs/gcode/M600.html
  178. retract_method = self.getSettingValueByKey("retract_method")
  179. color_change = color_change + (" %s%.2f" % (retract_method, later_retract))
  180. if x_pos is not None:
  181. color_change = color_change + (" X%.2f" % x_pos)
  182. if y_pos is not None:
  183. color_change = color_change + (" Y%.2f" % y_pos)
  184. if z_pos is not None and z_pos > 0.:
  185. color_change = color_change + (" Z%.2f" % z_pos)
  186. if enable_after_macro:
  187. color_change = color_change + "\n" + after_macro
  188. color_change = color_change + "\n;END FilamentChange plugin\n"
  189. layer_targets = layer_nums.split(",")
  190. if len(layer_targets) > 0:
  191. for layer_num in layer_targets:
  192. try:
  193. layer_num = int(layer_num.strip()) + 1 #Needs +1 because the 1st layer is reserved for start g-code.
  194. except ValueError: #Layer number is not an integer.
  195. continue
  196. if 0 < layer_num < len(data):
  197. data[layer_num] = color_change + data[layer_num]
  198. return data