Hacking Your CNC Toolchain

At the monthly DIY CNC night at PS:One some people were complaining about the CNC Toolchains they were using with their ShapeOkos. I decided to write a blog post on the process of hacking or tweaking your CNC toolchain.

A toolchain is the series software programs you use to get a completed product.  I will use CNC routing as an example throughout this post, but other digital fabrication processes have their own toolchains and can be tweaked using the same process.  My toolchain goal was to be able to use my commercial CAM programs, use a state of the art machine controller like Marlin and have a nice GUI interface, like PrintRun.

The purpose of this post is to show how to hack a toolchain.  I am not suggesting that any of these programs are better than any other programs.  This just shows you the steps typically done to tweak your existing toolchain.  Here is a typical CNC routing toolchain.

  • CAD – This is the software where you draw or model your part.  For the ShapeOko that would typically be a 2D vector drawing.  AutoCAD, InkScape, CorelDRAW are typical programs I use.  The only requirement is that it exports to a format that the next link in the chain can handle.  Most people export in DFX format, but SVG, AI, EPS are also popular.
  • CAM – This is where you determine how the item will be machined.  For example: Cut this shape with a 3mm bit to a depth of 2mm in one clockwise path.  This then outputs machine code that the machine to cut.  It is usually G-Code.  I use programs from Vectric, like Cut2D, V-Carve and Aspire.
  • Machine Interface – This is the software that lets your computer talk to the CNC machnie.  It could be a simple as a text prompt like GRBL uses or a GUI like PrintRun.
  • Machine Controller – This is the software that runs on the machine.  In this case it is software that runs on an Arduino.  If you use EMC2 or Mach3, the machine controller and machine interface are typically the same program.

With the ShapeOko, most people are using GRBL.  (Garble? Gerbil?).  I have not hacked GRBL in a while, but last time I looked, it did not compile straight from the Arduino IDE and the pace of new versions was slower than some other controller projects.  The pace of development and new features in the 3D printer area appears to be faster and Marlin is very popular right now.

Programs like Marlin are well commented easy to modify, but if you hack the actual code, you will need to re-hack it every time a new version comes out.  My goal was to only touch the configuration file.  That way upgrading to the latest version is very easy.

I don’t own a ShapeOko, so I used my ORD Bot to simulate a CNC router.  This ORD Bot was using a RAMPS 1.4 controller.  It already had the three axes and I attached a simple 12V fan to simulate a spindle.
Since Marlin is a 3D printer controller, spindle control is not included, so you need to find a work around.  All of the M and G codes implemented by the software can be found in the main Marlin.pde file.  For a good reference on G-Codes, check out my G Code commentor page.  It will show you the meaning of most codes.

The typical spindle control codes are M03 for on and M05 for off.  Neither of these are present in Marlin, but the cooling fan controls (M106 and M107) looked like they would work well.  I could have simply added the M03,M05 codes into Marlin, but that would create a customized version, which is what I wanted to avoid.  I did the M03/M05 to M106/M107 swap in the post processor.

The fan in Marlin can also be speed controlled which is a cool feature for a spindle.  The RAMPS board has many options to hook up a fan, but I chose to use the D9 connection because it is 12V and can drive 5amps which would be perfect for a relay to run a dremel tool.  BTW: Don’t try PWM speed control through a mechanical relay :-)

With this method I only needed to modify one line in my Marlin configuration.h file.  The motherboard type needs to be 33 so that D9 is used for a fan and not a second extruder.  That is it for Marlin…compile and upload.

#define MOTHERBOARD 33

The CAM software still wants to send M03 to turn on the spindle.  That needs to change to the fan control codes.  No two CNC machines are exactly the same, so CAM programs use a file called a post processor to tweak the G-Code that is produced.  The post processor file tells the CAM software what flavor of G-code to use for each operation.  There is no standardized format for post processor files.  They are unique to each CAM program, but they are pretty easy to figure out and most CAM programs have a guide on how to use them.  I use CAM programs from Vectric and their guide to editing a post processor is here.

This is how the header section of my Marlin post processor looks.  The stuff in the quotes what is outputed.   This is the how each G-Code file will start.  The lines starting with “;” are just comments about the file and are ignored by Marlin.  The items in square brackets are variables supplied by the CAM program.  The first line of G-Code starts with G90.  I have added comments to each line.  The line M106 is where the fan (spindle) turns on.  The [S] variable sets the PWM speed.  It comes from the speed you set when you create the toolpath in the CAM software.  If you don’t supply this it will run full speed or if you supply it, it should be 0-255 for 0 to full speed.  I would change the line to “M106 ; turn on spindle full speed” if you were using a relay and did not have speed control.

begin HEADER

“; File created: [DATE] – [TIME]“
“; for Marlin by Bart”
“; Material Size”
“G90 ; Absolute mode”
“G21 ; Use millimeter mode”
“G01 [ZH] ; go to z rapid height”
“M106 [S]; turn on spindle”
“G04 S3; dwell/wait for spindle to reach speed”
“G01 [XH] [YH] [F] ; Go to XY home”


begin FOOTER

“G01 [ZH] ;goto safe z”
“M107; turn off spindle”
“G01 [XH] [YH] ; goto xy home”




This is the G-Code that will result.  In this case I have my spindle speed set for 60.

