From 0620267ebb4d06c9b491b7a5c21fe0d6124006e3 Mon Sep 17 00:00:00 2001 From: Wurstnase Date: Wed, 11 Mar 2015 23:53:28 +0100 Subject: [PATCH 1/5] g29 auto-mode for the new G29 LRFB short: this script scans the first few lines from a gcode. If the line between 2 different z are greater than min_g1 this is our first layer. On this layer we search the min and max values of X and Y. With an offset we write that in a new file. --- Marlin/scripts/g29_auto.py | 164 +++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 Marlin/scripts/g29_auto.py diff --git a/Marlin/scripts/g29_auto.py b/Marlin/scripts/g29_auto.py new file mode 100644 index 000000000..95b3385ce --- /dev/null +++ b/Marlin/scripts/g29_auto.py @@ -0,0 +1,164 @@ +# This file is for preprocessing gcode and the new G29 Autobedleveling from Marlin +# It will analyse the first 2 Layer and return the maximum size for this part +# After this it will replace with g29_keyword = ';MarlinG29Script' with the new G29 LRFB +# the new file will be created in the same folder. + +# your gcode-file/folder +folder = './' +my_file = 'test.gcode' + +# this is the minimum of G1 instructions which should be between 2 different heights +min_g1 = 3 + +# maximum number of lines to parse, I don't want to parse the complete file +# only the first plane is we are interested in +max_g1 = 1000 + +# g29 keyword +g29_keyword = ';MarlinG29Script' + +# output filename +output_file = folder + 'g29_' + my_file + +# offset makes the plane a little bit bigger +offset_x = 10 +offset_y = 10 +probing_points = 3 # points x points + +# 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 = [] + + +def found_g1(line): + return line[:2].upper() == "G1" + + +def find(line, axis): + found = False + number = "" + for char in line: + if found: + if 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 + + +def set_mima(line): + global min_x, max_x, min_y, max_y, last_z + + current_x = find(line, 'x') + current_y = find(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 + + +def find_z(gcode, start_at_line=0): + for i in range(start_at_line, len(gcode)): + my_z = find(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: + try: + z, i = find_z(gcode, i + 1) + except TypeError: + break + + all_z.append(z) + z_at_line.append(i) + line_between_z.append(i - last_i - 1) + # last_z = z + last_i = i + if 0 < end_at_line <= i: + break + # print('{}:{}'.format(last_z, last_i)) + + line_between_z = line_between_z[1:] + return all_z, line_between_z, z_at_line + + +def get_lines(gcode, minimum): + i = 0 + all_z, line_between_z, z_at_line = z_parse(gcode, end_at_line=max_g1) + for count in line_between_z: + i += 1 + if count > minimum: + return z_at_line[i - 1], z_at_line[i] + + +with open(my_file, 'r') as file: + lines = 0 + for line in file: + lines += 1 + if lines > 1000: + break + if found_g1(line): + gcode.append(line) +file.close() + +start, end = get_lines(gcode, min_g1) +for i in range(start, end): + set_mima(gcode[i]) + +min_x = int(min_x) - offset_x +max_x = int(max_x) + offset_x +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) + + +out_file = open(output_file, 'w') +print('out_file open') +input_file = open(my_file, 'r') +print('input_file open') + +for line in input_file: + if line[:len(g29_keyword)] == g29_keyword: + out_file.write(new_command) + print('write new_command') + else: + out_file.write(line) + +file.close() +out_file.close() From 2e7ba44633372f726ef471bf4d1edc7debb2a36e Mon Sep 17 00:00:00 2001 From: Wurstnase Date: Fri, 13 Mar 2015 07:31:27 +0100 Subject: [PATCH 2/5] some renaming for readability --- Marlin/scripts/g29_auto.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Marlin/scripts/g29_auto.py b/Marlin/scripts/g29_auto.py index 95b3385ce..b460e97a7 100644 --- a/Marlin/scripts/g29_auto.py +++ b/Marlin/scripts/g29_auto.py @@ -38,11 +38,11 @@ lines_of_g1 = 0 gcode = [] -def found_g1(line): +def has_g1(line): return line[:2].upper() == "G1" -def find(line, axis): +def find_axis(line, axis): found = False number = "" for char in line: @@ -66,8 +66,8 @@ def find(line, axis): def set_mima(line): global min_x, max_x, min_y, max_y, last_z - current_x = find(line, 'x') - current_y = find(line, 'y') + 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) @@ -81,7 +81,7 @@ def set_mima(line): def find_z(gcode, start_at_line=0): for i in range(start_at_line, len(gcode)): - my_z = find(gcode[i], 'Z') + my_z = find_axis(gcode[i], 'Z') if my_z is not None: return my_z, i @@ -122,13 +122,13 @@ def get_lines(gcode, minimum): return z_at_line[i - 1], z_at_line[i] -with open(my_file, 'r') as file: +with open(folder+my_file, 'r') as file: lines = 0 for line in file: lines += 1 if lines > 1000: break - if found_g1(line): + if has_g1(line): gcode.append(line) file.close() From 76da32b5679ec4cb6e9525b90e05019d091b9863 Mon Sep 17 00:00:00 2001 From: Wurstnase Date: Fri, 13 Mar 2015 07:44:20 +0100 Subject: [PATCH 3/5] add hash-bang for python3 --- Marlin/scripts/g29_auto.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Marlin/scripts/g29_auto.py b/Marlin/scripts/g29_auto.py index b460e97a7..d5f2a1c6e 100644 --- a/Marlin/scripts/g29_auto.py +++ b/Marlin/scripts/g29_auto.py @@ -1,3 +1,5 @@ +#!/usr/bin/python3 + # This file is for preprocessing gcode and the new G29 Autobedleveling from Marlin # It will analyse the first 2 Layer and return the maximum size for this part # After this it will replace with g29_keyword = ';MarlinG29Script' with the new G29 LRFB From 14f02508535815c45219e5e64da337acc0dbacfc Mon Sep 17 00:00:00 2001 From: Wurstnase Date: Mon, 16 Mar 2015 14:26:59 +0100 Subject: [PATCH 4/5] allow negative values and some more comments --- Marlin/scripts/g29_auto.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/Marlin/scripts/g29_auto.py b/Marlin/scripts/g29_auto.py index d5f2a1c6e..c28352b29 100644 --- a/Marlin/scripts/g29_auto.py +++ b/Marlin/scripts/g29_auto.py @@ -12,15 +12,18 @@ my_file = 'test.gcode' # this is the minimum of G1 instructions which should be between 2 different heights min_g1 = 3 -# maximum number of lines to parse, I don't want to parse the complete file +# maximum number of lines to parse, I don't want to parse the complete file # only the first plane is we are interested in max_g1 = 1000 # g29 keyword -g29_keyword = ';MarlinG29Script' +g29_keyword = 'g29' +g29_keyword = g29_keyword.upper() # output filename output_file = folder + 'g29_' + my_file +# input filename +input_file = folder + my_file # offset makes the plane a little bit bigger offset_x = 10 @@ -40,10 +43,12 @@ lines_of_g1 = 0 gcode = [] +# return only g1-lines def has_g1(line): return line[:2].upper() == "G1" +# find position in g1 (x,y,z) def find_axis(line, axis): found = False number = "" @@ -51,6 +56,8 @@ def find_axis(line, axis): if found: if char == ".": number += char + elif char == "-": + number += char else: try: int(char) @@ -65,6 +72,7 @@ def find_axis(line, axis): 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 @@ -81,6 +89,7 @@ def set_mima(line): 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') @@ -104,27 +113,30 @@ def z_parse(gcode, start_at_line=0, end_at_line=0): 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: + if 0 < end_at_line <= i or temp_line >= min_g1: + # print('break at line {} at heigth {}'.format(i, z)) break - # print('{}:{}'.format(last_z, last_i)) 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_g1) 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(folder+my_file, 'r') as file: +with open(input_file, 'r') as file: lines = 0 for line in file: lines += 1 @@ -138,6 +150,8 @@ start, end = get_lines(gcode, min_g1) 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)) + min_x = int(min_x) - offset_x max_x = int(max_x) + offset_x min_y = int(min_y) - offset_y @@ -149,18 +163,17 @@ new_command = 'G29 L{0} R{1} F{2} B{3} P{4}\n'.format(min_x, max_y, probing_points) - out_file = open(output_file, 'w') -print('out_file open') -input_file = open(my_file, 'r') -print('input_file open') +in_file = open(input_file, 'r') -for line in input_file: - if line[:len(g29_keyword)] == g29_keyword: +for line in in_file: + if line[:len(g29_keyword)].upper() == g29_keyword: out_file.write(new_command) - print('write new_command') + print('write G29') else: out_file.write(line) file.close() out_file.close() + +print('auto G29 finished') From 752c8046773ef326434f63ea7c9f3392fd0a8425 Mon Sep 17 00:00:00 2001 From: Wurstnase Date: Mon, 16 Mar 2015 15:13:16 +0100 Subject: [PATCH 5/5] remove offset, add minimum scan area --- Marlin/scripts/g29_auto.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Marlin/scripts/g29_auto.py b/Marlin/scripts/g29_auto.py index c28352b29..884e62b2a 100644 --- a/Marlin/scripts/g29_auto.py +++ b/Marlin/scripts/g29_auto.py @@ -14,7 +14,7 @@ min_g1 = 3 # maximum number of lines to parse, I don't want to parse the complete file # only the first plane is we are interested in -max_g1 = 1000 +max_g1 = 100000000 # g29 keyword g29_keyword = 'g29' @@ -25,9 +25,8 @@ output_file = folder + 'g29_' + my_file # input filename input_file = folder + my_file -# offset makes the plane a little bit bigger -offset_x = 10 -offset_y = 10 +# minimum scan size +min_size = 40 probing_points = 3 # points x points # other stuff @@ -152,10 +151,18 @@ for i in range(start, end): print('x_min:{} x_max:{}\ny_min:{} y_max:{}'.format(min_x, max_x, min_y, max_y)) -min_x = int(min_x) - offset_x -max_x = int(max_x) + offset_x -min_y = int(min_y) - offset_y -max_y = int(max_y) + offset_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,