This repository has been archived by the owner on Jan 17, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathTweakAtZ.py
495 lines (486 loc) · 25 KB
/
TweakAtZ.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
# TweakAtZ script - Change printing parameters at a given height
# This script is the successor of the TweakAtZ plugin for legacy Cura.
# It contains code from the TweakAtZ plugin V1.0-V4.x and from the ExampleScript by Jaime van Kessel, Ultimaker B.V.
# It runs with the PostProcessingPlugin which is released under the terms of the AGPLv3 or higher.
# This script is licensed under the Creative Commons - Attribution - Share Alike (CC BY-SA) terms
#Authors of the TweakAtZ plugin / script:
# Written by Steven Morlock, [email protected]
# Modified by Ricardo Gomez, [email protected], to add Bed Temperature and make it work with Cura_13.06.04+
# Modified by Stefan Heule, [email protected] since V3.0 (see changelog below)
# Modified by Jaime van Kessel (Ultimaker), [email protected] to make it work for 15.10 / 2.x
# Modified by Ruben Dulek (Ultimaker), [email protected], to debug.
##history / changelog:
##V3.0.1: TweakAtZ-state default 1 (i.e. the plugin works without any TweakAtZ comment)
##V3.1: Recognizes UltiGCode and deactivates value reset, fan speed added, alternatively layer no. to tweak at,
## extruder three temperature disabled by "#Ex3"
##V3.1.1: Bugfix reset flow rate
##V3.1.2: Bugfix disable TweakAtZ on Cool Head Lift
##V3.2: Flow rate for specific extruder added (only for 2 extruders), bugfix parser,
## added speed reset at the end of the print
##V4.0: Progress bar, tweaking over multiple layers, M605&M606 implemented, reset after one layer option,
## extruder three code removed, tweaking print speed, save call of Publisher class,
## uses previous value from other plugins also on UltiGCode
##V4.0.1: Bugfix for doubled G1 commands
##V4.0.2: uses Cura progress bar instead of its own
##V4.0.3: Bugfix for cool head lift (contributed by luisonoff)
##V4.9.91: First version for Cura 15.06.x and PostProcessingPlugin
##V4.9.92: Modifications for Cura 15.10
##V4.9.93: Minor bugfixes (input settings) / documentation
##V4.9.94: Bugfix Combobox-selection; remove logger
##V5.0: Bugfix for fall back after one layer and doubled G0 commands when using print speed tweak, Initial version for Cura 2.x
##V5.0.1: Bugfix for calling unknown property 'bedTemp' of previous settings storage and unkown variable 'speed'
##V5.1: API Changes included for use with Cura 2.2
## Uses -
## M220 S<factor in percent> - set speed factor override percentage
## M221 S<factor in percent> - set flow factor override percentage
## M221 S<factor in percent> T<0-#toolheads> - set flow factor override percentage for single extruder
## M104 S<temp> T<0-#toolheads> - set extruder <T> to target temperature <S>
## M140 S<temp> - set bed target temperature
## M106 S<PWM> - set fan speed to target speed <S>
## M605/606 to save and recall material settings on the UM2
from ..Script import Script
#from UM.Logger import Logger
import re
class TweakAtZ(Script):
version = "5.1.1"
def __init__(self):
super().__init__()
def getSettingDataString(self):
return """{
"name":"TweakAtZ """ + self.version + """ (Experimental)",
"key":"TweakAtZ",
"metadata": {},
"version": 2,
"settings":
{
"a_trigger":
{
"label": "Trigger",
"description": "Trigger at height or at layer no.",
"type": "enum",
"options": {"height":"Height","layer_no":"Layer No."},
"default_value": "height"
},
"b_targetZ":
{
"label": "Tweak Height",
"description": "Z height to tweak at",
"unit": "mm",
"type": "float",
"default_value": 5.0,
"minimum_value": "0",
"minimum_value_warning": "0.1",
"maximum_value_warning": "230",
"enabled": "a_trigger == 'height'"
},
"b_targetL":
{
"label": "Tweak Layer",
"description": "Layer no. to tweak at",
"unit": "",
"type": "int",
"default_value": 1,
"minimum_value": "-100",
"minimum_value_warning": "-1",
"enabled": "a_trigger == 'layer_no'"
},
"c_behavior":
{
"label": "Behavior",
"description": "Select behavior: Tweak value and keep it for the rest, Tweak value for single layer only",
"type": "enum",
"options": {"keep_value":"Keep value","single_layer":"Single Layer"},
"default_value": "keep_value"
},
"d_twLayers":
{
"label": "No. Layers",
"description": "No. of layers used to tweak",
"unit": "",
"type": "int",
"default_value": 1,
"minimum_value": "1",
"maximum_value_warning": "50",
"enabled": "c_behavior == 'keep_value'"
},
"e1_Tweak_speed":
{
"label": "Tweak Speed",
"description": "Select if total speed (print and travel) has to be tweaked",
"type": "bool",
"default_value": false
},
"e2_speed":
{
"label": "Speed",
"description": "New total speed (print and travel)",
"unit": "%",
"type": "int",
"default_value": 100,
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
"enabled": "e1_Tweak_speed"
},
"f1_Tweak_printspeed":
{
"label": "Tweak Print Speed",
"description": "Select if print speed has to be tweaked",
"type": "bool",
"default_value": false
},
"f2_printspeed":
{
"label": "Print Speed",
"description": "New print speed",
"unit": "%",
"type": "int",
"default_value": 100,
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
"enabled": "f1_Tweak_printspeed"
},
"g1_Tweak_flowrate":
{
"label": "Tweak Flow Rate",
"description": "Select if flow rate has to be tweaked",
"type": "bool",
"default_value": false
},
"g2_flowrate":
{
"label": "Flow Rate",
"description": "New Flow rate",
"unit": "%",
"type": "int",
"default_value": 100,
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
"enabled": "g1_Tweak_flowrate"
},
"g3_Tweak_flowrateOne":
{
"label": "Tweak Flow Rate 1",
"description": "Select if first extruder flow rate has to be tweaked",
"type": "bool",
"default_value": false
},
"g4_flowrateOne":
{
"label": "Flow Rate One",
"description": "New Flow rate Extruder 1",
"unit": "%",
"type": "int",
"default_value": 100,
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
"enabled": "g3_Tweak_flowrateOne"
},
"g5_Tweak_flowrateTwo":
{
"label": "Tweak Flow Rate 2",
"description": "Select if second extruder flow rate has to be tweaked",
"type": "bool",
"default_value": false
},
"g6_flowrateTwo":
{
"label": "Flow Rate two",
"description": "New Flow rate Extruder 2",
"unit": "%",
"type": "int",
"default_value": 100,
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
"enabled": "g5_Tweak_flowrateTwo"
},
"h1_Tweak_bedTemp":
{
"label": "Tweak Bed Temp",
"description": "Select if Bed Temperature has to be tweaked",
"type": "bool",
"default_value": false
},
"h2_bedTemp":
{
"label": "Bed Temp",
"description": "New Bed Temperature",
"unit": "C",
"type": "float",
"default_value": 60,
"minimum_value": "0",
"minimum_value_warning": "30",
"maximum_value_warning": "120",
"enabled": "h1_Tweak_bedTemp"
},
"i1_Tweak_extruderOne":
{
"label": "Tweak Extruder 1 Temp",
"description": "Select if First Extruder Temperature has to be tweaked",
"type": "bool",
"default_value": false
},
"i2_extruderOne":
{
"label": "Extruder 1 Temp",
"description": "New First Extruder Temperature",
"unit": "C",
"type": "float",
"default_value": 190,
"minimum_value": "0",
"minimum_value_warning": "160",
"maximum_value_warning": "250",
"enabled": "i1_Tweak_extruderOne"
},
"i3_Tweak_extruderTwo":
{
"label": "Tweak Extruder 2 Temp",
"description": "Select if Second Extruder Temperature has to be tweaked",
"type": "bool",
"default_value": false
},
"i4_extruderTwo":
{
"label": "Extruder 2 Temp",
"description": "New Second Extruder Temperature",
"unit": "C",
"type": "float",
"default_value": 190,
"minimum_value": "0",
"minimum_value_warning": "160",
"maximum_value_warning": "250",
"enabled": "i3_Tweak_extruderTwo"
},
"j1_Tweak_fanSpeed":
{
"label": "Tweak Fan Speed",
"description": "Select if Fan Speed has to be tweaked",
"type": "bool",
"default_value": false
},
"j2_fanSpeed":
{
"label": "Fan Speed",
"description": "New Fan Speed (0-255)",
"unit": "PWM",
"type": "int",
"default_value": 255,
"minimum_value": "0",
"minimum_value_warning": "15",
"maximum_value_warning": "255",
"enabled": "j1_Tweak_fanSpeed"
}
}
}"""
def getValue(self, line, key, default = None): #replace default getvalue due to comment-reading feature
if not key in line or (";" in line and line.find(key) > line.find(";") and
not ";TweakAtZ" in key and not ";LAYER:" in key):
return default
subPart = line[line.find(key) + len(key):] #allows for string lengths larger than 1
if ";TweakAtZ" in key:
m = re.search("^[0-4]", subPart)
elif ";LAYER:" in key:
m = re.search("^[+-]?[0-9]*", subPart)
else:
#the minus at the beginning allows for negative values, e.g. for delta printers
m = re.search("^[-]?[0-9]*\.?[0-9]*", subPart)
if m == None:
return default
try:
return float(m.group(0))
except:
return default
def execute(self, data):
#Check which tweaks should apply
TweakProp = {"speed": self.getSettingValueByKey("e1_Tweak_speed"),
"flowrate": self.getSettingValueByKey("g1_Tweak_flowrate"),
"flowrateOne": self.getSettingValueByKey("g3_Tweak_flowrateOne"),
"flowrateTwo": self.getSettingValueByKey("g5_Tweak_flowrateTwo"),
"bedTemp": self.getSettingValueByKey("h1_Tweak_bedTemp"),
"extruderOne": self.getSettingValueByKey("i1_Tweak_extruderOne"),
"extruderTwo": self.getSettingValueByKey("i3_Tweak_extruderTwo"),
"fanSpeed": self.getSettingValueByKey("j1_Tweak_fanSpeed")}
TweakPrintSpeed = self.getSettingValueByKey("f1_Tweak_printspeed")
TweakStrings = {"speed": "M220 S%f\n",
"flowrate": "M221 S%f\n",
"flowrateOne": "M221 T0 S%f\n",
"flowrateTwo": "M221 T1 S%f\n",
"bedTemp": "M140 S%f\n",
"extruderOne": "M104 S%f T0\n",
"extruderTwo": "M104 S%f T1\n",
"fanSpeed": "M106 S%d\n"}
target_values = {"speed": self.getSettingValueByKey("e2_speed"),
"printspeed": self.getSettingValueByKey("f2_printspeed"),
"flowrate": self.getSettingValueByKey("g2_flowrate"),
"flowrateOne": self.getSettingValueByKey("g4_flowrateOne"),
"flowrateTwo": self.getSettingValueByKey("g6_flowrateTwo"),
"bedTemp": self.getSettingValueByKey("h2_bedTemp"),
"extruderOne": self.getSettingValueByKey("i2_extruderOne"),
"extruderTwo": self.getSettingValueByKey("i4_extruderTwo"),
"fanSpeed": self.getSettingValueByKey("j2_fanSpeed")}
old = {"speed": -1, "flowrate": -1, "flowrateOne": -1, "flowrateTwo": -1, "platformTemp": -1, "extruderOne": -1,
"extruderTwo": -1, "bedTemp": -1, "fanSpeed": -1, "state": -1}
twLayers = self.getSettingValueByKey("d_twLayers")
if self.getSettingValueByKey("c_behavior") == "single_layer":
behavior = 1
else:
behavior = 0
try:
twLayers = max(int(twLayers),1) #for the case someone entered something as "funny" as -1
except:
twLayers = 1
pres_ext = 0
done_layers = 0
z = 0
x = None
y = None
layer = -100000 #layer no. may be negative (raft) but never that low
# state 0: deactivated, state 1: activated, state 2: active, but below z,
# state 3: active and partially executed (multi layer), state 4: active and passed z
state = 1
# IsUM2: Used for reset of values (ok for Marlin/Sprinter),
# has to be set to 1 for UltiGCode (work-around for missing default values)
IsUM2 = False
oldValueUnknown = False
TWinstances = 0
if self.getSettingValueByKey("a_trigger") == "layer_no":
targetL_i = int(self.getSettingValueByKey("b_targetL"))
targetZ = 100000
else:
targetL_i = -100000
targetZ = self.getSettingValueByKey("b_targetZ")
index = 0
for active_layer in data:
modified_gcode = ""
lines = active_layer.split("\n")
for line in lines:
if ";Generated with Cura_SteamEngine" in line:
TWinstances += 1
modified_gcode += ";TweakAtZ instances: %d\n" % TWinstances
if not ("M84" in line or "M25" in line or ("G1" in line and TweakPrintSpeed and (state==3 or state==4)) or
";TweakAtZ instances:" in line):
modified_gcode += line + "\n"
IsUM2 = ("FLAVOR:UltiGCode" in line) or IsUM2 #Flavor is UltiGCode!
if ";TweakAtZ-state" in line: #checks for state change comment
state = self.getValue(line, ";TweakAtZ-state", state)
if ";TweakAtZ instances:" in line:
try:
tempTWi = int(line[20:])
except:
tempTWi = TWinstances
TWinstances = tempTWi
if ";Small layer" in line: #checks for begin of Cool Head Lift
old["state"] = state
state = 0
if ";LAYER:" in line: #new layer no. found
if state == 0:
state = old["state"]
layer = self.getValue(line, ";LAYER:", layer)
if targetL_i > -100000: #target selected by layer no.
if (state == 2 or targetL_i == 0) and layer == targetL_i: #determine targetZ from layer no.; checks for tweak on layer 0
state = 2
targetZ = z + 0.001
if (self.getValue(line, "T", None) is not None) and (self.getValue(line, "M", None) is None): #looking for single T-cmd
pres_ext = self.getValue(line, "T", pres_ext)
if "M190" in line or "M140" in line and state < 3: #looking for bed temp, stops after target z is passed
old["bedTemp"] = self.getValue(line, "S", old["bedTemp"])
if "M109" in line or "M104" in line and state < 3: #looking for extruder temp, stops after target z is passed
if self.getValue(line, "T", pres_ext) == 0:
old["extruderOne"] = self.getValue(line, "S", old["extruderOne"])
elif self.getValue(line, "T", pres_ext) == 1:
old["extruderTwo"] = self.getValue(line, "S", old["extruderTwo"])
if "M107" in line: #fan is stopped; is always updated in order not to miss switch off for next object
old["fanSpeed"] = 0
if "M106" in line and state < 3: #looking for fan speed
old["fanSpeed"] = self.getValue(line, "S", old["fanSpeed"])
if "M221" in line and state < 3: #looking for flow rate
tmp_extruder = self.getValue(line,"T",None)
if tmp_extruder == None: #check if extruder is specified
old["flowrate"] = self.getValue(line, "S", old["flowrate"])
elif tmp_extruder == 0: #first extruder
old["flowrateOne"] = self.getValue(line, "S", old["flowrateOne"])
elif tmp_extruder == 1: #second extruder
old["flowrateOne"] = self.getValue(line, "S", old["flowrateOne"])
if ("M84" in line or "M25" in line):
if state>0 and TweakProp["speed"]: #"finish" commands for UM Original and UM2
modified_gcode += "M220 S100 ; speed reset to 100% at the end of print\n"
modified_gcode += "M117 \n"
modified_gcode += line + "\n"
if "G1" in line or "G0" in line:
newZ = self.getValue(line, "Z", z)
x = self.getValue(line, "X", None)
y = self.getValue(line, "Y", None)
e = self.getValue(line, "E", None)
f = self.getValue(line, "F", None)
if 'G1' in line and TweakPrintSpeed and (state==3 or state==4):
# check for pure print movement in target range:
if x != None and y != None and f != None and e != None and newZ==z:
modified_gcode += "G1 F%d X%1.3f Y%1.3f E%1.5f\n" % (int(f / 100.0 * float(target_values["printspeed"])), self.getValue(line, "X"),
self.getValue(line, "Y"), self.getValue(line, "E"))
else: #G1 command but not a print movement
modified_gcode += line + "\n"
# no tweaking on retraction hops which have no x and y coordinate:
if (newZ != z) and (x is not None) and (y is not None):
z = newZ
if z < targetZ and state == 1:
state = 2
if z >= targetZ and state == 2:
state = 3
done_layers = 0
for key in TweakProp:
if TweakProp[key] and old[key]==-1: #old value is not known
oldValueUnknown = True
if oldValueUnknown: #the tweaking has to happen within one layer
twLayers = 1
if IsUM2: #Parameters have to be stored in the printer (UltiGCode=UM2)
modified_gcode += "M605 S%d;stores parameters before tweaking\n" % (TWinstances-1)
if behavior == 1: #single layer tweak only and then reset
twLayers = 1
if TweakPrintSpeed and behavior == 0:
twLayers = done_layers + 1
if state==3:
if twLayers-done_layers>0: #still layers to go?
if targetL_i > -100000:
modified_gcode += ";TweakAtZ V%s: executed at Layer %d\n" % (self.version,layer)
modified_gcode += "M117 Printing... tw@L%4d\n" % layer
else:
modified_gcode += (";TweakAtZ V%s: executed at %1.2f mm\n" % (self.version,z))
modified_gcode += "M117 Printing... tw@%5.1f\n" % z
for key in TweakProp:
if TweakProp[key]:
modified_gcode += TweakStrings[key] % float(old[key]+(float(target_values[key])-float(old[key]))/float(twLayers)*float(done_layers+1))
done_layers += 1
else:
state = 4
if behavior == 1: #reset values after one layer
if targetL_i > -100000:
modified_gcode += ";TweakAtZ V%s: reset on Layer %d\n" % (self.version,layer)
else:
modified_gcode += ";TweakAtZ V%s: reset at %1.2f mm\n" % (self.version,z)
if IsUM2 and oldValueUnknown: #executes on UM2 with Ultigcode and machine setting
modified_gcode += "M606 S%d;recalls saved settings\n" % (TWinstances-1)
else: #executes on RepRap, UM2 with Ultigcode and Cura setting
for key in TweakProp:
if TweakProp[key]:
modified_gcode += TweakStrings[key] % float(old[key])
# re-activates the plugin if executed by pre-print G-command, resets settings:
if (z < targetZ or layer == 0) and state >= 3: #resets if below tweak level or at level 0
state = 2
done_layers = 0
if targetL_i > -100000:
modified_gcode += ";TweakAtZ V%s: reset below Layer %d\n" % (self.version,targetL_i)
else:
modified_gcode += ";TweakAtZ V%s: reset below %1.2f mm\n" % (self.version,targetZ)
if IsUM2 and oldValueUnknown: #executes on UM2 with Ultigcode and machine setting
modified_gcode += "M606 S%d;recalls saved settings\n" % (TWinstances-1)
else: #executes on RepRap, UM2 with Ultigcode and Cura setting
for key in TweakProp:
if TweakProp[key]:
modified_gcode += TweakStrings[key] % float(old[key])
data[index] = modified_gcode
index += 1
return data