From 3D Printing to Machining Metal Parts

This article walks through the conversion of a g0704 mini mill to a CNC machine using LinuxCNC. I avoid the cost of a ballscrew conversion and instead use software backlash compensation with the stock ballscrews and am still able to achieve great results:

Way back in 2016, I got my first 3D printer and my eyes were open to the world of rapid manufacturing. The accessibility of information and tools for 3D printing are outstanding, in no small part to the founder of the open source 3D printer RepRap project, Dr. Adrian Bowyer.

After 4 years of learning to build 3D printers, designing new CAD models, and printing plastic parts, I decided it was time to make parts out of metal. Rapid manufacturing in metal is a fascinating topic, but is not nearly as accessible in terms of costs and publicly available information as plastic 3D printing. Therefore, I opted for a CNC milling machine.

Choosing a Machine

I spent a long time trying to figure out the best machine to buy. I looked at options from Tormach, littlemachineshop, Harbor Freight, and Sieg (the actual manufacturer of most mini-mills). In the end, the Tormach was too expensive, the benefit of a little machine shop over the Harbor Freight version was not worth it to me. I looked into getting a Sieg KX1-MACH, and would have chosen this, but importing it in the middle of the pandemic did not work out. If you're someone who does not want to build their own CNC, the Sieg KX1 seems like the best option. I really wanted an iKX1S-SIEG which has an option for a toolchanger, a faster spindle, and an enclosure, but the exclusive importer of these is Intelitek and they wouldn't sell me one. The folks at Sieg are very accessible, so if you are interested in this route, just email them directly.

In the end, I found and purchased a used Grizzly g0704 mill and South Bend lathe. While the g0704 is just a re-branded Sieg machine, and way over-priced if purchased new, great deals can be found on a used machines.

They were a bit dirty when I picked them up.

They cleaned up nicely and I mounted them on a table made out of 8020 aluminum extrusion. Having both machines on the same sturdy table was very useful as their collective mass makes them more stable than if they were mounted somewhere separately. Adding mass to your machine, by a mounting configuration such as this or some other way, is a simple way to improve the precision of the machine. More mass reduces the potential for anything to move or vibrate during usage. A sturdy mounting of some sort is highly recommended.

Take note, the axes configuration on this machine, once converted to a CNC will be as described in the LinuxCNC User Guide, here are the axes are configured:

While this article is not about the lathe, it was very useful in making couplers for the mill, as I describe below.


Thanks to everyone I talked to along the way. Notably, Chris at, was very helpful, all the folks I talked to at and Chris Li at Leadshine America who sold me the electronics as discussed below.

Hardware CNC Conversion

There are quite a few options to convert the manual g0704 to a CNC. The first choice is if one should use ballscrews or not. I decided to convert the machine without changing to ballscrews and use software backlash compensation, which turned out great.

Aside from being able to achieve great results without the cost of ballscrews, the main benefit of doing a leadscrew only (no ballscrew) conversion is that there is very little modification required to retrofit the g0704. The way I achieved this was by designing motor mounts that fit onto the existing mounts and couplers that fit over the nuts that hold the leadscrews on the x-axis and the y-axis, so permanent modification of the existing hardware for the leadscrew is required.

The two main things you'll need to make are the motor mounts and motor shaft couplers.

Leadscrew Motor Mounts

For the motor mounts, I started with the x and y axis:

I designed and 3D printed the y-axis mount, you can download the y-axis-mount.stl on thingiverse.

I cut the x-axis mount plate on the G0704 from 1/2" Aluminum stock by hand. The standoffs were cut to 2.10" (53.29mm), then drilled and tapped for M4 bolts.

Here is the x-axis drawing, if you would like to make your own:

I cut the z-axis last using the installed x-axis and y-axis cnc components. If you want to CNC the z-axis plate, the STL can be found on thingiverse. The reason this cannot be milled by hand is the center must be a circle. Standoffs were created the same way as the x-axis, but cut to 2.52" (64mm).

Here is the z-axis drawing:

Leadscrew Couplers

The x-axis coupler and y-axis coupler are the same. I designed them to replace the manual handle without modifying the other hardware on the axis, so the nut that would normally hold the handle in place, fits inside the coupler. Here is the original design:

In the final version, I decided to use 3mm rod to pin the couplers together to drive the shaft from the motor, instead of the 3x M3 set screws originally planned:

I made the couplers on the lathe, then drilled out the holes for the M3 pins on the mill.

The z-axis coupler is a simple fixed-shaft (solid) coupler:

