Milling a PCB

Using a CNC-mill to create a PCB has several advantages:

  • Fast
  • High accuracy
  • Holes are drilled for you directly
  • No chemicals
  • No need for UV exposure or direct toner transfer

This is how it is done:

When the PCB is designed (see this post) it’s time to prepare the board for manufacturing. I start by creating new layers for the mill paths.
1. Create mill paths

  1. Offset pads and traces to create closed loops for the PCB. These loops are used to control the engraving tool to cut out the copper areas to save.
  2. When the loops are done I offset them in order to create paths for removing excess copper outside the traces. This is not always necessary, but it is easier to solder a PCB without any excess copper. Don’t forget to make sure that you trim away offsets that intersect other copper traces.
  3. Make sure I have points in each hole that needs to be drilled. (used by CAM to define drill positions)
  4. Offset the contour of the PCB in order to create the release path for the PCB. I usually use a router with 3mm diameter for this -> the path is 1.5mm outside the PCB contour.
  5. Export all mill data. As preparation I convert all paths to polylines and make sure that they are connected. I have written two Rrhino scripts for the export. The first one exports each control point on the polylines into a comma separated file. This file is then used to create the engraving and cutting paths as CNC code for the mill. The second script exports each point to another comma separated file, this time to create the CNC code for the drilling operations.

2. Create CNC code
The comma separated files does not contain any information about for spindle speed or federate so they need a little more preparation before they can be uploaded to the mill. What is needed is a program that parses the data and converts it to standard G-code. The program also needs a user interface that would allows you to select cutting method, add data about federate and cutting depth etc. I wrote the whole script as an html file with embedded JavaScript. The good thing with JavaScript and html is that it runs on all platforms, does not need to be compiled, html it gives you the a user interface and it is fast enough, even for bigger jobs. This is what you need to do:

  1. Select cutting operation (2D cut for the PCB engraving)
  2. Paste the comma separated data in one text field and press sort to reduce travel distance
  3. Adjust the cutting values and press convert to generate the G-code
  4. Copy the generated code from the text field and paste it in a text document.

3. Check the g-code
It is a good habit to briefly go thru the g-code before you execute it. Make sure the right tool is selected, that all coordinates are positive and that the cutting depth is correct.

4. Load the mill
Insert an empty fr4 substrate into the mill. My current mill does not have a vacuum plate, so I use double sided adhesive to attach the PCB to the plate. It it very important that the top surface is completely flat and in level with the mill x-y axis. If you planar the area first with a router the result will be better.

5. Press play to continue
Upload the g-code to the mill, press “start” and watch the mill produce a the PCB. If the mill does not have an automated tool change, you need to run each operation separately and manually switch tool and measure the tool length. If tool change is automatic you can create a single file with all the operations and just lean back and enjoy.


Rhinoscript for polyline export (control points):

 _-RunScript (
	'Export all control points at curves as neutral file format
	Dim strObject, arrObjects, lineCount, pointCount
	strText = ""
	arrObjects = Rhino.GetObjects("Select lines to export")
	If IsArray(arrObjects) Then
		For Each strObject In arrObjects
			lineCount = lineCount+1	

			' Get the curve's control points
			Dim arrPoints
			arrPoints = Rhino.CurvePoints(strObject)

			' Write each point as text to the file
			Dim strPoint, strText
			For Each strPoint In arrPoints
				pointCount = pointCount+1
				strText = strText + Rhino.Pt2Str(strPoint) + ";"
			strText = strText & vbCr & vbLf
		If Not IsNull(strText) Then
			MsgBox CStr(lineCount) + " paths, " + CStr(pointCount) +" points copied to clipboard", 0, "Clipboard Text"
		End If
	End If

Rhinoscript for point export:

 _-RunScript (
	'Export all points as neutral file format
	Dim pt, strObject, arrObjects, pointCount
	pointCount = 0
	strText = ""
	arrObjects = Rhino.GetObjects("Select points to export")
	If IsArray(arrObjects) Then
		For Each strObject In arrObjects
			' Write point as text to the file
			pointCount = pointCount+1
			pt = Rhino.PointCoordinates(strObject)
			strText = strText + Rhino.Pt2Str(pt) + ";"
			strText = Left(strText,Len(strText)-1)
			strText = strText & vbCr & vbLf
		If Not IsNull(strText) Then
			MsgBox CStr(pointCount) +" points copied to clipboard", 0, "Clipboard Text"
		End If
	End If

 See also

CAM processing in HTML


Related posts:

12 thoughts on “Milling a PCB

  1. Pingback: CAM processing in HTML | Johan von Konow

  2. hi.
    your workflow is quite interesting. I understand that you dont use a CAD to design the pcb so I presume the milling path creation is also something of a speciality.

    What software do you use to do all this? Since creating a millpath is a major pain even in a standard workflow (CAG -> CAM -> gcode )

  3. Pingback: Accelerometer and digital compass (BGA & LGA) breakout board | Johan von Konow

  4. Pingback: Web access lab board (internet of things) | Johan von Konow

  5. Pingback: Designing a PCB | Johan von Konow

  6. Pingback: Ultimate PIC16F628/627 breakout board | Johan von Konow

  7. Pingback: Miniature USB to serial PCB | Johan von Konow

  8. Pingback: Bringing a 12 year old Roland MDX-20 up to date | Johan von Konow

  9. What kind of milling heads do you use? I tried CNC pcb milling but I had whiskers and problems with milling heads wearing down.

  10. Pingback: Nanino – the DIY friendly Arduino | Johan von Konow