HowTo: Process for 2.5D CNC milling using free and OpenSource Software

Discussion in 'Luthier's Corner' started by couchsofa, Dec 19, 2014.

  1. At my local fablab we have a CNC that's running EMC2.4 (LinuxCNC) and I've been using it in the last few weeks to create custom hardware and work with difficult wood.

    Since blindsagacity asked me to elaborate on some of the steps involved I thought I'd just put together a short tutorial.

    You will need:

    If it's a really easy shape, like milling pockets for my brass tuners, I prefer to write the code by hand and paramatrize the whole design.
    That way, if something goes wrong, like the cutter moving into the workpiece I can make quick adjustments or change tolerances.
    It's a lot easier then changing a model and generating new code, but only really works for simple geometry.


    Here is an example of a simple piece of gcode I wrote for milling the headless tuner design:

    (Creates the first, closed pocket)
    G21 (using mm)
    G40 (manual toolrad comp)
    (Operation config)
    #<z-safe> = 20 (safe height)
    #<z-feed> = 0.5 (depth feed steps)
    #<toolrad> = 4
    #<feedrate> = 200
    (Workpiece params)
    #<wp_length> = 93.8
    #<width> = 12
    #<length> = 40
    #<depth> = 8
    #<steps> = [#<depth> / #<z-feed>]
    G00 X0 Y0 Z[#<z-safe>]
    G00 Y[#<wp_length> * 0.5 - #<toolrad> - 8] X[#<width> * 0.5 - #<toolrad>]
    #<current_depth> = [#<depth>]
    O101 repeat [#<steps>]
       #<current_depth> = [#<current_depth> - #<z-feed>]
       G01 Z[#<current_depth>] F[#<feedrate>]
       G01 Y[#<wp_length> * 0.5 - #<toolrad> - #<length> - 8] F[#<feedrate>]
       G01 X[#<width> * -0.5 + #<toolrad>] F[#<feedrate>]
       G01 Y[#<wp_length> * 0.5 - #<toolrad> - 8] F[#<feedrate>]
       G01 X[#<width> * 0.5 - #<toolrad>] F[#<feedrate>]
    O101 endrepeat
    G00 Z[#<z-safe>]
    (Return to Origin)
    G00 X0 Y0 Z[#<z-safe>]
    You should have some programming experience and gcode knowledge for this approach.
    A much more methodical workflow that also works with more complex geometry is the following.

    1.) Draw the cutting path in inkscape

    Pretty straight forward. I'm going to use a electronics cavity for this example.
    Remember that the path will represent the center of the cutter so you will have to compensate for that by insetting the outline by the radius of the cutter.


    Now you need to create paths to mill out the center of the pocket. I do that by choosing Path->Linked Offset and creating a path that's inset by the cutter diameter.
    Then select that path and use Path->Object to Path to get rid of the link. Then repeat until the area is filled.
    If you get artefacts from insetting you can delete the paths by double clicking and selecting the nodes you want to remove after you've converted the object to a path.


    Create a layer and move the paths on it. For some reason Gcodetools doesn't like SVGs without layers.
    Select Extensions->gcodetools->Path to Gcode. The only thing I change is under Preferences, the output folder and the post-processor.
    Choose Parametrize Gcode as post-processor. It will add X,Y and Z offeset variables and scale factors which will come in very handy.
    Hit apply and wait for the generator.


    2.) Editing the GCode file

    You can use your preferred text editor for that, gcode is just ASCII, but it should support Search and Replace.
    First I replace the number variables from the post processor with something a bit more human-readable.

    (Generated by gcodetools from Inkscape.)
    (Using default header. To add your own header create file "header" in the output dir.)
    (Header end.)
    G21 (All units in mm)
    #8  = 0 (Z axis offset)
    #6  = 0 (X axis offset)
    #7  = 0 (Y axis offset)
    #10 = 1 (XY Scale factor)
    #11 = 1 (Z Scale factor)
    #21 = 400.000000 (Feed definition)
    #20 = 100.000000 (Feed definition)
    G00 X0.0000 Y0.0000
    (Using default footer. To add your own footer create file "footer" in the output dir.)
    So I replace "#8" with "#<z_axis_offset>", "#20" with "#<z_feed-rate>", "#21" with "#<feed-rate>, ...
    Then I replace the header with my usual stuff:

    G21 (using mm)
    G40 (manual toolrad comp)
    The M3 statement tells the spindle in which direction to turn and M5 (footer) to stop. The CNC at the lab has a manually operated motor, so I don't need them.
    M2 ends the program and is considered obsolete.

    3.) Wrapped in a Loop

    2.5D means that we are dealing with a two dimensional shape that is extruded to create a volume. So far everything was 2D.
    To get the extrusion the code needs to be repeatedly executed at different heights.
    That's easily done with the repeat statement and a subroutine:

    #<steps> = [#<depth> / #<z_feed>]
    #<current_depth> = [#<depth>]
    O101 repeat [#<steps>]
    #<current_depth> = [#<current_depth> - #<z_feed>]
    (code here)
    O101 endrepeat
    The first command calculates how many steps to execute by taking the depth of the pocket to cut and dividing it by the z-feed (not the z_feed-rate!).
    z-feed specifies how much material to take off in one step. I usually go with .5 or .25 mm, depending on the material.

    O101 repeat [#<steps>] starts and O101 endrepeat ends the loop.
    #<current_depth> = [#<current_depth> - #<z_feed>] calculates the depth at every step by taking the depth from last step and subtracting the z-feed amount.

    Now you need to replace all commands in your code that have Z coordinate statement with the variable depth.
    Because the design was 2D all Z components should be the same and easy to replace.
    I like the keep the scale factor and offset so if your coordinates look like this:

    G03 X[54.939101 + #<x_offset>] Y[263.425865 + #<y_offset>] Z[0.125000 + #<z_offset>] I[0.747043] J[-92.629963] F [#<feed_rate>]
    I would replace "Z[0.125000" with "Z[#<current_depth>".

    4.) Simulate!

    Now it's time to load the code into LinuxCNC and play around, change some commands, do a bit of optimization.
    Select the axis_mm simulator. There are a bunch more that do fancy stuff, but we only want to look at the gcode and see if some steps can be optimized.


    Then load the gcode file.


    Now just play around with the code look at the effects in the sim.
    I usually get rid of a few commands that move the head to the origin after every loop or convert some G00 (movement) to G01 (cutting/feed) commands just to be safe.

    I hope you learned something and have some fun with utilizing CNC milling machines in luthiery.
    It's not actually that hard to get started and can be a great asset!

    Have fun.
    Camaro and xaxxat like this.