mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2025-12-28 18:30:36 -07:00
210 lines
5.7 KiB
Python
Executable file
210 lines
5.7 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
# This file is for preprocessing G-code and the new G29 Auto bed leveling from Marlin
|
|
# It will analyze the first 2 layers and return the maximum size for this part
|
|
# Then it will be replaced with g29_keyword = ';MarlinG29Script' with the new G29 LRFB.
|
|
# The new file will be created in the same folder.
|
|
|
|
from __future__ import print_function
|
|
|
|
# Your G-code file/folder
|
|
folder = './'
|
|
my_file = 'test.gcode'
|
|
|
|
# The minimum number of G1 instructions that should be between 2 different heights
|
|
min_g = 3
|
|
|
|
# Maximum number of lines to parse. We don't want to parse the
|
|
# whole file since we're only interested in the first plane.
|
|
max_g = 100000000
|
|
|
|
# G29 keyword
|
|
g29_keyword = 'G29'
|
|
|
|
# Output filename
|
|
output_file = folder + 'g29_' + my_file
|
|
# Input filename
|
|
input_file = folder + my_file
|
|
|
|
# Minimum scan size
|
|
min_size = 40
|
|
probing_points = 3 # points x points
|
|
max_lines = 1500
|
|
|
|
# Other stuff
|
|
min_x = 500
|
|
min_y = min_x
|
|
max_x = -500
|
|
max_y = max_x
|
|
last_z = 0.001
|
|
|
|
layer = 0
|
|
lines_of_g1 = 0
|
|
|
|
gcode = []
|
|
|
|
g29_found = False
|
|
g28_found = False
|
|
|
|
YELLOW = '\033[33m'
|
|
GREEN = '\033[32m'
|
|
RED = '\033[31m'
|
|
RESET = '\033[0m'
|
|
|
|
# Return only G0-G1 lines
|
|
def has_g_move(line):
|
|
return line[:2].upper() in ("G0", "G1")
|
|
|
|
# Find position in G move (x,y,z)
|
|
def find_axis(line, axis):
|
|
found = False
|
|
number = ""
|
|
for char in line:
|
|
if found:
|
|
if char == ".":
|
|
number += char
|
|
elif char == "-":
|
|
number += char
|
|
else:
|
|
try:
|
|
int(char)
|
|
number += char
|
|
except ValueError:
|
|
break
|
|
else:
|
|
found = char.upper() == axis.upper()
|
|
try:
|
|
return float(number)
|
|
except ValueError:
|
|
return None
|
|
|
|
|
|
# Save the min or max-values for each axis
|
|
def set_mima(line):
|
|
global min_x, max_x, min_y, max_y, last_z
|
|
|
|
current_x = find_axis(line, 'x')
|
|
current_y = find_axis(line, 'y')
|
|
|
|
if current_x is not None:
|
|
min_x = min(current_x, min_x)
|
|
max_x = max(current_x, max_x)
|
|
if current_y is not None:
|
|
min_y = min(current_y, min_y)
|
|
max_y = max(current_y, max_y)
|
|
|
|
return min_x, max_x, min_y, max_y
|
|
|
|
|
|
# Find z in the code and return it
|
|
def find_z(gcode, start_at_line=0):
|
|
for i in range(start_at_line, len(gcode)):
|
|
my_z = find_axis(gcode[i], 'Z')
|
|
if my_z is not None:
|
|
return my_z, i
|
|
|
|
|
|
def z_parse(gcode, start_at_line=0, end_at_line=0):
|
|
i = start_at_line
|
|
all_z = []
|
|
line_between_z = []
|
|
z_at_line = []
|
|
#last_z = 0
|
|
last_i = -1
|
|
|
|
while len(gcode) > i:
|
|
result = find_z(gcode, i + 1)
|
|
|
|
if result is None:
|
|
raise ValueError(f'{RED}Unable to determine Z height.{RESET}')
|
|
|
|
z, i = result
|
|
|
|
all_z.append(z)
|
|
z_at_line.append(i)
|
|
temp_line = i - last_i -1
|
|
line_between_z.append(i - last_i - 1)
|
|
#last_z = z
|
|
last_i = i
|
|
if 0 < end_at_line <= i or temp_line >= min_g:
|
|
#print('break at line {} at height {}'.format(i, z))
|
|
break
|
|
|
|
line_between_z = line_between_z[1:]
|
|
return all_z, line_between_z, z_at_line
|
|
|
|
|
|
# Get the lines which should be the first layer
|
|
def get_lines(gcode, minimum):
|
|
i = 0
|
|
all_z, line_between_z, z_at_line = z_parse(gcode, end_at_line=max_g)
|
|
#print('Detected Z heights:', all_z)
|
|
for count in line_between_z:
|
|
i += 1
|
|
if count > minimum:
|
|
#print('layer: {}:{}'.format(z_at_line[i-1], z_at_line[i]))
|
|
return z_at_line[i - 1], z_at_line[i]
|
|
|
|
|
|
with open(input_file, 'r', encoding='utf_8') as file:
|
|
lines = 0
|
|
for line in file:
|
|
lines += 1
|
|
if lines > max_lines:
|
|
break
|
|
if has_g_move(line):
|
|
gcode.append(line)
|
|
file.close()
|
|
|
|
layer_range = get_lines(gcode, min_g)
|
|
|
|
if layer_range is None:
|
|
raise ValueError(f'{RED}Unable to determine layer range.{RESET}')
|
|
|
|
start, end = layer_range
|
|
|
|
for i in range(start, end):
|
|
set_mima(gcode[i])
|
|
|
|
print('x_min:{} x_max:{}\ny_min:{} y_max:{}'.format(min_x, max_x, min_y, max_y))
|
|
|
|
# Resize min/max - values for minimum scan
|
|
if max_x - min_x < min_size:
|
|
offset_x = int((min_size - (max_x - min_x)) / 2 + 0.5) # int round up
|
|
#print('min_x! with {}'.format(int(max_x - min_x)))
|
|
min_x = int(min_x) - offset_x
|
|
max_x = int(max_x) + offset_x
|
|
if max_y - min_y < min_size:
|
|
offset_y = int((min_size - (max_y - min_y)) / 2 + 0.5) # int round up
|
|
#print('min_y! with {}'.format(int(max_y - min_y)))
|
|
min_y = int(min_y) - offset_y
|
|
max_y = int(max_y) + offset_y
|
|
|
|
|
|
new_command = 'G29 L{0} R{1} F{2} B{3} P{4}\n'.format(min_x,
|
|
max_x,
|
|
min_y,
|
|
max_y,
|
|
probing_points)
|
|
|
|
with open(input_file, 'r', encoding='utf_8') as in_file, open(output_file, 'w', encoding='utf_8') as out_file:
|
|
for line in in_file:
|
|
# Check if G29 already exists
|
|
if line.strip().upper().startswith(g29_keyword):
|
|
g29_found = True
|
|
out_file.write(new_command)
|
|
print(f'{YELLOW}Write G29.{RESET}')
|
|
else:
|
|
out_file.write(line)
|
|
|
|
# If we find G28 and G29 wasn't found earlier, insert G29 after G28
|
|
if not g29_found and line.strip().upper().startswith('G28'):
|
|
g28_found = True # Mark that G28 was found
|
|
out_file.write(new_command) # Insert G29 command
|
|
print(f'{YELLOW}Note: G29 was not found.\nInserted G29 after G28.{RESET}')
|
|
|
|
# Debugging messages
|
|
if not g28_found and not g29_found:
|
|
print(f'{RED}Error: G28 not found! G29 was not added.{RESET}')
|
|
else:
|
|
print(f'{GREEN}auto G29 finished!{RESET}')
|