# HG changeset patch # User mdd # Date 1506094808 -7200 # Node ID 0abfa46427764e49916bc0f4d40e0007fbf8a900 # Parent 92035ebc474303a3f519fda26e1dcb3bbd57d33c SVG bugfix: first shape line not drawn SVG feature: Dont control the laser via extrusion, switch on at shape start, off at shape end diff -r 92035ebc4743 -r 0abfa4642776 printrun-src/printrun/laser.py --- a/printrun-src/printrun/laser.py Fri Sep 22 17:38:36 2017 +0200 +++ b/printrun-src/printrun/laser.py Fri Sep 22 17:40:08 2017 +0200 @@ -1,6 +1,6 @@ """ Lasercutter library -2015-2016 by NeoSoft, Malte Di Donato +2015-2017 by NeoSoft, Malte Di Donato Intended to use standalone or implemented in Pronterface/Printrun """ @@ -18,7 +18,7 @@ # GENERAL HEADER AND FOOTER GCODE GCODE_HEAD = """ ; GCode generated by laser.py pronterface library (marlin code flavour) -; 2015/2016 by NeoSoft - Malte Bayer +; 2015-2017 by NeoSoft - Malte Di Donato G21 ; Metric ; We assume Z is in focus height and laser head is focus at bottom left of image! @@ -30,12 +30,17 @@ M209 S0 ; disable firmware retraction, we dont want to burn holes... M302 ; Allow cold extrudes - doesnt matter because we hack the extruder physically off with the M571 E mod M571 S1 E1 ; Activate Laser output on extrusion, but block real motor movement! +M85 S0 ; Disable idle hold timeout +M84 ; enable motors + """ -GCODE_FOOT = """G0 X0 Y0 F%.4f +GCODE_FOOT = """ +M42 P28 S0 ; Force laser off! +M85 S30 ; re-enable idle hold timeout +G0 X0 Y0 F%.4f ; Move back to origin M400 ; Wait for all moves to finish -M571 S0 E0 -M42 P28 S0 ; Force laser off! +M571 S0 E0 ; disable extruder firmware hack M501 ; undo all settings made """ % (100*60) @@ -295,6 +300,7 @@ import xml.etree.ElementTree as ET from svg2gcode import shapes as shapes_pkg from svg2gcode.shapes import point_generator + from svg2gcode import simplepath, cspsubdiv, cubicsuperpath self.log("Generating paths from SVG (outlines only)...") svg_shapes = set(['rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path']) @@ -375,6 +381,7 @@ fo = open(filename + ".g", "w") fo.write("; Filename: %s\n%s" % (filename, GCODE_HEAD)) + fo.write("M571 S0 E1 ; On SVG we control the laser by ourself\n") travel_speed = self.settings.lc_travel_speed * 60 engrave_speed = self.settings.lc_engrave_speed * 60 * self.settings.lc_svg_speed_factor @@ -391,7 +398,7 @@ shape_class = getattr(shapes_pkg, tag_suffix) shape_obj = shape_class(elem) d = shape_obj.d_path() - m = shape_obj.transformation_matrix() + mat = shape_obj.transformation_matrix() if d: fo.write("M400 ; start %s\n" % (tag_suffix)) @@ -399,41 +406,74 @@ E = 0 xo = 0 yo = 0 - p = point_generator(d, m, smoothness) - start = True - for x,y,pen in p: - x += ofs_x - y += ofs_y - y = height - y # invert the bed - xs = scale_x * x - ys = scale_y * y - if xo == xs and yo == ys: continue + idxo = None + #p = point_generator(d, mat, smoothness) + + simple_path = simplepath.parsePath(d) + if len(simple_path) == 0: + self.log("Path length zero!") + continue + + p = cubicsuperpath.parsePath(d) + + if mat: + simpletransform.applyTransformToPath(mat, p) + + for sp in p: + cspsubdiv.subdiv( sp, smoothness) + self.log("Laser ON at: " + repr(sp[0][0])) + x = sp[0][0][0] + ofs_x + y = sp[0][0][1] + ofs_y + y = height - y # invert the bed + xs = scale_x * x + ys = scale_y * y + fo.write("M400 ; Wait for all moves to finish\n") + fo.write("M42 P28 S0 ; Turn off laser\n") + fo.write("G0 X%0.4f Y%0.4f F%.4f ; Move to start of shape\n" % ( + xs, ys, travel_speed)) + fo.write("M400 ; Wait for all moves to finish\n") + fo.write("M42 P28 S255 ; Turn on laser\n") - if not pen: start = True - if xs >= 0 and xs <= bed_max_x+0.1 and ys >= 0 and ys <= bed_max_y+0.1: - if start: - fo.write("G0 X%0.2f Y%0.2f F%.4f ; Move to start of shape\n" % ( - xs, ys, travel_speed)) - start = False - xo = xs - yo = ys - object_xs = xs - object_ys = ys - else: - e_distance = math.hypot(xs - xo, ys - yo) - xo = xs - yo = ys - E = E + (e_distance) - fo.write("G1 X%0.2f Y%0.2f E%.4f F%.4f\n" % ( - xs, ys, E * E_FACTOR, engrave_speed)) - else: - self.log("Position outside print dimension: %d, %d" % (xs, ys)) + xo = xs + yo = ys + object_xs = xs + object_ys = ys + + for csp in sp: + ctrl_pt1 = csp[0] + ctrl_pt2 = csp[1] + end_pt = csp[2] + + x = end_pt[0] + ofs_x + y = end_pt[1] + ofs_y + + y = height - y # invert the bed + xs = round(scale_x * x, 4) + ys = round(scale_y * y, 4) + if xo == xs and yo == ys: continue + + #self.log(" Point " + repr(end_pt)) + + if xs >= 0 and xs <= bed_max_x+0.1 and ys >= 0 and ys <= bed_max_y+0.1: + e_distance = math.hypot(xs - xo, ys - yo) + xo = xs + yo = ys + E = E + (e_distance) + fo.write("G1 X%0.4f Y%0.4f E%.4f F%.4f\n" % ( + xs, ys, E * E_FACTOR, engrave_speed)) + + else: + self.log("Position outside print dimension: %d, %d" % (xs, ys)) + + + #print " Point: ", end_pt[0], end_pt[1], pen + self.log("Laser OFF at: " + repr(sp[-1][-1])) if shape_obj.xml_node.get('fill'): # Close the polygon e_distance = math.hypot(object_xs - xo, object_ys - yo) E = E + (e_distance) - fo.write("G1 X%0.2f Y%0.2f E%.4f F%.4f ; Close the object polygon\n" % ( + fo.write("G1 X%0.4f Y%0.4f E%.4f F%.4f ; Close the object polygon\n" % ( object_xs, object_ys, E * E_FACTOR, engrave_speed)) print "connecting filled path end to start"