Another Option: Ballscrews

The other option is to convert the lead screws to ballscrews. The drawings for the ballscrews are below, if you decide to go this route. You'll also need to actually modify the base of your g0704 as described in various places on the web, such as here:

I have not checked these drawings myself, as I decided to use software backlash compensation, explained further below, instead of ballscrews, which made the conversion simpler.

Another option is to buy a kit such as: or However, these kits cost about $700, which is way more than I wanted to spend.

So far, I've been able to get great performance without ballscrews, as you can see from the video at the top of the page. The one downside is the head is not very heavy, so I have to take z-axis plunges quite slow to avoid the head riding up on the z-axis backlash. If I were to add a ballscrew, it would be for the z-axis, but don't see the need at this point and plan on just taking relatively slow plunge cuts.


  • Collet Set for holding endmills. I got a full collet set, with my used mill purchase, but if you're just starting out, it may be better to pick a single size and just get the one or two collets you need. I use my 3/8" collet almost exclusively. If you're buying endmills, just buy them in the size that fits your collet, the shank size must match the collet, but the cutter size does not have to be the same as the collet.

  • Drill Chuck I prefer a keyless chuck. The main consideration here is to get one that is not too tall to avoid having to bring the head way up before changing it! I actually bought a bit taller one that was cheaper, but I should have gotten the shorter one.

  • 4" Precision Vise for work holding. A 4" vise is about the biggest you'll want and even this is a little big. I had to clamp mine down a bit creatively, since it does not fit well using the normal bolt cutouts -- it's a little too close to the back of the mill. Notice how I'm holding the vise in the photo below. Holding it this way works great.


  • Endmills The best endmills to purchase will depend on the material you intend to work with. I suggest the material you start with aluminum or brass, which tend to be easier to work with "free machining" materials. For these, a set of two-flute High Speed Steel (HSS) cutters will do the trick. Remember to buy a set with a shank size matching your collet.

  • Center Drills are necessary for starting (drilled) holes in the correct locations.

  • Drills are for drilling holes. You can use any drills, but a large set of HSS bits will ensure you have the right size for the job.



For CNC control, I'm using an old computer with a parallel port and a SainSmart 5 Axis CNC Breakout Board. SainSmart has a nice manual. Stepper online has their own version of the same manual as well. However, all of these manuals cover Mach3 and not LinuxCNC. This guide walks through the LinuxCNC setup in detail below.

Instead of buying from a Aliexpress or Amazon seller, I decided to get my electronics straight from a distributor. I think this is important so one gets a product that meets the specifications described in the manual. The distributor with the best product quality and price combination I found was Leadshine America. I'm using authentic Leadshine 4A stepper motors with DM556E drivers. I also bought a 48v, 10.5A power supply from Leadshine as well.

Here is the full electronics part list:

3x Stepper Motors: 57CM31-4A-I9 @ $49 each = $147

3x Stepper Drivers: DM556E @ $40 each = $120

1x 48V, 10.5A switching power supply: RPS4810 @ $55

Shipping was just over $20 and was quite fast, arrived from the west coast to my home on the east coast in only few days.

If you would like to order the same electronics I used, contact Chris Li at Leadshine America. Let him know you found him via this article. He did mention the power supply option, RPS4810, may be updated soon, so that might have a new model number if you order, but the rest should be the same.

I initially wanted larger motors, but Chris thought longer (more amperage) stepper motors would be too loud. It turns out these steppers work great and are nice and quiet for my use. Even running at full amperage, they stay nice and cool maxing out around 120 degrees Fahrenheit.

I also wanted steppers with a shaft that protrudes so I could attach a handle for manual motion. It turns out this is not necessary at all once the CNC is setup, and could actually cause a problem if manually moved, changing the zero point, so I am glad I got the version without the extended shaft.

I considered getting the more expensive DM556S stepper drivers, but am glad I went with the less expensive DM556E option that I chose, since this is more than sufficient for my use.


First, some terminology.

The controller is the card that plugs into your parallel port on the computer.

The drivers connects to the controller and a stepper motor. There is one driver per stepper.

Controller to PC

You can use a parallel port cable if you have one. Since I don't a parallel port cable, I plugged the controller straight into the back of the PC. Since the USB cable no longer fits, I re-wired the cable by soldering it to the other side of the PCB. We only need to wire the USB cable's +5v and GND lines.

The board also needs 12v. For this, I tapped the yellow +12v line and black ground line from the computer power supply to the CD-ROM drive. I wired these to the parallel port adapter board.

