| 1 |
ron |
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')
|