|
@@ -0,0 +1,186 @@
|
|
1
|
+#!/usr/bin/python3
|
|
2
|
+
|
|
3
|
+# This file is for preprocessing gcode and the new G29 Autobedleveling from Marlin
|
|
4
|
+# It will analyse the first 2 Layer and return the maximum size for this part
|
|
5
|
+# After this it will replace with g29_keyword = ';MarlinG29Script' with the new G29 LRFB
|
|
6
|
+# the new file will be created in the same folder.
|
|
7
|
+
|
|
8
|
+# your gcode-file/folder
|
|
9
|
+folder = './'
|
|
10
|
+my_file = 'test.gcode'
|
|
11
|
+
|
|
12
|
+# this is the minimum of G1 instructions which should be between 2 different heights
|
|
13
|
+min_g1 = 3
|
|
14
|
+
|
|
15
|
+# maximum number of lines to parse, I don't want to parse the complete file
|
|
16
|
+# only the first plane is we are interested in
|
|
17
|
+max_g1 = 100000000
|
|
18
|
+
|
|
19
|
+# g29 keyword
|
|
20
|
+g29_keyword = 'g29'
|
|
21
|
+g29_keyword = g29_keyword.upper()
|
|
22
|
+
|
|
23
|
+# output filename
|
|
24
|
+output_file = folder + 'g29_' + my_file
|
|
25
|
+# input filename
|
|
26
|
+input_file = folder + my_file
|
|
27
|
+
|
|
28
|
+# minimum scan size
|
|
29
|
+min_size = 40
|
|
30
|
+probing_points = 3 # points x points
|
|
31
|
+
|
|
32
|
+# other stuff
|
|
33
|
+min_x = 500
|
|
34
|
+min_y = min_x
|
|
35
|
+max_x = -500
|
|
36
|
+max_y = max_x
|
|
37
|
+last_z = 0.001
|
|
38
|
+
|
|
39
|
+layer = 0
|
|
40
|
+lines_of_g1 = 0
|
|
41
|
+
|
|
42
|
+gcode = []
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+# return only g1-lines
|
|
46
|
+def has_g1(line):
|
|
47
|
+ return line[:2].upper() == "G1"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+# find position in g1 (x,y,z)
|
|
51
|
+def find_axis(line, axis):
|
|
52
|
+ found = False
|
|
53
|
+ number = ""
|
|
54
|
+ for char in line:
|
|
55
|
+ if found:
|
|
56
|
+ if char == ".":
|
|
57
|
+ number += char
|
|
58
|
+ elif char == "-":
|
|
59
|
+ number += char
|
|
60
|
+ else:
|
|
61
|
+ try:
|
|
62
|
+ int(char)
|
|
63
|
+ number += char
|
|
64
|
+ except ValueError:
|
|
65
|
+ break
|
|
66
|
+ else:
|
|
67
|
+ found = char.upper() == axis.upper()
|
|
68
|
+ try:
|
|
69
|
+ return float(number)
|
|
70
|
+ except ValueError:
|
|
71
|
+ return None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+# save the min or max-values for each axis
|
|
75
|
+def set_mima(line):
|
|
76
|
+ global min_x, max_x, min_y, max_y, last_z
|
|
77
|
+
|
|
78
|
+ current_x = find_axis(line, 'x')
|
|
79
|
+ current_y = find_axis(line, 'y')
|
|
80
|
+
|
|
81
|
+ if current_x is not None:
|
|
82
|
+ min_x = min(current_x, min_x)
|
|
83
|
+ max_x = max(current_x, max_x)
|
|
84
|
+ if current_y is not None:
|
|
85
|
+ min_y = min(current_y, min_y)
|
|
86
|
+ max_y = max(current_y, max_y)
|
|
87
|
+
|
|
88
|
+ return min_x, max_x, min_y, max_y
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+# find z in the code and return it
|
|
92
|
+def find_z(gcode, start_at_line=0):
|
|
93
|
+ for i in range(start_at_line, len(gcode)):
|
|
94
|
+ my_z = find_axis(gcode[i], 'Z')
|
|
95
|
+ if my_z is not None:
|
|
96
|
+ return my_z, i
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+def z_parse(gcode, start_at_line=0, end_at_line=0):
|
|
100
|
+ i = start_at_line
|
|
101
|
+ all_z = []
|
|
102
|
+ line_between_z = []
|
|
103
|
+ z_at_line = []
|
|
104
|
+ # last_z = 0
|
|
105
|
+ last_i = -1
|
|
106
|
+
|
|
107
|
+ while len(gcode) > i:
|
|
108
|
+ try:
|
|
109
|
+ z, i = find_z(gcode, i + 1)
|
|
110
|
+ except TypeError:
|
|
111
|
+ break
|
|
112
|
+
|
|
113
|
+ all_z.append(z)
|
|
114
|
+ z_at_line.append(i)
|
|
115
|
+ temp_line = i - last_i -1
|
|
116
|
+ line_between_z.append(i - last_i - 1)
|
|
117
|
+ # last_z = z
|
|
118
|
+ last_i = i
|
|
119
|
+ if 0 < end_at_line <= i or temp_line >= min_g1:
|
|
120
|
+ # print('break at line {} at heigth {}'.format(i, z))
|
|
121
|
+ break
|
|
122
|
+
|
|
123
|
+ line_between_z = line_between_z[1:]
|
|
124
|
+ return all_z, line_between_z, z_at_line
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+# get the lines which should be the first layer
|
|
128
|
+def get_lines(gcode, minimum):
|
|
129
|
+ i = 0
|
|
130
|
+ all_z, line_between_z, z_at_line = z_parse(gcode, end_at_line=max_g1)
|
|
131
|
+ for count in line_between_z:
|
|
132
|
+ i += 1
|
|
133
|
+ if count > minimum:
|
|
134
|
+ # print('layer: {}:{}'.format(z_at_line[i-1], z_at_line[i]))
|
|
135
|
+ return z_at_line[i - 1], z_at_line[i]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+with open(input_file, 'r') as file:
|
|
139
|
+ lines = 0
|
|
140
|
+ for line in file:
|
|
141
|
+ lines += 1
|
|
142
|
+ if lines > 1000:
|
|
143
|
+ break
|
|
144
|
+ if has_g1(line):
|
|
145
|
+ gcode.append(line)
|
|
146
|
+file.close()
|
|
147
|
+
|
|
148
|
+start, end = get_lines(gcode, min_g1)
|
|
149
|
+for i in range(start, end):
|
|
150
|
+ set_mima(gcode[i])
|
|
151
|
+
|
|
152
|
+print('x_min:{} x_max:{}\ny_min:{} y_max:{}'.format(min_x, max_x, min_y, max_y))
|
|
153
|
+
|
|
154
|
+# resize min/max - values for minimum scan
|
|
155
|
+if max_x - min_x < min_size:
|
|
156
|
+ offset_x = int((min_size - (max_x - min_x)) / 2 + 0.5) # int round up
|
|
157
|
+ # print('min_x! with {}'.format(int(max_x - min_x)))
|
|
158
|
+ min_x = int(min_x) - offset_x
|
|
159
|
+ max_x = int(max_x) + offset_x
|
|
160
|
+if max_y - min_y < min_size:
|
|
161
|
+ offset_y = int((min_size - (max_y - min_y)) / 2 + 0.5) # int round up
|
|
162
|
+ # print('min_y! with {}'.format(int(max_y - min_y)))
|
|
163
|
+ min_y = int(min_y) - offset_y
|
|
164
|
+ max_y = int(max_y) + offset_y
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+new_command = 'G29 L{0} R{1} F{2} B{3} P{4}\n'.format(min_x,
|
|
168
|
+ max_x,
|
|
169
|
+ min_y,
|
|
170
|
+ max_y,
|
|
171
|
+ probing_points)
|
|
172
|
+
|
|
173
|
+out_file = open(output_file, 'w')
|
|
174
|
+in_file = open(input_file, 'r')
|
|
175
|
+
|
|
176
|
+for line in in_file:
|
|
177
|
+ if line[:len(g29_keyword)].upper() == g29_keyword:
|
|
178
|
+ out_file.write(new_command)
|
|
179
|
+ print('write G29')
|
|
180
|
+ else:
|
|
181
|
+ out_file.write(line)
|
|
182
|
+
|
|
183
|
+file.close()
|
|
184
|
+out_file.close()
|
|
185
|
+
|
|
186
|
+print('auto G29 finished')
|