Controller to driver connections

All the + control lines go to a +5v line

The DIR and PUL lines go to the same line on the correct axis. Note that on my controller, the PUL line is labeled CLK, which is fine, it does the same thing.

The ENA pin on the drivers all go to the same enable pin on the controller

Driver to motor

Using our wiring diagram for the motor, we see the correct connection by wire color

You'll also need to plug in your high-voltage supply

Driver Configuration

Here is a link to the full pdf manual for the Leadshine DM556E drivers.

The dip switches map to:

I set the RMS current to 3.5A for the X and Y axis. The RMS current for the Z axis needed to be a little higher, so I set it to 4.0A:

I left the micro stepping setting to the default setting of 2: OFF, ON, ON, ON

Software: LinuxCNC

There are basically 2 options for controlling a CNC milling machine with a computer: LinuxCNC or Mach3/4. From everything I read, LinuxCNC is much more powerful and flexible. Plus it's free and open source, which is always a plus. The only constraint is that you'll need a computer with a parallel port or you'll need to buy an extension board. Cards from Mesa such as the 7I92M Anything I/O Ethernet card are a popular way to add a parallel port to new machine. If you choose to use Mach3 or Mach4, you can plugin the controller to any USB port. I'm using a computer with a built-in parallel port.

Installing Linux CNC

Look for the latest version available on

I'll be using what is currently the latest LinuxCNC 2.8.0, Debian 10 ISO, which includes the realtime PREEMPT-RT kernel patch.

Burn the ISO to a USB stick. I used balenaEtcher on my Mac.

Install the Debian 10 distro from the USB stick. Detailed instructions can be found here:

Configuring and testing the parallel port

First, if you're using a computer with an onboard parallel port, enter the bios and make sure SPP mode is enabled.

Once you've got it connected and configured, run a test to make sure the parallel port is working by launching LinuxCNC and choosing the appropriate test port:

Use a multimeter in DC mode. Put the leads on the P2 pin and 5v pin. It should read ~5 volts. Click the Pin 02 button and the voltage should drop to 0. If this works, you're ready to move on.

Configuring the machine

Once you've got the OS installed, launch stepconf from a terminal or the Applications menu bar.

Create a new configuration, I'm using metric units, as most drawings I do are in metric.

Set the machine name, mine is set to g0704. Choose "Other" for the Driver type and use the Driver Timing Settings are from the table here. Search for DM556 and you'll find:

Step Time: 2500
Step Space: 2500
Direction Hold: 10000
Direciton Setup: 5000
Steps on: Rising Edge

Run the HAL Latency Test. Use the computer for a bit and then record the Max Jitter (ns) value.

Enter the max value and continue to the next screen.

For the parallel port config, set pin 14 to Amplifier Enable, matching the label of the pin on the board.

Recall we left the drivers set to the default microstepping value of 2 (switch 5-8: off,on,on,on), so leave this to 2 in the setup

For the X and Y Axis config, we'll compute the leadscrew pitch which is indicated on the g0704 handles as 0.1" per revolution. Converting this to mm/rev we get: 2.54 mm/rev. I'm not sure how aggressive the default Maximum Velocity and Acceleration are at 25 and 750 respectively, so I'll turn these down to 10 until I get everything dialed in.

If you want to update the .ini configuration file later, the formula to convert this 2.54 mm/rev into "steps per user unit" used for the SCALE variable is described here and is as follows for my g0704 and motors:

STEPS_REV = 200 steps per revolution (equivalent to 360/1.8)
MICROSTEPS = 2 microsteps per step
LEADSCREW_PITCH = 2.54 mm per turn

Then scale is:

SCALE = STEPS_REV * MICROSTEPS * LEADSCREW_PITCH = 200 * 2 * (1/2.54) = 157.480314961

For the Z-Axis, the handle indicates 0.166" per revolution or 4.2164 mm/rev, so our Z-Axis scale is:

SCALE = STEPS_REV * MICROSTEPS * LEADSCREW_PITCH = 200 * 2 * (1/4.2164) = 94.867659615

Backlash Compensation

After ensuring your scale is correct, measure the backlash using a dial indicator.

Add this to the g0704.ini file under each axis. Also increase the axis joint's MAX_ACCEL value by 2x


I built a touch probe and touch plate for easier and more reliable setup.


I have setup my machine to be manually homed above the touchplate. To avoid a crash, be sure to home it such that the longest tool can travel down 50mm before contacting the touchplate! The tool will automatically move 50mm down before probing. This settings is further described below, but change the following parameter to change this behavior.

