Tuesday, 28 August 2012

CNC drilling software development

Ever used Mach3 for your CNC machine? Or RouteOut? Or one of those other CNC applications with a myriad of settings so that it can support any type of CNC machine?

If you've ever bought a second-hand CNC machine off eBay or tried to build one from salvaged parts, you know how difficult it is to work out (or guess at) the settings to make it work. Sometimes you end up shoving numbers in and keep tweaking until the actual output sort-of matches the drawing files you give it.

Well not any more....

Not only has Robot Steve redefined simple CNC design, with his awesome push-fit chassis, but this custom-written software is designed to do away with CNC-hardware-related headaches. Simply load a file, manually move to head to a start position (origin), move the head to a second position, then hit go.

At the minute the software can read NC drill files.
Here's the app reading a drill file generated from an Eagle PCB


After calculating the scale and rotation for each point (at the minute we're just working on scale, having just read in an nc drill file) the software runs through each point, creating a "cutting path"


At first, something appears to have gone wrong down the left-hand side. But on further inspection, the software is actually following the simple rule "move to the nearest hole that hasn't been drilled yet".
Because we set the origin to the top-left-most hole then travel to the bottom-right-most hole, the cutting head  should be at the bottom right of our PCB.
From here, it starts with the rule "move to the nearest point" then marks it as "drilled" when it gets there.
Repeating for only holes that haven't been drilled creates the cutting path above.


Monday, 27 August 2012

CNC drilling machine first test (x- and z- axis)

After a successful couple of hours at the nerd cupboard, we managed to get Steve's CNC design working in two axes. The test board simply uses buttons to turn a connected stepper motor clockwise and anticlockwise (we've yet to finish our controller software) but proves the concept of moving a drilling head across a gantry and performing a plunge-and-drill operation.



Exhilarating stuff!
We're particularly pleased with the dual-servo control: the first servo is actually an RC motor controller and sets the drilling spindle spinning. Then the z-axis servo plunges the drill head, pauses, and retracts the head, before stopping the drill spindle. (In code we "detach" the z-axis servo so that it is only powered for as long as is required.)

Surely it's only a matter of time before the y-axis (cutting bed) is in place and we're ready to try out some custom software to drill our first board!

CNC drilling software (open source?)

We're still not 100% au fait with the requirements for open source, GNU licences and all that kind of stuff - does everything in the chain have to be open source? Can we use our preferred PIC microcontrollers to make a USB device when the Microchip software and USB libraries are not open source? Does it really matter?

We're blundering ahead with our software, but have hit upon two potential problems - and hopefully workable answers to them:

The first is converting the NC drill file units (mm or inches) into steps on our CNC machine.
Since a big part of our design process is to make the machine easily repeated and built from spare parts (salvaged printers are a great place to get hold of cheap steppers) we're trying to work from the assumption that the end user knows nothing (or very little) about their hardware.

Rather than have the user enter all kinds of values to describe their hardware (or worse still, guess at them) we thought we'd have a simple manual calibration routine at the start of the software. Simply put, the user loads their pre-printed/etched PCB onto the cutting bed and moves the drill head above the top-left-most hole (the software will highlight one if there are multiple possibilities). This will form the origin (co-ordinate point 0,0) for our cutting routine(s).