; Profile 3
; File created: Friday, August 10, 2012 – 11:42 AM
; for Marlin by Bart
; Material Size
; X= 100.000, Y= 100.000, Z= 10.000;
G90 ; Absolute mode
G21 ; Use millimeter mode
G01 Z20.000 ; go to z rapid height
M106 S60; turn on spindle
G04 S3; dwell/wait for spindle to reach speed
G01 X0.000 Y0.000 F1800.0 ; Go to XY home

Here are some screen shots from my CAM program.  I made 2 toolpaths.  The first is a square with the spindle set to a speed of 60.  The second is a circle with a ramping plunge move and a speed of 255.

This is the GUI interface you will have with the machine controller using PrintRun.  You will have to ignore the heater controls, but the interface is nice for jogging and you can see the macro buttons I have added to limit manual typing.

BTW: The other neat trick about this hack is you could quickly attach a 3D print head to the ShapeOko and print without any changes to the controller or controller software.

Here is a video of the ORD Bot standing in for a CNC router.  Here are the sequence of events.

  • Spindle (fan) turns on at speed 60
  • It waits 3 seconds for the spindle to reach speed.
  • The Z drops down to the rapid movement height from the safe Z height (start)
  • It plunges into the material.
  • It cuts the square.
  • It goes up to the rapid Z height and moves to the XY start of the circle.
  • Spindle speeds up to full.
  • It does a ramping plunge move down.
  • It completes the circle at the bottom.
  • It return to the safe Z height.

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks

7 Responses to “Hacking Your CNC Toolchain”

  1. carl


    interesting piece- I have a similar chain and problem
    plotter- 120×80 cm, arduino/ramps/marlin/pronterface

    I want to convert image to gcode, now using Inkscape with gcode extension, but when uploaded into pronterface, it sees the sizes, but no layers

    any ideas would be greatly appreciated




  2. Micah

    This has been greatly informative for me. I’m building a 2′X4′ CNC router and I plan to use the tool chain you’ve outlined here because I am familiar with all components individually. I’ve built a few RepRaps using Ramps with Marlin and Pronterface and I’ve used PartWorks (shopbot branch of VCarve) with a ShopBot. Your log has connected many of the dots for me.
    Did you do more in your post processing file than you show here? I’m not sure what else I’ll need to add other than a similar footer and header. I suppose I’ll need to add a function to pause between tool paths when they use a different bit. Have you implemented this?

    Thanks for sharing your log,


  3. bdring

    I typically just run separate files for each tool. Unless you have an automatic tool changer there is no real advantage to a single toolpath.

  4. Brad

    Does Marlin (or Repetier or other typical 3D printing firmware) support G0 vs G1? I read somewhere that they are treated identically so fast moves possibly don’t end up being fast.

  5. bdring

    You are right, but the firmware would be easy to hack a rapid speed in. You could probably hack the post processor to include the feed rate on each rapid too.

  6. Brian Jemail

    I have a custom built overhead gantry CNC machine with Grbl. Much like a shapeoko axis configuration, not wrapping the z axis. I decided to upgrade said machine to a 3d printer and updated the control board to ramps 1.4 atmega with LCD and rotary encoder. Your post was instrumental to getting this working alongside the CNC, all with the Marlin firmware at its center. I am now able to swap the spindle tool with an extruder effortlessly.

    I am a full-time programmer (c based code) by day and a mad scientist by night. After reading your post, I gave Aspire a try and liked it so much ended up buying it.

    There are a few things I would like to add/share to your documentation:

    First, the fan output off the ramps board works ok, but the spindle needs more power. Right now it can cut plastic with g-code M106 S255, but more is needed for metal. M4, M4, M5 is not supported by Marlin, but I intend to add it. This is what I have for a spindle: http://www.zentoolworks.com/product_info.php?products_id=122

    My machine does not always have a hot bed attached, so to get Marlin to work, I had to set Marlin Config: HEATER_0_MINTEMP to 0. This way, i could bypass MINTEMP errors. My extruder also uses a thermocouple with MAX6675, so the same applies to MAXTEMP errors.

    The g-code (custom post processor per your info) generated by Aspire, needs the Z axis to go negative. So it can cut into the material. This is necessary when you zero out Z (and possibly XY) and get ready to cut. I had to set Marlin Config: Z_MIN_POS to -177, that is the travel of my Z axis. Also adding custom commands to pronterface is crucial, especially G92 Z0 to set the Z on top of your material before cut.

    With this setup, I am still unsure why sometimes the limit switch behaves properly, yet sometimes it allows the motor to continue past the limit. It does not happen much unless I drew and cut something outside the envelope limit.

    Thanks again for sharing your information.

  7. Arsi


    I created GRBl port for RAMPS 1.4

    Steppers redirected to fastio.h from marlin firmware
    min switches remaped to AUX-3, GBRL uses pin change interrupts
    simple scheme to allow future porting of next releases
    command buttons currently disabled
    Ramps pins config moved to ramps.h
    cpu_map.h – min switches
    added GRBL_RAMPS1_4.ino for arduino IDE
    Ramps 1.4 | GRBL | Test
    X axis | X axis | OK working
    Z axis | Y axis for dual motor Y axis | OK working
    Y axis | Z axis | OK working
    Ramps AUX-3 pin 3 | min X | OK working
    Ramps AUX-3 pin 4 | min Y | OK working
    Ramps AUX-3 pin 5 | min Z | not tested
    D10 | motor ON | not tested
    D9 | motor direction | not tested
    D8 | coolant on | not tested