# Absolute Z start search coordinates
Z = -50

With the probe in place and the machine homed above the touchplate, use the two remap M6 buttons on the probe screen to first probe the touchplate then probe the workpiece height.

With this done, probe the workpiece to set the G54 offsets and begin machining.

Even without limit switches, the machine can easily be kept homed between power cycles by homing the machine before turning off the machine and when the machine is re-powered on, simply set the home to the current position before moving the machine.

Probe Hardware

I built two probes, a tool setter and a touch probe. They are both normally closed and wired in parallel, so if either one triggers, the pin will go low.

Tool Setter

I don't have plans for the touch place, but it's basically just a microswitch bolted into a turned piece of aluminum round stock. There is a hole in the bottom so it can be bolted onto the table. I also placed a lightweight spring inside the mechanism to encourage the touch plate to move back up when not under pressure.

The touch plate diameter on the top is just under 20mm.

Touch Probe

I designed a mostly 3D printed touch probe. The design files and detailed build instructions are available on thingiverse.

It uses 6x 8mm bearings (actually 7.5mm diameter) in conjunction with 3x 4mm steel rods to create an exact-constraint mechanism. When the mechanism in capture, the circuit is complete. When the probe is moved slightly in any direction (including up), continuity is broken and the switch triggers.

The small wires are held in place under the pressure of the bearing. Bearings are attached by a small m3 bolt into a drilled and tapped hole in the bearing.

The rods are press fit into the probe-tip holder in the middle.

Capture is encouraged using a spring.

Any size shaft and probe tip can be used. I used a 1/2" piece of steel rod I had laying around for the shaft and a small brass rod along with another ball bearing for the tip. This works well, but with such a large tip, probing any surface with less than 4mm height is not possible, so I will probably change this to use a small ruby tip in the near future.

The top of the probe is connected with 3x m3 bolts.


Both probes are wired in parallel, as shown below.

There is also a connector for the touch probe, so it can be removed if necessary, while maintaining continuity for the tool setter.

Probing Setup

Configure the HAL, one wire of my probe is plugged into pin 15 and the other wire to the nearby ground.

Configure the HAL as follows:

net probe-in        <=
net probe-in        => motion.probe-input

Install probe screen v2

Comment out the bottom of the hal file, replacing them with the single line config for probe screen:

Comment out:

#loadusr -W hal_manualtoolchange
#net tool-change iocontrol.0.tool-change => hal_manualtoolchange.change
#net tool-changed iocontrol.0.tool-changed <= hal_manualtoolchange.changed
#net tool-number iocontrol.0.tool-prep-number => hal_manualtoolchange.number
#net tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared


net tool-prep-loop iocontrol.0.tool-prepare => iocontrol.0.tool-prepared

Download and unzip:

curl -L -o
sudo apt install -y unzip
cd probe_screen_v2-linuxcnc-2.8/

Copy the configs into your machine configuration directory, my config directory is ~/Desktop/g0704

cp -r python ~/Desktop/g0704/
cp -r macros ~/Desktop/g0704/
cp -r probe_icons ~/Desktop/g0704/

Install the plugin by adding the following in the [DISPLAY] section of the .ini config file:

EMBED_TAB_LOCATION = ntb_user_tabs
EMBED_TAB_COMMAND = gladevcp -x {XID} -u python/ probe_icons/

Configure the plugin by adding this to the bottom of the .ini file and modifying as necessary. Take care to merge any sections that already exist, such as RS274NGC:

# Absolute coordinates of the toolsetter pad
X = 0.001
Y = 0.001
# Absolute Z start search coordinates
Z = -50
# Maximum search distance and direction (sign)
# Speed of movements during working in Probe Screen
# Diameter of toolsetter pad
# The speed of the reverse rotation of the spindle when measuring the tool diameter

# Abs coordinates tool change point
X = -20
Y = -20
Z = -10

PARAMETER_FILE = linuxcnc.var
RETAIN_G43 = 0
REMAP=M6   modalgroup=6  prolog=change_prolog   ngc=manual_change  epilog=change_epilog

PATH_PREPEND = ./python
TOPLEVEL = python/

Note: that with this configuration the toolhead or probe will drop to Z = -50 (in absolute coordinates) before probing up to -170mm more. Make sure your tool is at least 50mm above the toolsetter or decrease this value!

More user documentation for probe screen v2 can be found here:


I use the Fusion360 Manufacturing tools for my CNC toolpath planning and code generation. The included LinuxCNC post processor works great: