Sub $200 PCB Mill that doesn't suck!

A PCB mill inspired by open source CNC 3D printers with a custom design to fit standard size copper clad boards (6" x 4" / 160mm x 100mm)

Similar projects worth following
A 3D Printer inspired CNC mill specifically designed to work with 160mm x 100mm (European Standard Format) or 6" x 4" as obtainable everywhere in the US.

Main Features:
- < $200 in material (excluding Multitool and mill bits)
- Etching of single as well as double sided PCBs
- Milling of random PCB outlines
- Drilling of all holes (> 0.5mm)
- Automatic homing
- Automatic Z-Leveling using probing in CNCGcodeController
- Precise enough for 8 mill traces
- Compatible to Eagle, PCB-Gcode, CncGcodeController, grblController
- Knobs for manually adjusting the position
- Only three 3D printed parts designed for PLA and to not warp
- Easy to lasercut on cheap Chinese K40 CO2 laser at home using 5mm plywood from the local hardware store (or in high quality aluminium on an industrial laser cutter)
- Very easy to assemble and to use
- Relay and wall plug for switching the Multitool on and off using G-Code
- Easy to transport and to set up
- No overly exposed wirin

Part List:

It would be good to have access to a laser cutter to make this. Otherwise just order the parts including material from your local laser cutting shop.

Print Instructions:

I use KisSlicer for printing my parts! I use it because it offers a VERY valuable function which calculates insets for holes. Properly calibrated, this gives me exactly 12mm when I design a 12mm hole! For all parts, this means that I can pressfit my linear bushings! Please keep that in mind before you kick of your 10h prints!

GPX Converter.rar

Tool to convert gCode to Makerbot binary format. Needs proper configuration in param.ini DISCLAIMER: I have only tested this on my Malyan M180 and have no idea if it works with Makerbot at all.

RAR Archive - 134.99 kB - 12/12/2017 at 03:40



IGS file for 3D printed part so that you can modify it to your desire.

Initial Graphics Exchange Specification (IGES) - 2.82 MB - 12/12/2017 at 03:37


Z-Axis UpperRodHolder.IGS

IGS file for 3D printed part so that you can modify it to your desire.

Initial Graphics Exchange Specification (IGES) - 2.24 MB - 12/12/2017 at 03:37


Z-Axis RunCat.IGS

IGS file for 3D printed part so that you can modify it to your desire.

Initial Graphics Exchange Specification (IGES) - 1.66 MB - 12/12/2017 at 03:37


NuggetMill5 - step.rar

Complete NuggetMill5 as a step file.

RAR Archive - 1.51 MB - 07/14/2017 at 01:43


