Jump to: navigation, search

Using Replicape to run a laser-based machine

Warning

This write-up is a work in progress, based on feedback from @Szeker on the Replicape Slack. It will be significantly improved over the next few weeks pending feedback from new laser users.


The main issue was with directly generated LASER cutting codes (from other tools) is that they are heavily using G2 and G3 commands to cut arcs (and practically everything not straight). Because of some reason, whatever settings I tried G2 and G3 were always executed with much slower movement speed compared to G1 commands, which led to uneven engraving/cutting result. Practically straight lines (G1) were nearly invisible, while curves (G2 or G3 commands) were burning the material heavily.

So I decided to generate the path for the LASER using G1 commands only - as any typical slicer is doing today (e.g. Simplify 3D), in which way I have better control of all parameters.

I'm using S3D with STL files only (designed in a CAD system e.g. Fusion 360), so no direct experience with SVGs, but there should be conversion tools to generate STL from SVG (e.g.: svg2stl.com[1] ).

After generating the toolpath with the slicer, I feed the Gcode to the script, which is converting it to control the movement speed and the power of the LASER through the PWM duty cycle of Fan1. (You can change it in the script of course.)

Note: The Fan output is inverted on Replicape, so I used a simple optocoupler to invert "back" the fan PWN signal for the LASER.

Extrusion on = LASER on (power and speed are set according to the relevant parameters passed to the script) NO extrusion (travel) = LASER off (travel speed is set according to the travel speed parameter passed to the script)

You can also set the number of passes, so the whole cutting/engraving cycle will be repeated by the number of passes. You can also set the "layer hight" in mm, which will move the LASER head down with the given parameter after each pass completed (to keep the focus of the LASER on the surface to be cut)

So my process for cutting or engraving (of vector-type graphics) with a LASER:

  1. Design or download the STL to be cut or engraved
  2. Slice it (tested only with Simplyfy3D) (Example parameters I used: Nozzle diameter = extrusion width = 0,1mm (will be the line distance) , layer hight = 0.01mm, only slicing from 0.0mm to 0.01mm = 1 layer)
  3. Feed the generated code to the Python script:
    Parameters: -i filename [-o filename] [-pw Output power] [-ps Number of cut passes] [-lh LayerHeight] [-cs Cutting Speed] [-ts Travel Speed]
    Example: py G2L_S3D.py -i Test1.gcode -o Test1_LASER.gcode -pw 70 -ps 5 -lh 0.5 -cs 200 -ts 2000
  4. Move the head to the starting point (also set the correct focusing hight of the LASER)
  5. Start "printing". All movements will be relative to the starting point.

Python script :


import string
import re
import sys
import os
import argparse
​
def main():
​
    LaserState = False
​
    parser = argparse.ArgumentParser(description='Modifying S3D generated G-code for LASER cutting on D3D printer')
    group1 = parser.add_argument_group('File input and output options')
    group1.add_argument('-i', '--input', required=True, metavar='filename', help='specify the input file to process')
    group1.add_argument('-o', '--output', required=False, metavar='filename', help='specify the output file to generate.  If not specified, output file name will use the original with the _L extension at the end.')
​
    group2 = parser.add_argument_group('LASER Parameters')
    group2.add_argument('-pw', '--power', required=False, type=int  , default=100, metavar='Output power', help='specify the output power of the LASER (0-100%, default = 100%)')
    group2.add_argument('-ps', '--passes', required=False, type=int, default=1, metavar='Number of cut passes', help='specify the number of cut passes')
    group2.add_argument('-lh', '--layerheight', required=False, type=float, default=0, metavar='LayerHeight', help='specify the cut height (height difference between cut iterations, default = 0)')
    group2.add_argument('-cs', '--cutspeed', required=False, type=int, default=300, metavar='Cutting Speed', help='specify the cutting speed in mm/min (default = 300)')
    group2.add_argument('-ts', '--travelspeed', required=False, type=int, default=1000, metavar='Travel Speed', help='specify the travel speed in mm/min (default = 2000)')
​
    try:
        args = parser.parse_args()
        #print(args)
    except:
        print('Error: Missing or wrong parameters!')
        exit()
​
    inputfile = str.strip(args.input)
​
    if args.output:
        outputfile = str.strip(args.output)  # [0]
    else:
​
        path, filename_w_ext = os.path.split(inputfile)
        filename, file_extension = os.path.splitext(filename_w_ext)
        outputfile = path + filename + '_L' + file_extension
        #print(filename_w_ext + ' ' +filename + ' ' + file_extension + ' ' + path)
​
​
    fi = open(inputfile,'r')
    fo = open(outputfile,'w')
    lines = fi.readlines()
​
    outstring = ""
    outstring += ";******************************" + "\n"
    outstring += ";D3D LASER cutting g-code" + "\n"
    outstring += ";Parameters: " + str(args) + "\n"
    outstring += ";******************************" + "\n"
    outstring += "\n"
    outstring += "M106 P1 S0" +  "\n"
    outstring += "G90" + "\n"
    outstring += "M82" + "\n"
    outstring += "M106 S0" + "\n"
    outstring += "M140 S0" + "\n"
    outstring += "M104 S0 T0" + "\n"
    fo.write(outstring)
    outstring = ""
​
    for passnum in range(int(args.passes)):
        outstring += "\n"
        outstring += ";Pass " + str(passnum + 1) + "\n"
​
        if (passnum > 0):
            outstring += "G91" + "   ; Change to relative mode" + "\n"
            outstring += "G1 Z-" + str(args.layerheight) + " F2000" + "    ; Change Z hight by -" + str(args.layerheight) + "mm" + "\n"
            outstring += "G90" + "   ; Change back to absolute mode" + "\n"
            outstring += "\n"
​
        for origline in lines:
​
            #outstring += ("Orig: " + origline)
​
            G1com = re.search("^G[01]\s+", origline)
            if G1com:
                Extrusion = re.search("E([\+\-0-9\.]*)", origline)
                E = 0
                if Extrusion:
                    E = float(Extrusion.group(1))
​
                if E>0:
                    if LaserState == False:
                        LaserState = True
                        outstring += ("M106 P1 S" + "{:.0f}".format(args.power * 2.55) + "  ;LASER ON" + "\n")
​
                    newline = "G1 "
                    Xcoordinates = re.search("X([\+\-0-9\.]*)", origline)
                    if Xcoordinates:
                        newline = newline + " X" + str(Xcoordinates.group(1))
​
                    Ycoordinates = re.search("Y([\+\-0-9\.]*)", origline);
                    if Ycoordinates:
                        newline = newline + " Y" + str(Ycoordinates.group(1))
​
                    Feed = re.search("F([\+\-0-9\.]*)", origline)
​
                    if Feed:
                        newline = newline + " F" + "{:g}".format(args.cutspeed)
​
                    outstring += (newline + "\n")
​
                else:
                    if LaserState:
                        newline = "M106 P1 S0" + "  ;LASER OFF" + "\n"
                        outstring += (newline)
                        LaserState = False
​
                    newline = "G1 "
                    Xcoordinates = re.search("X([\+\-0-9\.]*)", origline)
                    if Xcoordinates:
                        newline = newline + " X" + str(Xcoordinates.group(1))
​
                    Ycoordinates = re.search("Y([\+\-0-9\.]*)", origline);
                    if Ycoordinates:
                        newline = newline + " Y" + str(Ycoordinates.group(1))
​
                    Feed = re.search("F([\+\-0-9\.]*)", origline)
​
                    if Feed:
                        newline = newline + " F" + "{:g}".format(args.travelspeed)
​
                    if (Xcoordinates or Ycoordinates):
                        outstring += (newline + "\n")
​
    outstring += "M106 P1 S0" + "  ;Shut down LASER" + "\n"
    fo.write(outstring)
​
main()