The software will then find the bottom-right-most hole (furthest away from the origin) in the drill file, highlight it and prompt the user to move the drill head (maybe using the computer keyboard's arrow keys or similar) above this second hole. Using these two co-ordinates we can calculate two vitally important things: scale and rotation.

In the NC drill file we have co-ordinates for every point on the board. Using pythagoras theorum (a^2 = b^2 + c^2) we can calculate the distance R1 between the top-left and bottom-right points. On our actual PCB, this represents the same distances between the same two points. The only difference is the units used to measure this distance.

In the same way the same distance can be described in imperial (inches) and metric (millimetres) by multiplying one set of values by a constant, we can do the same to convert inches or millimetres in the NC drill files into steps on the CNC machine. Let's pretend both images (above) are exactly the same size. Let's say the distance R1 is measured in millimetres, but we want the same distance R2 in inches. We know that 1 inch = 2.54cm and 1cm=10mm. So we can easily compare R1 (mm) with R2 (inches) by multiplying R2 by 25.4 (or dividing R1 by 2.54 to get R2, the same distance in inches).

We don't know what this constant value is to convert our NC drill measurements (mm/inches) into number of steps, but we can calculate R2, the distance the drill head travelled between two points, in terms of steps. Knowing the value of R1 (in, say, mm) and the distance of R2 in steps allows us to calculate the scale between the two. Scale = R2/R1

The great thing about using the first hole as our origin point is that it doesn't actually matter at this stage whether or not the PCB board on the CNC machine is dead square. If the PCB board were not aligned exactly squarely, the difference between these two distances would be exactly the same, since they both describe the radius of a circle with it's centre point at the origin

 So now we've worked out the scale (the constant to multiply our NC drill hole positions by to convert distances in mm/inches into number of stepper motor steps) we now need to work out the rotation of the PCB on the cutting bed

Even if the PCB on the cutting bed were badly skewed, the ratio (scaling) between R1 and R2 would be the same. We know the location of the bottom-right-most hole from the origin according to our NC drill file, and we know the distance of the same hole on the actual PCB in terms of number of steps travelled in both the x and y axis. What we need to do is calculate by how much the PCB has been rotated.

One way to do this is to calculate the angle (from the origin) of the diagonal in the NC drill file (the larger of the three angles above) then calculate the angle from the origin of the current position of the drilling head.
Since we know the position of the cutting head from the origin in terms of steps (we count the number of steps moved in both the x- and y- axes) we can calculate this angle (the green diagonal) quite easily.

Using simple trigonometry:



If we rotate the bottom triangle 90 degrees clockwise, we can see that we've described a right angled triangle, where the adjacent side is the number of steps travelled in the y axis, the opposite side is the number of steps travelled in the x-axis, so tanA = stepsY / stepsX

From here we can calculate the angle of the position of the drilling head from the origin.
Using the same principles, and with the values from the NC drill files, we can calculate the angle between the bottom-right-most hole and the origin (top-right-most hole). The opposite side of this triangle is the difference between the x co-ordinates of the two holes and the adjacent side is the difference between the y co-ordinates of the two holes, so tanA = (y1-y2) / (x1-x2)

Knowing these two angles, we can subtract one from the other to calculate by how much the PCB has been rotated on the cutting bed. Now we know the scaling AND rotation, we can simply apply these to every point in the NC drill file, to get the number of steps needed to move in both the x- and y- directions to reach in point on the actual PCB on the cutting bed.

Apply rotation to a co-ordinate point can be acheived by using a rotation matrix:



What this scary looking equation boils down to is - the coordinates (x',y') of the point (x,y) after rotation are:
x' = (x * cosA) - (y * sinA)
y' = (x * sinA) + (y * cosA)

Given that we know x and y (from the NC drill file) and we've calculated the rotation of the PCB on the cutting bed, we can work out:

xSteps = ( (x * cosA) - (y * sinA) ) * scaling
ySteps = ( (x * sinA) + (y * cosA) ) * scaling

where x and y are the co-ordinates given in the NC drill file.
And all without knowing how many teeth are on the CNC belt, how many steps the motors turn per full revolution or any of that other junk, nor without any headaches lining up the PCB to get it absolutely square and accurate on the cutting bed.

In theory, this provides a really nice and easy to use - if not entirely easy to understand for everyone - way of drilling every hole on the PCB, from an NC drill file, given the user has manually located two holes on the board.

Software design requirements for CNC drill machine

Robot Steve's late entry into the BuildBrighton CNC Drilling Machine competition has in some ways spurred us on and in others caused things to grind to a halt. In some ways, seeing such a simple, usable design has us wondering whether it's worth continuing with our little laser-cut caddy. The main difference between our approach and Matt's CNC monster was simply scale and cost:

Matt came up with a solid (though possibly over-engineered) design using linear bearings, rods and bolts by the bucketload, expensive steppers and belts - basically blowing the budget to create the best CNC type machine he could manage.
We stuck to the cheap-as-possible, easy to replicate route, but possibly at the cost of accuracy (we still don't know if our design will actually create a working, functional CNC machine!)

Steve's design fits nicely in the middle.
With 3d printed parts, built from a 3d CAD-based design, he can see his prototype working (virtually) before cutting or casting a single piece of plastic! Yet with minimum part count and easy push-fit construction, there's no need to worry about bolting plastics edge-to-edge and trying to get everything square. It's a great design.

So is it worth continuing with a slightly shonky design, knowing that eventually we'll probably adopt another in the near future? We'll leave that question, and spend our time constructively on the one aspect that no-one seems to have addressed just yet: software.

The budget allows for the complete build - including driver board/electronics and controlling software.
The easiest approach would be to get a MACH3 compatible driver board, hook up the steppers and run everything through some milling software like MACH3. But this is an expensive way of going about things, so we reckon custom software is the way to go.

Also, we're not drilling or milling blank material. Our PCBs with either already be etched, or have tracks and traces already marked on them, ready for etching. So before we start any drilling, we have to make sure our boards are perfectly lined up to begin with.

In something like mach3 we could do this by moving the drill head to a known position and placing the board underneath it, then moving the head to a second (known) position and rotating the board until this second point fits under the head. With the board in place, we could lock it down and start the cnc running.
MACH3 also has a myriad of settings, belt-tooth size, leadscrew adjustment values - all things which make it quite complicated and daunting to the untrained user. For our software we want:


  • Minimum settings screens - we don't care how big your stepper motor is, the tooth pitch, degrees per step and so on. The software should work with a wide range of machines without any complicated maths/physics calculations!


  • Auto-alignment - placing a PCB exactly squarely on the cutting bed is going to be difficult enough. Cutting the sides square is hard - knowing that you've placed one edge exactly squarely can be hit-and-miss, and if your edges aren't exactly true and straight, getting the whole thing to line up is almost impossible!


  • Auto-scaling for different measurement units - NC drill files are commonly described in imperial (inches) but there is software that uses (and an NC drill command for using) metric (millimetres). The software should be able to handle mm and inches without the need to re-calculate the drill position data in the NC drill file.

We're not worried about making everything open source, complying with GNU licences and all that - we're just looking to create some software that just works (in Windows at least) using whichever tools do the job. Of course, details of how the software is created will be explained, should anyone wish to re-create their own, but we're not ruling out any specific technologies just because it's not "open source" or GNU-a-like or anything like that!

Sunday, 26 August 2012

Late entry to the BuildBrighton CNC drill machine challenge

It's a bit late - though not as late as our actual machines are for being ready (they should have been drilling PCBs in time for last August's BuildBrighton Guitar Stompbox Workshop) - but we've had an exciting last-minute entry from Robot Steve.


Steve's taken the simplicity of our design but coupled it with the super-low cost option (and ease of construction) of a 3D printed solution. We think it looks amazing.


Using a servo for the drill plunge, this design keeps things about as simple as they possibly can be. The rails are structural as well as functional (carrying the carriage for the x/z axes) and the tiny steppers are mounted directly onto the moving parts. Rather than mess about with linear bearings, Steve has gone for the simpler (and cheaper) design used in many inkjet printers - greased rails and precision cut nylon blocks sliding along them!


We think the best thing about this design is the relatively low part count. Once you take away the cutting bed (a piece of cheap acrylic or some mdf) and the rails, you're left with a handful of cheaply produced 3d printed parts.


Steve sent over some early prototype photos. It actually looks better in real life!


Friday, 24 August 2012

CNC linear rails testing

Down at BuildBrighton tonight, fellow PIC-programmers were in short supply, so with reluctance we had to crack open an Arduino Duemilanove and learn some crazy Arduino coding. It turns out it's not as difficult as it looks (but it does still make you feel a bit dirty).

To get things working, we just wanted to be able to turn a stepper motor clockwise and anti-clockwise. Here's the code we came up with:



int state=0;
int dir=0;

void setup(){
     pinMode(1, INPUT_PULLUP);
     pinMode(2, INPUT_PULLUP);
     pinMode(3, OUTPUT);
     pinMode(4, OUTPUT);
     pinMode(5, OUTPUT);
     pinMode(6, OUTPUT);

}

void loop(){
     //read the pushbutton value into a variable
     int inputVal1 = digitalRead(1);
     int inputVal2 = digitalRead(2);
     
     // Keep in mind the pullup means the pushbutton's
     // logic is inverted. It goes HIGH when it's open,
     // and LOW when it's pressed.
     if (inputVal1 == LOW) {
          // turn the motor clockwise
          dir=1;
     }else if(inputVal2 == LOW) {
          // turn the motor anticlockwise
          dir=-1;
     }else{
      // stop turning the motor
      dir=0;
     }
     
     if(dir!=0){
               // move the motor
               state+=dir;
               if(state<0){state=7;}
               if(state>7){state=0;}
               
               switch(state){
                     case 0:
                     // energise coil A
                     digitalWrite(3, HIGH);
                     digitalWrite(4, LOW);
                     digitalWrite(5, LOW);
                     digitalWrite(6, LOW);
                    
                     break;
                    
                     case 1:
                     // energise coils A+B
                     digitalWrite(3, HIGH);
                     digitalWrite(4, HIGH);
                     digitalWrite(5, LOW);
                     digitalWrite(6, LOW);
                     break;
                    
                     case 2:
                     // energise coil B
                     digitalWrite(3, LOW);
                     digitalWrite(4, HIGH);
                     digitalWrite(5, LOW);
                     digitalWrite(6, LOW);
                     break;
                    
                     case 3:
                     // energise coils B+C
                     digitalWrite(3, LOW);
                     digitalWrite(4, HIGH);
                     digitalWrite(5, HIGH);
                     digitalWrite(6, LOW);
                     break;
                    
                     case 4:
                     // energise coil C
                     digitalWrite(3, LOW);
                     digitalWrite(4, LOW);
                     digitalWrite(5, HIGH);
                     digitalWrite(6, LOW);
                     break;
                    
                     case 5:
                     // energise coils C+D
                     digitalWrite(3, LOW);
                     digitalWrite(4, LOW);
                     digitalWrite(5, HIGH);
                     digitalWrite(6, HIGH);
                     break;
                    
                     case 6:
                     // energise coil D
                     digitalWrite(3, LOW);
                     digitalWrite(4, LOW);
                     digitalWrite(5, LOW);
                     digitalWrite(6, HIGH);
                     break;
                                             
                     case 7:
                     // energise coils D+A
                     digitalWrite(3, HIGH);
                     digitalWrite(4, LOW);
                     digitalWrite(5, LOW);
                     digitalWrite(6, HIGH);
                     break;
                    
               }
               
               delay(1);
     }
     
}




It's a simple state machine - when the motor is turning clockwise, we energise the coils in sequence 1...2...3... etc, when running anti-clockwise we go 7...6...5.... etc

Doing this allows us to quickly and easily make the motor run by pulling an input pin low (pull-up resistors mean the inputs are always high with no input on them).


Here's a video showing the motor in action:

Wednesday, 22 August 2012

Miniature CNC drilling machine x-axis carriage

We've had a bit of mixed success at Nerd Towers tonight.
Firstly, we wanted to get our x-axis working on the miniature drilling CNC machine. The y-axis (bed) is easy enough - it's just a plastic bed set on top of an Ikea drawer runner. The x-axis is altogether more difficult, as it's a gantry-based axis (to keep the size/footprint down).

In the spirit of making everything as cheaply and as repeatable as possible, we're using the same rack-and-pinion approach for our x-axis as we have done on the y.
Simply put, a long toothed edge will run along the top of the gantry, and the stepper motor mounted on top of the moving carriage will pull the carriage along by rotating a cog/pulley along the tooth-edged strip.

We've decided on this approach as once the parts are designed and proven to work, anyone with access to a laser cutter should be able to make the same thing from our drawings.
The only thing is, we've drawn most of the CNC by eye - so have no idea how far away from the rails or toothed edge our carriage is going to be. So the first thought was to make an adjustable carriage:


At the bottom of the picture you can see the side section of our carriage. By adjusting the bolts. the stepper motor (mounted on the top of the carriage section) could be moved closer to and further away from the toothed edge running along the top.
After bolting all this together, we found that not one single piece of this carriage had been designed properly so we started the whole thing again, this time with a slightly different approach - "guesstioneering"

It's a term coined one night at BuildBrighton and fits this approach perfectly.
Basically we make something based on a best guess, then whittle things down until they fit.....


This second carriage (in blue) was designed entirely by eye and with no reference to our frame! (if the frame doesn't fit, we can always tweak that, and the carriage together, until they line up and mesh together nicely!)
In this instance, the small cog on top of the stepper motor is neither high enough, nor close enough (laterally) to the toothed edge running along the top.
Instead of messing about measuring and re-measuring and cutting and re-cutting, we just decided to make our toothed edge have a bit more play in it. The idea being that we line it up with the carriage in place and just fix it down!

As we were cutting a new toothed section, we decided to go for a double-sided piece, with the cog on the stepper motor sitting between two rails. Hopefully, this will stop the motor from pushing away from the toothed edge and skipping steps....


The only thing now, of course, is that we need to make our gantry stands about 3mm higher and a little wider on one side (so they're asymmetrical) so that this new piece doesn't look like it's been cobbled together and just shoved on as an afterthought. (it has, but there's no need to advertise the fact!)


This new carriage moves along the rails quite nicely.
There's not much play and hopefully this double-rail approach will eliminate this altogether. Here's a quick photo to show the actual size of the gantry. It's really quite small -


So there we have it. A nice sliding gantry with a stepper motor mounted onto it. It's not quite working under it's own steam just yet, but we can't help but feel that we're getting a little bit closer!
Here's how the final thing will sort-of look in place over the y-axis bed. We may even go crazy and lose the lump of scrap wood for a nice piece of red acrylic. That's the kind of colour scheme that would make Robot Steve have a fit