| 1 | #Name: Dual Temp Test |
| 2 | #Info: Lower the temperature for the nozzle that is not printing |
| 3 | #Depend: GCode |
| 4 | #Type: postprocess |
| 5 | #Param: coolTemperatureDifference(float:50.0) Drop idle nozzle temperature (C) |
| 6 | #Param: heatupTimeDelay(float:20.0) Heatup nozzle before use (sec) |
| 7 | #Param: zHop(float:0.0) Raise Z when reheating active extruder (mm) |
| 8 | |
| 9 | |
| 10 | __copyright__ = "Copyright (C) 2013 David Braam, Copyright (C) 2016 Clinton Ebadi <clinton@unknownlamer.org> - Released under terms of the AGPLv3 License" |
| 11 | import re |
| 12 | import math |
| 13 | from Cura.util import profile |
| 14 | |
| 15 | def getValue(line, key, default = None): |
| 16 | if not key in line or (';' in line and line.find(key) > line.find(';')): |
| 17 | return default |
| 18 | subPart = line[line.find(key) + 1:] |
| 19 | m = re.search('^[0-9]+\.?[0-9]*', subPart) |
| 20 | if m is None: |
| 21 | return default |
| 22 | try: |
| 23 | return float(m.group(0)) |
| 24 | except: |
| 25 | return default |
| 26 | |
| 27 | def wipeNozzle (f): |
| 28 | f.write (""" |
| 29 | G91 |
| 30 | G0 X{d} Y{d} F{rate} |
| 31 | G0 X-{d} Y-{d} F{rate} |
| 32 | G0 X-{d} Y-{d} F{rate} |
| 33 | G0 X{d} Y{d} F{rate} |
| 34 | G90 |
| 35 | """.format (d=3, rate=float(profile.getProfileSetting('travel_speed')) * 60)) |
| 36 | |
| 37 | fanOnCommand = None |
| 38 | |
| 39 | def disableFan(f): |
| 40 | if fanOnCommand is not None: |
| 41 | f.write ("M107\n") |
| 42 | |
| 43 | def enableFan(f): |
| 44 | if fanOnCommand is not None: |
| 45 | # ensure fan actually kicks back on |
| 46 | f.write ("M106 S255\n") |
| 47 | f.write (fanOnCommand) |
| 48 | |
| 49 | with open(filename, "r") as f: |
| 50 | lines = f.readlines() |
| 51 | |
| 52 | z = 0. |
| 53 | x = 0. |
| 54 | y = 0. |
| 55 | e = 0. |
| 56 | feedrate = float(profile.getProfileSetting('print_speed')) |
| 57 | wipeTowerP = profile.getProfileSetting('wipe_tower') == 'True' |
| 58 | currentSectionType = 'CUSTOM' |
| 59 | activeExtruder = -1 |
| 60 | firstLayer = True |
| 61 | # todo: use 2nd/3rd/etc extruder temp if available (arrays are alright...) |
| 62 | printTemperature = float(profile.getProfileSetting('print_temperature')) |
| 63 | coolTemperature = printTemperature - coolTemperatureDifference |
| 64 | |
| 65 | with open(filename, "w") as f: |
| 66 | # skip start gcode |
| 67 | idx = lines.index (';LAYER:0\n') |
| 68 | startIdx = idx |
| 69 | for line in lines[0:idx]: |
| 70 | if getValue(line, 'T', None) is not None and getValue(line, 'M', None) is None: |
| 71 | activeExtruder = getValue(line, 'T', None) |
| 72 | f.write (line) |
| 73 | while idx < len(lines): |
| 74 | line = lines[idx] |
| 75 | if getValue(line, 'T', None) is not None and getValue(line, 'M', None) is None: |
| 76 | nextExtruder = getValue(line, 'T', None) |
| 77 | printTime = 0.0 |
| 78 | sx = x |
| 79 | sy = y |
| 80 | sz = z |
| 81 | for n in xrange(startIdx, idx): |
| 82 | line = lines[n] |
| 83 | if line.startswith(';'): |
| 84 | continue |
| 85 | g = getValue(line, 'G', None) |
| 86 | if g == 0 or g == 1: |
| 87 | nx = getValue(line, 'X', x) |
| 88 | ny = getValue(line, 'Y', y) |
| 89 | nz = getValue(line, 'Z', z) |
| 90 | feedrate = getValue(line, 'F', feedrate) |
| 91 | printTime += math.sqrt((nx-x)*(nx-x)+(ny-y)*(ny-y)+(nz-z)*(nz-z)) / feedrate * 60 |
| 92 | x = nx |
| 93 | y = ny |
| 94 | z = nz |
| 95 | |
| 96 | heatupTime = printTime - heatupTimeDelay |
| 97 | if heatupTime < 0.0: |
| 98 | heatupTime = None |
| 99 | heatupBlocked = not firstLayer # do not reheat until active extruder is heated |
| 100 | x = sx |
| 101 | y = sy |
| 102 | z = sz |
| 103 | |
| 104 | f.write("M104 T%d S%d\n" % (nextExtruder, coolTemperature)) |
| 105 | f.write("T%d\n" % (activeExtruder)) |
| 106 | |
| 107 | printTime = 0.0 |
| 108 | for n in xrange(startIdx, idx): |
| 109 | line = lines[n] |
| 110 | if line.startswith(';'): |
| 111 | f.write(line) |
| 112 | continue |
| 113 | if getValue(line, 'M', 666) == 107: |
| 114 | fanOnCommand = None |
| 115 | f.write(line) |
| 116 | continue |
| 117 | if getValue(line, 'M', 666) == 106: |
| 118 | fanOnCommand = line |
| 119 | f.write(line) |
| 120 | continue |
| 121 | # find where the newly activated extruder is unspooled and block until fully reheated |
| 122 | if (getValue(line, 'G', 666) == 0 or getValue(line, 'G', 666) == 1) and getValue (line, 'E', 666) == 0.0 and (heatupBlocked or firstLayer): |
| 123 | # todo: if wipeTowerP, only |
| 124 | # wait for a few degrees below |
| 125 | # printTemperature and allow |
| 126 | # it to finish heating while |
| 127 | # priming |
| 128 | if zHop > 0.0: |
| 129 | f.write ("G91\nG0 Z%.3f\nG90\n" % zHop) |
| 130 | |
| 131 | disableFan(f) |
| 132 | f.write("M109 T%d S%d\n" % (activeExtruder, printTemperature)) |
| 133 | wipeNozzle(f) |
| 134 | enableFan(f) |
| 135 | |
| 136 | if zHop > 0.0: |
| 137 | f.write ("G91\nG0 Z%.3f\nG90\n" % -zHop) |
| 138 | zHop = -1 |
| 139 | heatupBlocked = False |
| 140 | if heatupTime is not None: |
| 141 | g = getValue(line, 'G', None) |
| 142 | if g == 0 or g == 1: |
| 143 | nx = getValue(line, 'X', x) |
| 144 | ny = getValue(line, 'Y', y) |
| 145 | nz = getValue(line, 'Z', z) |
| 146 | feedrate = getValue(line, 'F', feedrate) |
| 147 | printTime += math.sqrt((nx-x)*(nx-x)+(ny-y)*(ny-y)+(nz-z)*(nz-z)) / feedrate * 60 |
| 148 | if (printTime > heatupTime) and (not heatupBlocked): |
| 149 | f.write("M104 T%d S%d\n" % (nextExtruder, printTemperature)) |
| 150 | f.write("T%d\n" % (activeExtruder)) |
| 151 | heatupTime = None |
| 152 | x = nx |
| 153 | y = ny |
| 154 | z = nz |
| 155 | f.write(line) |
| 156 | f.write(lines[idx]) |
| 157 | startIdx = idx + 1 |
| 158 | activeExtruder = nextExtruder |
| 159 | firstLayer = False |
| 160 | idx += 1 |
| 161 | for n in xrange(startIdx, idx): |
| 162 | f.write(lines[n]) |