Background: After running into numerous projects (and project ideas) where it would be convenient to have a metal-capable CNC mill (not router), it was finally time to build one. Since I can't justify the cost of a larger light duty CNC mill, nor have the space for one, the goal of the project was to create a rigid, portable, and affordable CNC mill.
Despite being a much more ambitious and challenging project than some previous year-long projects, this machine went from conception to operation in about 5 months thanks to the resources and tools available to me at my new workplace - sometimes having the right tools for the job is invaluable.
To help better explain some of the design intent here, we'll need to address some of the constraints and criteria of this project.
Criteria:
Suitably rigid for cutting ferrous metals and using large tooling involving high torque and cutting forces.
Reasonably heavy to help dampen cutting vibrations.
Acceptable precision motion and squareness for hobby purposes.
Constraints:
Portable - to be moved between different locations during and after manufacturing.
Low cost, under ~$3000
Manufacturable with given equipment (ie. making sure milled faces fit within manual mill work capacity)
Working XY capacity of at least 6" x 12"
Before designing anything, deciding the core frame design/kinematics was necessary. While most hobby CNC machines (routers) will utilize a moving gantry spanning across the work area, you'll typically notice that larger, industrial CNC machines make use of a large fixed vertical column along which the Z-axis/spindle moves, while the X and Y axes travel on their own as moving 'tables'. The reason a fixed vertical column style is generally favored for heavier-duty usage in metals is that pound-for-pound, the rigidity of this design is typically much better than moving gantry style machines. Some exceptions can be made for other variations, like a 'portal' design, but this can become a rabbit hole not worthwhile exploring here. To conclude, I had chosen to pursue a fixed column style design. Asides from rigidity, this style lends itself much better towards portability in my case, since this style of machine is self contained without the need for any table or base surface.
There's a lot of rambling in this section, so feel free to skip ahead to photos if you're not curious about the thought process behind any of the selected hardware for this machine.
It was basically a given that this machine would use profile linear rails, more specifically the HG-series of linear rails due to their tolerance of imperfect surfaces, low cost, and availability. Since Most profile linear bearing systems would already be quite over-specced for the purposes of this machine, and the only noticeable performance difference between bearing models would be based around bearing preload (or more likely manufacturing quality), I settled on HGR20 (20mm) rails with HGH20 bearings. I was fortunate to have found a set of two rails and four bearings made by Hiwin for sale used, the other two pairs of linear rails + bearings were purchased from generic overseas sources and are of questionable quality.
Next, ball screws were chosen based on the most popular size available (16mm), and their compatibility with the HGR20 system (only a 15mm offset between bearing and ball nut topmost/mounting surfaces). The ball screws selected were SFU1605 (5mm pitch, single start for an effective 5mm lead) for reasons of precision with the finite resolution of stepper motors, and low torque requirement for motor selection. It's hard to say, but I would also hazard a guess that this relatively low ball screw lead helps greatly with any minor deflection caused by any drive components (rubber deforming in jaw couplings, pulley stretching), and makes a good case for this use case.
All in all, the HGR15/20/25 + 16mm ball screw is such a tried and true solution in CNC that I can be confident this is a safe route to take.
I had convenient access to a GRBL-based controller with built in TB6600 stepper drivers, as well as a few other features. These drivers are just about at the lower limit of what would be required to have a heavy machine like this operate without any issues or lack of max speed, but they've ended up working okay so far. Using GRBL firmware is very limited feature-wise, and is only a temporary solution until the machine proves itself capable. I'd like to switch the controller system to LinuxCNC or Mach3/4 at some point for other useful features like rigid tapping and closed loop servo capability.
The motors being used are 425 oz-in NEMA 23 motors. These might seem quite undersized for this type of machine, but due to the relatively low lead of the ball screws used, they produce plenty of torque for this use case. The Z-axis gantry was to be counterbalanced as well, so there were no concerns about a lack of pull-out torque, nor detent torque to cause this heavy gantry to lose position.
For the spindle motor, I was dead-set on using an AC servo motor for a number of reasons:
Constant speed, incredibly useful for machining demanding materials such as steel.
Ability to configure rigid tapping with software.
Ability to halt the machine's movement/program should an alarm or torque limit be reached by the servo (indicating a crash).
Small form factor, since my machine is on the smaller side of mills.
The AC servo I ended up selecting was an 80ST-M02430 1kw unit with a max speed of 3000rpm. This is on the lower side of things, but I figured I'd start small/cheap and upgrade to something 3kw+ later on if the machine seemed like it was up for more aggressive cuts.
The spindle chosen was an ER25 spindle head with matched angular contact bearings - good for up to 6000rpm. Obviously, a better choice would've been to go with a BT30 spindle for future auto tool change capabilities, but as someone who didn't anticipate using this machine for large production runs I didn't think this was a justifiable cost.
To drive the spindle via the motor, we'll use a HTD-5M pulleys rather than V-groove pulleys so that we can leave doors open for rigid tapping at some point without worrying about belt slip.
Ideally, I would've purchased the steel for the frame of my machine based on what I had designed - not so much the case when steel is quite expensive, and there's lots of it needed. While pondering ideas for rough designs, I came across this 3.5" 3/8' wall thickness HSS steel being sold for a very reasonable price of $40. Some napkin math showed that this would be suitable for a machine of the rough size I was looking for, so I picked this up and began redesigning around it. They had some surface rust but cleaned up very well as shown. There are some complications (flatness, welding, etc.) involved in using these steel sections as the frame for a CNC, but we'll address those as we get to any relevant steps.
A bandsaw would've been idea for cutting these, but you make do with what you have.
Picked up some other hot rolled 3/8" plate for some other bits. These probably cost more than the 100lbs+ of HSS.
I was lucky enough to have access to a small milling machine at my workplace to get anything I needed flattened/squared. Access to this mill was obviously invaluable in this entire project, it's hard to make a CNC mill without at least a non-CNC mill...
The frame splits at the corner joint between the vertical, and horizontal steel sections. This has two very big benefits: easier disassembly for portability, and easier adjustment/accessibility for tuning.
The large frame was expected to weigh almost 200lbs when assembled without any other gantries, since I was planning to be test-assembling this in my one-bedroom apartment and moving this across several locations in my sedan, the only possible hope I had of doing this was by allowing the frame to split into two pieces.
To address the imperfectly square machined surfaces which would be used to define and constrain the machine's squareness in the YZ-plane, as well as the effects of warping that would happen during welding, by having the two mating surfaces readily accessible and adjustable I'm able to assemble then correct any issues post-manufacturing. This is incredibly important for such poor manufacturing tolerances and outcomes when making a pseudo-precise machine.
Joining the two pieces would be done using 3/8" bolts (sticking with the whole 3/8" theme) and would utilize as much of the surface area of these plates as possible - I really didn't want this joint to be a point of weakness for such an otherwise stout frame.
A last key feature was the machining of a slot wherein the joining plate would reference off of and be constrained during welding. In order to get the ball screws that would drive this machine to be as close to parallel with the linear rails of each axis, I would need to machine the mounting surfaces for these two items post-welding. By constraining this plate between the two steel tube sections, it would be reasonably close to parallel and would be constrained from warping along its length during welding. The closer I could get these surfaces to parallel before welding, the less clean up work I'd have to do later on, and I had already had my fill of steel surfacing at this point.
This could've gone worse, but also could've gone much much better. I'd done my best to prep all these thick pieces for decent weld penetration with chamfers where necessary, but despite my best efforts, it was not a great time. I had run out of welding electrodes for stick welding, then proceeded to TIG weld where possible out of desperation. On the bright side, some of the welds ended up looking kind of cool.
There were some fancy looking welds, I sure hope they're actually doing something. You might also notice that I didn't include close-up photos of any stick welds; there's a reason for that.
Not great, not bad; pretty much about what I expected. You can see in the photo below the light passing through the large steel square against the faces of the two weldments bolted together. It seemed to be a few millimeters out of square across ~2 feet, so nothing I couldn't fix later on while machining mounting surfaces.
Now that the hard part was over, and I was left with the finished weldments for the frame and X-axis table, it was time to start machining all mounting surfaces for linear rails, ball screw mounting hardware, and anything else. A reference edge was machined for each pair of linear rails, then rails were clamped and holes were transfer punched for drilling.
So far, so good, the X and Y axis were moving just fine without any binding, indicating that my mounting surfaces were adequately flat and parallel. HG-series linear rails are designed to be quite tolerant of imperfect surfaces, so this might've been a contributor to my success. You'll also notice two things not discussed in these photos:
The sketchy-looking CNC-cut MDF jigs used to align the 'floating' linear rail to the reference rail for hole transfer punching.
These worked well since dimensional error didn't matter so long as it was even in each jig to ensure parallelism between both rails.
The aluminum X-axis table mounted onto the X-axis weldment.
This was just a 3/4"x8"x14" aluminum offcut I happened upon, with hole positions spot drilled using a CNC router, then drilled and counterbored manually. The bottom surface of this plate was surfaced flat for mounting as well.
Up until now, I had put my focus on getting a finished frame with mounting surfaces for the more trivial components of the machine. It was now time to shift focus on getting some of those more trivial components; the first being the Z-axis gantry which would hold the spindle and spindle motor.
There isn't much to talk about with this piece. Its only job is to hold the heavy spindle further out from the Z-axis column to gain Y-axis travel. Since this sits quite close to any cutting forces, it doesn't need to be terribly rigid since it has a very short lever arm to where these forces occur. In any case, gusseting was added mainly due to concerns of weld strength, since the rounded corners of the HSS steel I was reusing made any practical tee joint weld impossible. Not shown in this photo are the plug welds on the back side of the plate.
The mill was definitely starting to take shape at this point, I had only needed to begin manufacturing motor mounts and other bits but was waiting for a good weekend to start painting any finished parts. The spindle head I had ordered a month earlier had conveniently arrived. This is an ER25 spindle with matched angular contact bearings, good for up to 6000rpm. Runout of the inside spindle ER collet taper showed about .0005" of runout which is acceptable for my purposes. The only issue with this spindle was the awful green color which I would address later on during painting.
I brought the machine back home to paint any steel components one weekend. This was done using an enamel paint, mostly to help with rust and make everything look much less ugly. This was also a great opportunity to grind down any horrific welds.
You might notice some small blocks that standoff the spindle head from the Z-axis gantry in the photo above which we've overlooked so far. These do two things: stand off the spindle head a bit more for more Y-axis travel, and allow for easy nod/tilt adjustment during tramming. To correct for nod (misalignment in the YZ-plane), we can simply indicate off of our table surface, calculate the angle to adjust the spindle by, then remove either the top or bottom of these two blocks and skim a small amount from the surface. This avoids the need for solutions like shimming which can be annoying. To correct for tilt (misalignment in the XZ-plane), we can loosen the bolts holding these blocks onto the gantry, and easily adjust the spindle head alignment like you would with any other mill.
After measuring and facing the top spindle standoff block by 0.023", I was able to get the nod error to about ~0.003" across an 8" diameter sweep, and tilt error to be <0.001" - both completely adequate for my needs.
I made these aluminum parts on a CNC router using some stock I had laying around, with some faces cleaned up on the milling machine. With these parts finished, I was able to finally assemble the mill.
Z-axis motor mount installed
When ordering the HTD pulleys which would transmit power to the spindle, I had overlooked the need to request that keyways be machined inside the inner bore. To get this done, I was able to use a lathe tooling blank held within a lathe to manually broach this in many passes. I regretted this for the remainder of the evening, as I had blisters from the force needed to broach this with the lathe handwheel.
A very obvious issue with most VMC CNC mills is the absurdly heavy Z-axis gantries + spindles which must move up and down thousands of times with perfect repeatability. Since my Z-axis gantry, spindle, and spindle motor weighed close to 50lbs, I would definitely need to devise a counterbalance of sorts. There are two typical approaches to this: using one or more gas springs attached directly to the gantry, or a pulley/chain system that attaches the gantry to a sliding counterweight on the rear of the machine.
I wasn't keen on either of these because:
Having two gas springs protruding on the sides of the machine takes away from the aesthetics of the machine in my opinion
These two gas springs must be twice the length of the Z-axis travel, and would therefore stick out in my build.
Having a counterweight essentially doubles the moving mass the Z-axis motor must handle, meaning acceleration values must be reduced. This is very bad when using adaptive tool paths with lots of linking, or many pecking drilling cycles.
So here comes in the 2:1 pulley reduction gas spring pulley reduction design I thought of. This uses one single gas spring tucked away hidden inside the Z-axis column. A single steel core belt runs through two idle pulleys forming a 'block and tackle' belt path. This design does alot for addressing my above concerns very well:
The entire Z-axis counterbalance system is tucked away out of sight, with only a belt hardly visible from the front.
This system is much smaller in size (most importantly length) and does not extend the original footprint of the machine whatsoever.
There is no more moving mass added onto the Z-axis gantry, with the only increased resistance coming from the belt friction and damping from the gas spring.
Using a 2:1 reduction at the pulley, any damping effects that would arise from the use of gas springs directly connected to the gantry are essentially halved. Any spring factor in this gas spring causing it to stray from providing constant force would also be halved.
Considering that it's either very inconvenient, or ugly to use just one gas spring directly connected to your gantry, we can likely say that we've now only got 25% of the damping and spring effects compared to a typical 2 gas spring system on other machines.
Is any of this really all that serious? No, probably not - I just thought this was a clever design worth pursuing, and it ended up working very well.
Z-gantry lowered (gas spring fully compressed)
Z-gantry raised (gas spring fully extended)
The machine was finally finished at this point, and was ready to be moved and setup where it would be used. This was about 100km away, and was fit into the trunk and back seat of my sedan. You can see the pile of parts and frame pieces in the first photo below - everything shown here would make up one finished VMC mill.
The second photo shows the mill re-assembled in it's new spot. A wooden enclosure is being used for the time being, something more waterproof will be coming once I get around to deciding on a coolant system and way covers.
It's also worth mentioning that the wooden workbench I'm using here is very unsuitable, this machine would ideally sit on very heavy steel table legs in order to dampen vibrations; this will likely be built into a steel enclosure when that time comes.
With the machine finished at this point, I had tried to make some first cuts and almost sent a chunk of steel flying across the room due to the less than ideal clamping/work holding I was using. I immediately swore that I wouldn't try cutting anything else until I had a legitimate vise setup so thus began the process of making my own. I was also waiting on the arrival of more tooling from overseas to start taking larger cuts for testing.
Like many others, I was a big fan of the modular vise system made by Saunder's machine works and chose to replicate this for a number of reasons:
Very low profile, ideal for smaller CNC machines (even though mine has plenty of Z-axis travel to spare)
Easy and flexible positioning
Straightforward soft jaw adaptability
Simple and cheap to manufacture (this was the most important factor for me, since I would be making my own)
The only downside was that these use all imperial hardware and fixture plate hole spacing; this obviously wasn't an issue since I would be making my own and could design around any of my needs.
Rendering of my vise and fixture plate model
All pieces of this vise were machined using a CNC router. People will typically shy away from machining such large aluminum pieces on a CNC router, but even with V-wheels and a 900W trim router, this machine had no problem chewing through aluminum to produce these parts. Some of the videos below show these pieces getting machined - pay no attention to the chatter when cutting in the Y-axis though..
The results ended up looking pretty good, mostly due to facing some of the more visible faces of each part. This design uses M10 flat head cap screws to actuate the clamping force, and M8 socket head cap screws to lock the fixed jaw, as well as mount the vise to the fixture plate. An MGN12 linear rail was used as a vise jaw since these are already hardened to some degree, and closely mimic the solid jaw insert sold by SMW. I plan to sharpen and grind serrations on the inside edges of these bars for better grip in the future.
With the vise finished, it was time to start making the fixture plate. For stock, MIC-6 cast aluminum tooling plate would've been the most obvious choice, but I chose to cheap out and start with a 1/2"x8"x14" piece of extruded flat bar. Thankfully, this ended up being relatively flat, and will be constrained by 6 points onto the table anyways. The videos below show the process (in order) of:
Drilling the table mounting holes for the fixture plate.
Surfacing the X-axis table ahead of mounting the fixture plate.
Surfacing the fixture plate with this mounted to the table.
Now it was time to drill alot of holes - 109 holes to be exact. I didn't have high hopes for the cheap Mastercraft drill bit I was using to predrill these holes, but to my surprise it made it through with no problems. I realized afterwards I had forgotten to run a spot drilling program beforehand, but we'll see if we run into fitment issues due to hole position error.
After the holes were drilled, they were interpolated to M8 tap diameter with a shallow 8mm dowel pin counterbore for vise and fixture locating. These dowel holes ended up coming out as 8.03mm when checking with gauge pins, which is a good locational clearance fit with the 8.01mm dowels I'm using.
I also realized while doing all of this how badly I needed to shield the linear rails and ball screws with way covers.
To conclude on this side project, here are some glamour shots of the fixture plate and vise. I've still been procrastinating tapping all 109 M8 holes, maybe I'll just keep waiting until I'm able to use rigid tapping on my machine to automate this.
After making some of the first chips on this machine, I realized I couldn't procrastinate on making some covers to keep chips off of the linear rails and ball screws. Since the X-axis is quite exposed and the easiest to deal with, I made covers for these first. These are simple 1/8" rubbber covers mounted to the side of the X-axis table. Some cascading 'bellow' covers would've been much more elegant, but these would've drastically increased the machine footprint due to the X-axis design.
I had finally received one of the larger end mills I was waiting for before doing testing, this was a 1/2" 3 flute bright end mill suitable for chewing through lots of aluminum. I would later learn of the dangers of large end mills which don't break and instead throw parts.
This was a 1/2" deep contour @ 1mm stepover, 1200mm/min. I was mainly interested in seeing the quality of the wall surface, which ended up being pretty good considering the lack of coolant.
Next was some higher MRR testing, this time 1/4" deep @ 4mm stepover, 1200mm/min, for a material removal rate of 1.85 in^3/min.
The machine is definitely capable of much higher removal rates, but I was worried about stalling my spindle servo since I had yet to calculate transmission/bearing losses, and had not yet set up the servo drive alarm to cause the machine to stop and prevent bits from breaking.
This cut should theoretically demand ~0.35kw from my 1kw spindle. I planned to keep pushing this until reaching ~0.5kw, but as you'll see next, this wasn't going to happen with this vise setup.
This next clip shows an adaptive clearing I was running. This wasn't a particularly aggressive cut at 1/4" deep, 2mm stepover, 1200mm/min, but was enough to reveal the flaws of my current vise.
Once the cut starts, you'll immediately notice the workpiece shift to the right (and chatter). The rest of the cut goes okay, but once the tool gets to the front, it goes south fast. At the start of the cut, the left side of the workpiece had lifted up while it shifted sideways, so it was at an angle which I hadn't noticed. Because of this, once the tool starts cutting on the front, it ends up slotting and gets up to 3/8" deep, ripping the already loose piece out of the vise and tossing it.
I'd like to extend a big thank you to regional councilor Joe Dipaola for blocking the flying aluminum chunk with his face on this repurposed election sign.
So why did the vise slip?
Lots of people use this vise system with plenty of success, so its unfair to fault the vise design. My own version of this vise utilizes an MGN12 linear rail as the steel jaw which contacts the work which has two flat faces. I had intended to grind these faces down to more of a point, as well as create serrations along the length, but had been a bit too confident without doing so.
You can see the flat surfaces which contact the work in the photo below, and understand why this might've slipped considering the circumstances. The vise jaw bar insert used by SMW is shown on the right, and has serrations along it's length with sharped teeth to grip the work. I'll be grinding in teeth into my current vise jaw and checking it's holding strength fully before any more cutting.
Some next steps for this machine are:
Finishing a temporary wooden machine enclosure
Routing a Z-axis drag chain to manage spindle motor wiring
Installing electronics into a NEMA electrical enclosure
Adding some form of coolant system
Designing and machining a tool length sensor