View all 8 files

  • High Voltage Wiring Diagram

    Timo Birnschein07/15/2017 at 22:00 0 comments

    was asked to create a wiring diagram for the NuggetMill5, so here it is.

    I left the basic stuff for stepper motors and endstops out because I already described it in my logs below.

    Motors are standard. Just make sure they move in the right direction with my configuration. If not, please turn the plug around and it should be fine. I stole the 5Volts for the relay from the I2C port. I also needed to use the MIN EndStop inputs for the three endstops that are supported with this version of grbl instead of MAX as described for the original grbl. Please keep that in mind.

  • pcb-gcode bugfixes and github

    Timo Birnschein07/08/2017 at 20:53 0 comments

    I realized another bug when milling my first actual project on the mill:

    pcb-gcode, even though many people seem to be using it and the documentation seems excellent, seems to have quite a lot of bugs that are easy to fix due to Eagles C-like scripting language.

    The latest bug I found and hopefully just fixed is the issue that spotting holes during the etch step drills all the way to DRILL_DEPTH right after the first hole was spotted properly. Spot drilling is supposed to help a manual drill step by creating a center hole for the drill press to work with.

    However, after the first proper spot drilling, the V-shaped engraver bit got punched into the PCB all the way to the drill depth (1.65 mm) which widened my holes quite a bit, shrinks the restring unnecessarily, it costs time, it wears out the engraving bit and it's generally... simply a bug! I don't yet understand why the first hole and all other holes are handled separately but I guess I will find out as soon as I work on my next project.

    To make things a lot easier, I also created a github repository for pcb-gcode. I have no idea why the original author is not using github to distribute the software...

  • First actual project

    Timo Birnschein07/02/2017 at 22:36 0 comments

    There are a couple bugs left in the configuration and some gcode issues like the etch step is also used for drilling "again" for no reason. I need to fix that in the pcb-gcode script. However, the results are really cool!

  • Happy 4th of July!

    Timo Birnschein07/01/2017 at 21:21 2 comments

    Make something cool today!

  • What the YAD?

    Timo Birnschein06/25/2017 at 01:27 2 comments

    The moment you realize....

    Your X-axis is inverted. And I was like... Why the hack does the 'H' look so weird!!?? .... [long break] ... oh it's a 'Y'... darn.

  • Calibration Wizards for Ease of Use

    Timo Birnschein06/24/2017 at 23:26 0 comments

    Today was a good day. After realizing that rewriting lost instructions makes no sense at all since I should be able to create a proper wizard for machine calibration in the same time, I did just that.

    With grblController you now can

    • Mill double sided PCBs without any hassle
    • Calibrate / mill down your X-Axis Alignment Fence to be 100% parallel to your X-Axis
    • Perform the X-Axis calibration for milling the bottom side of a PCB

    Since my goal is to make everything as simple as possible to the user, I created a step by step instruction set on new tabs in grblController:

    Above you see the options you have available for PCB milling. I think, this should give you all the tools that you might need to mill your double sided PCBs. But since you need to calibrate your fresh machine first, I added the calibration tabs.

    This tab provides you with step by step instructions to properly mill down your X-Axis alignment fence. Please use one of these mill bits to mill the fence down and to make it absolutely parallel with your mills X-axis.

    The bottom side is a bit more interesting, even though it will take much less time to get right. Just follow the instructions and you will end up with a perfectly calibrated machine.

    One add-on I'm thinking about is storing the actual negative space coordinate system for milling the bottom side of the PCB into the grbl controller itself and not the software. It could be beneficial if you plan on moving the mill to another place and use it with different computers from time to time. But for now, I think it's fine that the settings are stored properly and platform independent on one computer.

  • Milling your first PCB

    Timo Birnschein06/22/2017 at 04:02 0 comments

    Milling a PCB:

    You have come this far, that is both admirable and awesome and I thank you for following along!

    But that also means you need to get the settings and instructions now to be able to mill your first PCB successfully. In other words, this log entry might become a little wordy but I will try to keep it as short as possible since I'm not a fan of reading 20 pages to get the bottom of a simple step myself.

    • Fire up eagle and load your board design
    • Move your entire board slightly away from 0,0 which should be at the bottom left. This is important because otherwise the mill will eventually end up running into negative space on the TOP layer and that is definitely NOT what you want. We want to keep things simple. Move it away by 5 mm in X and Y.
    • Use the info tool and move your outlines from the layer 48 Document to the layer 46 Milling. This will enable the pcb-gcode script to find your outline and generate your milling path for the outer contour of the PCB. Please keep in mind that the end mill will run exactly in the center of the mill line. There is no outer offset based on the diameter of the endmill being calculated by pcb-gcode! You have to design that into your board layout yourself!
    • At the top of eagle you find your command text field. Type "run pcb-gcode-setup" and hit enter.
    • Change all fields to the following settings if the settings I have provided in the pcb-gcode patch archive didn't do that for you already:

    The new item that I added so that your outlines can be milled without destrying your endmill is on the right. Num Slices is the number of layers for cutting the outline. So at -1.8 mm cutting depth this results in {-0.3 mm, -0.6 mm, -0.9 mm, -1.2 mm, -1.5 mm, -1.8 mm} different cut depths.

    Since the board in my example didn't need a bottom side, I deactivated the bottom layer features. However, I think the following should be selected for a dual layer board:

    1. Generate top outlines (there is a bug in this menu: If the top outlines are not selected, the top.etch file will not be generated. I might hunt that bug down later...). We will ignore the top.mill file!
    2. Generate top drills (we want to drill first)
    3. Generate bottom outlines (this is your mill file for cutting the outline of the board. We need to do that LAST!).
    4. The bottom.etch file will be generated automatically.

    Please note: I have deactivated Show Preview because it annoyed me after a while. When you know what the result should be, you can deactivate it. It speeds up the process significantly - not that it's very slow in the first place...

    The machine uses the speeds that OtherMill suggests for milling FR1 copper clad board. That is by no means super fast but it looks impressive enough. My endmill holds up to that speed and I'm fairly confident that my 10 mill bits will last quite a long time for their huge $9 investment (for all ten).

    Select the grbl-cyclone.pp file and go to the next tab.

    • That's it! Hit Accept and make my board.

    Now, you should have a range of files in your project folder.

    • (ignore forever)
    • (ignore forever)

    We do not want to drill twice. If there is a tiny misalignment in your PCB machine, you will not drill into a hole but slightly off the center of that hole. It is very likely, that your drill bit will snap and we don't want that! Specifically, if it ends up in your eye!

    Preparation of the PCB:

    Make sure the PCB is flat. If not, use some gentle force to flatten it. When it is flat enough, use double sided tape and apply it with even distance throughout the area you expect the machine to mill. More doesn't hurt but it would be good to be able to remove the PCB from the mill bed after milling without destroying neither the PCB nor the bed.

    Apply the PCB to the top left corner of the mill bed for the top side and make sure you have it aligned properly and totally parallel and flat to the top mill bed alignment fence....

    Read more »

  • Fixing an Eagle Plugin: pcb-gcode

    Timo Birnschein06/19/2017 at 03:38 0 comments

    For a long time, people using Eagle for designing PCBs and pcb-gcode to generate mill files for RepRap based cnc machines complained a missing feature/bug in pcb-gcode:

    All generated outline milling for the PCBs is cut in one go. As you can imagine, using a 1 mm endmill, even though carbide coated, doesn't like running through 1.8 mm fiber glass board in one go. People (including me) requested this feature for a while but it was no where to be seen.

    One of the goals for this project is to have the simplest solution for everything possible. Very much like the OtherMill software, where everything just works straight out of the box as long as you follow the rules that are clearly laid out for you. Therefore, adding Z slices for the PCB outlines to the gcode by hand only to mill out the PCB was not an option anymore.

    So, as if I didn't read enough foreign code this weekend, I dug into yet another code. Luckily, Eagle uses a scripting language for their ULP files that is very much like C, so adapting to that was easy and very straight forward.

    I added a text field to the pcb-gcode-setup that allows to set the number of slices used to cut the outline of the PCB:

    I also modified two more files to add the actual functionality. It turned out to be extremely easy since I essentially only added a text field and a for-loop where the commands are generated written to gcode file.

    I'm very happy with the results. Just download pcb-gcode and add my simple patch to it.

  • grblController Extention

    Timo Birnschein06/19/2017 at 01:43 0 comments

    Today, after installing the latest QT - which took forever! - I managed to get the grblController compiled on my system. It's actually very easy, just don't follow the build instructions. Installing the latest free QT is enough to build it, if you install the entire package including MinGW for your 5.9.x installation.

    So after waiting for about 2h for the installation to finish I opened the project file and was presented with a nicely structured code in good old QT manner with signals and slots and the goodies I love about QT.

    To my surprise it was easy to compile. There are two standard QT includes missing which I added into my fork of grblHoming (the actual name of grblController). After that was done, I started adding buttons and some text fields that I wanted as comfort functions for PCB milling.

    As you can see in the image above, I added a new tab specifically for PCB milling. It offers an actual homing command ("$H") for grbl, probing commands using some parameters for the probing as well as setting the machine offset after homing for milling the bottom side. All of this works really well now and I'm eager to start some actual projects with the mill.

    At the bottom, I also started to add some stuff for autoleveling. I think this is a very useful function for PCB milling since the milling depth is in the -0.1 mm to -0.2 mm range and every little deviation from Z=0 will cause your track quality to suffer dramatically. So, if I run into problems, I might add this feature later. Right now, the mill bed is flat and I don't have an immediate need to implement this into grblController.

  • Now grbl controlled - by mistake...

    Timo Birnschein06/18/2017 at 06:41 1 comment

    Today was an interesting day. I Almost completely wasted my Saturday by eliminating the stuttering that some people on the internet thought it was caused by Marlin when running over very small line segments. The internet claimed, Marlin has issues with those super small line segments and can't keep up. But the developer said it was fixed.

    Apparently, it was.

    I invested the first three hours of today getting grbl for the Cyclone mill to work on my mill. It should have been straight forward if Cyclone would use standard pinouts. But grbl runs to MAX endstops by default, so I wired up my endstops to MAX on the RAMS1.4 board. However, the Cyclone port only uses MIN endstop pins. As soon as I figured that out the machine was ready to be tested.

    The grbl for Cyclone seems to be using a different homing pattern in general. Even when the offset from home is set to 0, grbl moves the tool head away from the endstop so that the mechanical endstop turns OFF again. Since these mechanical endstops have a hysteresis, my previous X0, Y0 is now slightly offset. That means I have to recalibrate my bottom layer milling offset again as well. It won't just be Y-162 anymore. But we will see.

    And then the actual issue of the day: It wasn't Marlin. It's the gCode sender - AGAIN!

    I experienced this issue before when I tried to use my K40 laser cutter for image engraving with a new laser power value every 0.1 mm. I had to write my own gCode sender in order to make that kind of data rate happen. And now, I tried to use CNC-gCode-Controller again, with all its comfort functions, and I see.... it still stutters exactly like Marlin! We're 4.5h in at this point.

    So I tried my own gCode sender and voila - it runs buttery smooth. But my version is console based and doesn't offer any other features than sending gCode as fast as possible to grbl.

    So I tried to dig into the horrible Java code of CNC-gCode-Controller and tried desperately to identify where the gcode is actually sent to grbl and how it was organized. A hopeless endeavor since there is practically no documentation and (in a classic Java manner) so many classes and helpers and whatever Java construct you can think of that I as C++ developer had to give up. I don't like Java. I only use it when I absolutely have to.

    We're 9h in now.

    The remaining 3.5h of the day, I restarted my search for some GUI based system that might be fast enough (I'm not laser engraving here) to send a PCB to grbl, so I found grblController again! And best of it is, IT WORKS!

    Unfortunately, I still miss a bunch of comfort functions! Here is an example:

    To mill the top side of the PCB I have to manually send

    • $H - for homing the machine and have it execute the first init line I gave it which is
    • G92 X0 Y107 - this sets the coordinate system at home X0, Y0, Z0 to X0 Y107 (done automatically by grbl now using $N0=G92X0Y107)
    • G0 X0 Y0 - to run the machine to actual PCB home for top side to be able to install a copper clad board (done automatically by grbl using $N1=G0X0Y0)
    • G38.2 Z-10 F20 - to probe for endmill - PCB contact with attached probe wires
    • G92 Z0 - to reset the coordinate system for Z to 0

    Now I can hit start! I would love a button for the first step and another button for the Z probing.

    To mill the bottom PCB I have to do even more:

    • $H - for homing the machine and have it execute the first init line I gave it which is
    • G92 X0 Y107 - this sets the coordinate system at home X0,Y0 to X0 Y107 (done automatically by grbl now using $N0=G92X0Y107)
    • G0 X0 Y0 - to run the machine to actual PCB home for top side (done automatically by grbl using $N1=G0X0Y0)
    • G92 X-160.3 - to let the machine know it is now in negative space with working coordinate at X=-160.3 mm
    • G0 X0 - to run the machine to actual PCB home for BOTTOM side
    • G38.2 Z-10 F20 - to probe for endmill - PCB contact using my probe
    • G92 Z0 - to reset the coordinate system for Z to 0 and leave X and Y where at is

    Again, buttons and confirmation would be cool to have to be less prone to user errors.

    Right now,...

    Read more »

View all 15 project logs

  • 1
    Step 1

    Printing the parts:

    Please use a slicer that supports calibrating holes properly. I use KisSlicer for slicing, there is a free version available that supports printing one type of part at a time. You may print multiple of them at once but only the same part. I love it because it allows me to print 15 mm holes at exactly 15mm so that I can press my linear bearings into the holes and don't need any additional thing but a vice to fix them in place for the lifetime of the part. It's also just $42 or so and its generally really good and requires more attention by 3D printer owners!

    Since you can do what you want and PLA and especially ABS will always warp at least a little bit, I designed the parts with warping in mind. I added tension releasing cuts where possible and all functional surfaces are facing away from the print bed. Therefore, you have to press the brass nuts in on the TOP side of your prints and never on the one that was flat on print bed. I changed the design of the X-axis (going from left to right when you look from the front) so that the next person to print these parts puts the brass nut on the onside of the X-axis because that side is more likely to be flat and 90 degrees than the print bed side.

    Since the parts are pretty large, the print of each takes many hours. Between 8 and 11 hours in my case at 0.2 mm layer height and 33% infill.

  • 2
    Step 2

    Laser cutting the wooden enclosure:

    This proved to be a challenge on my K40 laser cutter. I bought this super cheap $5 a sheet plywood from home depot and hoped that I could cut it well because I did it before. But I was wrong. Cutting multiple parts in one go seems to heat up a component within the laser so that the cutting power goes down. At first randomly, later permanently so that the system needs a cool down phase. Even changing the final focus lens to a 38.4 mm lens to get more power in one spot did only improve the situation but not completely eliminate the issue that some parts just wont cut after cutting a few before. It works, but it doesn't work well. I suggest to honer your local maker space and ask to use their laser cutter for a tip. They will cut all the parts in no time, you get the precision you want and you get to know some very nice people!

    I glued the parts together using wood glue. It is very easy so do since you can just lay them side by side and apply a bead of glue. Fold the parts and add M3 x 12mm screws and M3 nuts. Tighten the screws but please don't over-tighten them. The wood will crack and it's not necessary. The screws are more an accessory to get the mill into shape and to support the glue while drying.

  • 3
    Step 3

    Building it up:

    I highly suggest to order the hardened steel linear rods cut to the proper length! They are... VERY hard. Using a hacksaw to cut them will cost you more time and money than just ordering them at the proper length. I used an angle grinder with a thin 1 mm cutter to cut them and even that took some time at a proper workshop. Most ebayers except these requests because they have to cut them anyways.

    Putting the rest together should be pretty straight forward.

View all 9 instructions

Enjoy this project?



Paul McClay wrote 03/31/2021 at 07:30 point

Hi Timo. Thanks for the skull/follow for #Minamil! It won't do 100x160mm, but I wonder -- since you've had this machine for a few years by now -- how much of what you do with this could be done in 55mm+ x 55mm+, or maybe 70mm x 70mm?

  Are you sure? yes | no

Andrew Herdman wrote 07/12/2017 at 02:05 point

Great project, I'm building one, I've got all the wood laser cut and am collecting the other items, some will be quicker than others.  Do you have any pictures of the electronics section of the project to share?

  Are you sure? yes | no

Timo Birnschein wrote 07/14/2017 at 01:38 point

Hey Andrew, this is great! Thank for building one! It feels really good, if I'm honest :)

I will gladly work on a schematics for the power back pack. Generally, it's simple.

Power cable goes in, through the Home Depot light switch, to the power supply and also to the relay for the spindle and from there to the 115V power outlet of the spindle. From there, the other phase is routed back to the cable (I just used the power supply as a terminal block) and also from the power supply back into the 115V cable.

The only real trick here is that the relay needs 5V active high and you don't have that for free on the RAMPS 1.4 board. Only as open collector (essentially active low) through a MOSFET that is used for one of the heater elements of a 3D printer. But to be able to use M3 and M5 to start and stop the spindle, you need to solder a wire directly to the D9 pin on the ramps board. Not nice, but you won't need to change that board ever again.

Give me a couple of days. I assume, you'll be waiting for parts anyways. :)

  Are you sure? yes | no

Andrew Herdman wrote 12/11/2017 at 22:00 point

Hello, the build continues!  I've got all the parts, but ran into an issue with the 3d printed pieces (as you mention in the build log).  I can't use Kisslicer on the printer i'm using (Makerbot).. and lo and behold, the hole is about 0.4mm too small.  I tried increasing the size of the dimensions by 102.5% on the axis's with the holes, that works (for the bearings) but the part is now dimensional incorrect, I was just going to fix up the dxf files for the new dimensions, but then checked harder, and yup, the 3d printed parts on the dimension I didn't change, are affected.  Could you provide me access to the solid models of the 3d stl files?  I use Fusion 360 and stl to solid isn't it's best cup of tea.  I've got a 21mm and 15mm twist drill bits ordered, but they are weeks away from arriving...



  Are you sure? yes | no

Timo Birnschein wrote 12/12/2017 at 03:42 point

I can't reply to your second message for some reason but I uploaded igs files for you to import into whatever software you use. It's a standard format and you should be able to import them just fine. Please let me know.

Also, there is a tool available that converts the gcode from kisslicer into the binary format that your makerbot (or my Malyan M180) is using.

  Are you sure? yes | no

Jon Raymond wrote 07/04/2017 at 19:47 point

Wonderful and well thought-out project.  Is it possible to include STEP (or source) files as well for the 3d Printed parts so they can easily can be modified?

  Are you sure? yes | no

Timo Birnschein wrote 07/14/2017 at 01:44 point

Yes. I stepped out the entire NuggetMill5 - step.rar

Cheers and please let me know what you modify!

  Are you sure? yes | no

Patrick wrote 07/02/2017 at 21:46 point

Maybe you can try AtCore to control your CNC.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates