diff --git a/config.py b/config.py index 73edcba..2421d00 100644 --- a/config.py +++ b/config.py @@ -1,23 +1,82 @@ -"""Bed width in mm""" -bed_max_x = 376 +import argparse +import sys -"""Bed height in mm""" -bed_max_y = 315 +class Config: + + """G-code emitted at the start of processing the SVG file""" + preamble = "G90 ;Absolute programming\nG21 ;Programming in millimeters (mm)\nM5 ;Disable laser\n" + + """G-code emitted at the end of processing the SVG file""" + postamble = "G1 X0.0 Y0.0; Display printbed\nM02 ;End of program\n" + + gcode_file_path = " " + svg_file_path = " " + feedrate = 0 + moverate = 0 + passes = 0 + laserpower = 0.0 + bedsizex = 0 + bedsizey = 0 + smoothness = 0.0 + + def parse_arguments(self): + parser = argparse.ArgumentParser(description='Generate gcode from vector graphics.') + + parser.add_argument("-i", "--input", dest='inputfile', metavar='image.svg', help="path to vector graphic file", required=True) + parser.add_argument("-o", "--output", dest='outputfile', metavar='data.gcode', help="path to file for generated gcode", required=True) + + parser.add_argument("-fr", "--feedrate", dest='feedrate', metavar=300, default=300, help="rate while laser is on", required=False) + parser.add_argument("-mr", "--moverate", dest='moverate', metavar=1200, default=1200, help="rate while laser is off", required=False) + + parser.add_argument("-p", "--passes", dest='passes', metavar=1, default=1, help="number of passes (for deeper cutting)", required=False) + parser.add_argument("-lp", "--laserpower", dest='laserpower', metavar="0%", default="0%", help="laser power in %%", required=False) + + parser.add_argument("-bx", "--bedsizex", dest='bedsizex', default="376", help="x size of bed in mm", required=False) + parser.add_argument("-by", "--bedsizey", dest='bedsizey', default="315", help="y size of bed in mm", required=False) + + parser.add_argument("-s", "--smoothness", dest='smoothness', metavar=0.2, default=0.2, help="Used to control the smoothness/sharpness of the curves.\nSmaller the value greater the sharpness.\nMake sure the value is greater than 0.1", required=False) + + args = parser.parse_args() + + self.svg_file_path = args.inputfile + self.gcode_file_path = args.outputfile + self.feedrate = int(args.feedrate) + self.moverate = int(args.moverate) + self.passes = int(args.passes) + self.laserpower = ((float(args.laserpower.split("%")[0])/100.0)) + self.bedsizex = int(args.bedsizex) + self.bedsizey = int(args.bedsizey) + self.smoothness = float(args.smoothness) + + if(self.laserpower > 1): + print("[config] argument describing laser power is greater 100%") + sys.exit(1) + elif (self.laserpower < 0): + print("[config] argument describing laser power is lower 0%") + sys.exit(1) + if (self.feedrate < 1): + print("[config] argument describing feedrate is lower 1") + sys.exit(1) + if (self.moverate < 1): + print("[config] argument describing moverate is lower 1") + sys.exit(1) + if (self.passes < 1): + print("[config] argument describing passes is lower 1") + sys.exit(1) + if (self.bedsizex < 1): + print("[config] argument describing bedsizex is lower 1") + sys.exit(1) + if (self.bedsizey < 1): + print("[config] argument describing bedsizey is lower 1") + sys.exit(1) + + + + + -"""X/Y speed in mm/minute""" -xy_speed = 50 -"""G-code emitted at the start of processing the SVG file""" -preamble = "G90 ;Absolute programming\nG21 ;Programming in millimeters (mm)\nM5 ;Disable laser\n" -"""G-code emitted at the end of processing the SVG file""" -postamble = "G1 X0.0 Y0.0; Display printbed\nM02 ;End of program\n" -""" -Used to control the smoothness/sharpness of the curves. -Smaller the value greater the sharpness. Make sure the -value is greater than 0.1 -""" -smoothness = 0.2 diff --git a/svg2gcode.py b/svg2gcode.py index deece8e..a91f9ef 100755 --- a/svg2gcode.py +++ b/svg2gcode.py @@ -4,7 +4,6 @@ from __future__ import absolute_import from __future__ import print_function import sys import os -import argparse import xml.etree.ElementTree as ET import shapes as shapes_pkg from shapes import point_generator @@ -13,7 +12,7 @@ from config import * debug = True example_usage = "-i test_data/Test_H.svg -o test_data/test.gcode -fr 300 -mr 1200 -p 1 -lp 20%" svg_shapes = set(['rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path']) -gcode_file_path = " " +global conf def gcode_write(gcode_file, gcode): if (debug): @@ -26,26 +25,11 @@ def close_on_failure(): os.remove(gcode_file_path) sys.exit(1) -def parse_arguments(): - parser = argparse.ArgumentParser(description='Generate gcode from vector graphics.') - - parser.add_argument("-i", "--input", dest='inputfile', metavar='image.svg', help="path to vector graphic file", required=True) - parser.add_argument("-o", "--output", dest='outputfile', metavar='data.gcode', help="path to file for generated gcode", required=True) - - parser.add_argument("-fr", "--feedrate", dest='feedrate', metavar=300, default=300, help="rate while laser is on", required=False) - parser.add_argument("-mr", "--moverate", dest='moverate', metavar=1200, default=1200, help="rate while laser is off", required=False) - - parser.add_argument("-p", "--passes", dest='passes', metavar=1, default=1, help="number of passes (for deeper cutting)", required=False) - parser.add_argument("-lp", "--laserpower", dest='laserpower', metavar="0%", default="0%", help="laser power in %%", required=False) - - parser.add_argument("-bx", "--bedsizex", dest='bedsizex', default="376", help="x size of bed in mm", required=False) - parser.add_argument("-by", "--bedsizey", dest='bedsizey', default="315", help="y size of bed in mm", required=False) - - parser.add_argument("-s", "--smoothness", dest='smoothness', metavar=0.2, default=0.2, help="Used to control the smoothness/sharpness of the curves.\nSmaller the value greater the sharpness.\nMake sure the value is greater than 0.1", required=False) - - args = parser.parse_args() - return [args.inputfile, args.outputfile, int(args.feedrate), int(args.moverate), int(args.passes), ((float(args.laserpower.split("%")[0])/100.0)), int(args.bedsizex), int(args.bedsizey), float(args.smoothness) ] - +def laserpower_to_pwm(percent): + if (percent <= 1): + return int(percent*255) + else: + return 0 def read_input_file(svg_file_path): try: tree = ET.parse(svg_file_path) @@ -71,7 +55,7 @@ def generate_gcode(svg_file_root_tree, gcode_file): print("[SVG loaded] With:" + str(width) + "mm Height:" + str(height) + "mm") #generate start cmds's - gcode_write(gcode_file, preamble) + gcode_write(gcode_file, conf.preamble) for elem in svg_file_root_tree.iter(): @@ -84,18 +68,19 @@ def generate_gcode(svg_file_root_tree, gcode_file): shape_obj = shape_class(elem) obj_path = shape_obj.d_path() obj_trans_matrix = shape_obj.transformation_matrix() - + gcode_write(gcode_file, "G0 F" + str(conf.moverate) + " set the moverate to " + str(conf.moverate) + "mm/min;\n") if obj_path: gcode_write(gcode_file, "; == Start of " + tag_suffix + " ==\n") - points = point_generator(obj_path, obj_trans_matrix, smoothness) + points = point_generator(obj_path, obj_trans_matrix, conf.smoothness) num_points = 0 for x,y in points: if (debug): print("[Point] X: " + str(x) + " Y: " + str(y)) - if x > 0 and x < bed_max_x and y > 0 and y < bed_max_y: + if x > 0 and x < conf.bedsizex and y > 0 and y < conf.bedsizey: gcode_write(gcode_file, "G1 X%0.001f Y%0.001f\n" % (x, y)) num_points += 1 if (num_points == 1): - gcode_write(gcode_file, "M3 I S15 ;start laser\n") + gcode_write(gcode_file, "G0 F" + str(conf.feedrate) + " set the feedrate to " + str(conf.feedrate) + "mm/min;\n") + gcode_write(gcode_file, "M3 I S" + str(laserpower_to_pwm(conf.laserpower)) + " ;start laser\n") elif (debug): print("\n; Coordinates out of range:", "G1 X%0.01f Y%0.01f" % (x, y)) print("; Raw:", str(x), str(y), "\nScaled:", str(x), str(y), "\n") @@ -103,28 +88,17 @@ def generate_gcode(svg_file_root_tree, gcode_file): gcode_write(gcode_file, "M5 ;stop laser\n") gcode_write(gcode_file, "; == End of " + tag_suffix + " ==\n") generated_points_count += num_points - - gcode_write(gcode_file, postamble) + gcode_write(gcode_file, "G0 F" + str(conf.moverate) + " set the moverate to " + str(conf.moverate) + "mm/min;\n") + gcode_write(gcode_file, conf.postamble) print("\nGenerated", generated_points_count, "points") if __name__ == "__main__": sys.setrecursionlimit(20000) #needed for svg's with more indepented paths - - svg_file_path, gcode_file_path, feedrate, moverate, passes, laserpower, bedsizex, bedsizey, smoothness = parse_arguments() - - print("inputfile: " + str(svg_file_path)) - print("outputfile: " + str(gcode_file_path)) - print("feedrate: " + str(feedrate)) - print("moverate: " + str(moverate)) - print("passes: " + str(passes)) - print("laserpower: " + str(laserpower)) - print("bedsizex: " + str(bedsizex)) - print("bedsizey: " + str(bedsizey)) - print("smoothness: " + str(smoothness)) - + conf = Config() + conf.parse_arguments() try: - with open(gcode_file_path, 'w') as gcode_file: - generate_gcode(read_input_file(svg_file_path),gcode_file) + with open(conf.gcode_file_path, 'w') as gcode_file: + generate_gcode(read_input_file(conf.svg_file_path),gcode_file) except Exception as e: print("unable to create gcode file: \n" + str(e)) close_on_failure() diff --git a/test_data/test.gcode b/test_data/test.gcode index ebc53cf..0643f0d 100644 --- a/test_data/test.gcode +++ b/test_data/test.gcode @@ -1,29 +1,50 @@ G90 ;Absolute programming G21 ;Programming in millimeters (mm) M5 ;Disable laser -; == Start of path == -G1 X8.6 Y11.7 -M3 I S15 ;start laser -G1 X8.6 Y11.7 -G1 X29.4 Y9.7 -G1 X41.5 Y22.1 -G1 X35.3 Y35.3 -G1 X34.7 Y37.4 -G1 X33.9 Y38.9 -G1 X32.5 Y40.3 -G1 X30.4 Y41.0 -G1 X27.6 Y40.8 -G1 X23.7 Y39.4 -G1 X18.8 Y36.2 -G1 X14.9 Y33.0 -G1 X12.3 Y30.3 -G1 X10.6 Y27.9 -G1 X9.7 Y26.1 -G1 X9.4 Y24.6 -G1 X9.4 Y23.3 -G1 X9.6 Y23.0 -G1 X8.6 Y11.7 +G0 F1200 set the moverate to 1200mm/min; +; == Start of ellipse == +G1 X5.0 Y10.0 +G0 F300 set the feedrate to 300mm/min; +M3 I S2 ;start laser +G1 X5.0 Y10.4 +G1 X5.3 Y11.7 +G1 X5.9 Y12.9 +G1 X6.8 Y13.8 +G1 X7.9 Y14.5 +G1 X9.1 Y14.9 +G1 X10.4 Y15.0 +G1 X11.7 Y14.7 +G1 X12.9 Y14.1 +G1 X13.8 Y13.2 +G1 X14.5 Y12.1 +G1 X14.9 Y10.9 +G1 X15.0 Y9.6 +G1 X14.7 Y8.3 +G1 X14.1 Y7.1 +G1 X13.2 Y6.2 +G1 X12.1 Y5.5 +G1 X10.9 Y5.1 +G1 X9.6 Y5.0 +G1 X8.3 Y5.3 +G1 X7.1 Y5.9 +G1 X6.2 Y6.8 +G1 X5.5 Y7.9 +G1 X5.1 Y9.1 +G1 X5.0 Y10.0 M5 ;stop laser -; == End of path == +; == End of ellipse == +G0 F1200 set the moverate to 1200mm/min; +; == Start of rect == +G1 X30.0 Y30.0 +G0 F300 set the feedrate to 300mm/min; +M3 I S2 ;start laser +G1 X30.0 Y30.0 +G1 X40.0 Y30.0 +G1 X40.0 Y40.0 +G1 X30.0 Y40.0 +G1 X30.0 Y30.0 +M5 ;stop laser +; == End of rect == +G0 F1200 set the moverate to 1200mm/min; G1 X0.0 Y0.0; Display printbed M02 ;End of program