Showing posts with label g-code. Show all posts
Showing posts with label g-code. Show all posts

Thursday, 20 June 2013

SVG to g-code. Now we're getting there!

Using a different coloured dot as our origin marker works perfectly!


And the great thing is, by changing the multiplier (at the minute we're using 25.4/90 to convert an image at 90dpi into millimetres) we can output our g-code in any units that the cnc machine requires.

One thing we have noticed, however, is that there's no real control over the order of the dots - the svg file appears to write them in the order they were drawn on the screen. That's fine for a simple example like this, but could be a bit of a nightmare when importing files from other applications.

The generated g-code (obviously) follows the drawing order of the svg file, which may not necessarily by the most efficient path between points.

By following the points in our svg file exactly, we would end up with a drilling pattern something like this:
So the last little bit of our project to do now, is to add in some path optimisations. We've already done something similar in the past, with our miniature CNC drill, so it shouldn't be a major problem.
Because our CNC is pretty accurate this time (the miniature one had loads of backlash because of the super-cheap stepper motors) we should be able to implement a "move to nearest point" routine to reduce the amount of time the drill head spends travelling from one point to the next (and hopefully reduce the overall drilling time for each entire board).

Inkscape makes complex SVG files

Now we've got a working SVG-to-GCode converter working, it's time to think about calibrating the CNC machine. So we drew a simple grid of dots, spaced 0.1" apart (standard breadboard distance) and saved the SVG before running through our gcode generator. And something peculiar happened; it didn't quite work.
All the x axis values for every dot were the same.

When we looked at the svg file, every single dot had the same x-axis value, irrespective of where it appeared on the screen:


Our entire group of dots still had a "master translation" applied to the entire group, but this didn't explain why all the x-axis values were the same for every dot.


Further investigation revealed that every dot had it's own individual transformation matrix applied to it:


Now it's worth noting that our PCB svg (generated by loading a PDF, generated by CutePDF from inside ExpressPCB) is noticeably different to this latest file: this file we created by drawing a circle then copy-and-pasting the dot(s) repeatedly until we had a grid of 6x6 drill holes. In the PDF, every shape was a "path" - even the circles that made up our drill holes. In this file, we had "circle objects" rather than paths and it was each of these objects that had an inline transformation.

Now what we really should be doing is updating our g-code generator to parse all different types of svg files. But then we're in danger of spending more time building our tools instead of getting something working to enable us to drill some copper boards and - ultimately - make batches of PCBs. So for now, we just use the Inkscape menu - Path -> Object to path - and turn all our circles into paths. Saving the file as a plain svg seems to fix the problem: every drill hole is now a path and there are no nasty inline transformations to deal with

 <g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(0,-962.35975)">
    <path inkscape:connector-curvature="0" style="fill:#000000;stroke:none" d="m 3.5433072,1050.5905 c 0,0.9785 -0.793196,1.7717 -1.7716532,1.7717 -0.97845717,0 -1.7716535523622,-0.7932 -1.7716535523622,-1.7717 0,-0.9784 0.7931963823622,-1.7716 1.7716535523622,-1.7716 0.9784572,0 1.7716532,0.7932 1.7716532,1.7716 z" id="path2985" />
    <path inkscape:connector-curvature="0" style="fill:#ff0000;stroke:none" d="m 12.543307,1050.5905 c 0,0.9785 -0.793196,1.7717 -1.771653,1.7717 C 9.7931964,1052.3622 9,1051.569 9,1050.5905 c 0,-0.9784 0.7931964,-1.7716 1.771654,-1.7716 0.978457,0 1.771653,0.7932 1.771653,1.7716 z" id="path2987" />
 
</g>

But there's still one last thing.
As you can see from the svg snippet above, the holes are now correctly spaced (the difference between x values is 12.54-3.54 = 9 pixels and at 90dpi, 9 pixels = 9*25.4/90 = 2.54mm or 0.1") but their absolute location is still incorrect (3.54 pixels = 3.54*24.5/90 = 1mm). Our first drill hole should be a 0,0 but the x-axis value is 1mm.

Even applying the "master translation" doesn't fix this, since the x-part of the command translate(0,-962.35975) is zero.

So what's going on?
If we read the path co-ordinates that follow the m command in the svg attribute, it looks like the path is being drawn from the right-most side of the path, to the left (the x-part of each of the first few curve points is negative, suggesting the path is being drawn from right-to-left).

Now we've no idea if this is going to be consistent for all shapes drawn in future, or what happens if the user were to copy and paste, then rotate or flip their image before exporting as svg. So the easiest solution we can think of is to place a dot at 0,0 and give it it's own unique special colouring (we're thinking black for now).

After parsing the entire document, we should have a set of co-ordinates for our black dot (the origin) which we can then add/subtract from every other dot on the board, to get the correct, absolute position for all our drills holes.

Watch this space........

Parsing Inkscape SVG files to create g-code

Here's a screenshot of our first test - and it's all looking rather encouraging!


I actually got the generate g-code (after parsing the SVG file and applying modifiers) to match the positioning of the objects in Inkscape - in the example above, you can see that the x co-ordinate is the same in both the VB app and in Inkscape.

The y value is different but only because Inkscape insists on putting the origin (0,0) at the bottom left hand corner of the document, whereas most of us (and most other apps) expect it to be top-left. In fact, when I consider that my svg image is 99.5mm high, the numbers do stack up.

In my g-code I had the y axis value as 10.41 whereas Inkscape insisted it was 89.11.
However, subtract my 10.41 from 99.5 and you get....erm.... 89.01
So it looks like my outline is actually 99.52mm (so I was 0.02mm out!). I think this kind of tolerance is acceptable for a machine that has a 0.1mm accuracy.

All that remains now is to work out how many turns on our CNC we need to make to travel 1mm and get all that coded into the Mach3 interface. With a bit of luck we'll be able to drill some test boards (and hopefully actually print some PCBs) very, very soon!

Wednesday, 19 June 2013

Making NC drill files and GCode from a PDF (via Inkscape)

Mach3 is a serious bit of kit. There are options and settings for everything!
Which a lot of people would be really pleased with. Just like Eagle is the de-rigueur PCB layout software, because it's so configurable. But here at Nerd Towers, we're not really fans of spending ages getting things set up and working (hence the love of Windows over Linux, and ExpressPCB over Eagle) so - bizarrely - we'll often spend ages making our own tools, in order to "just get the job done". It's not always quicker, and it's most often less simple. But it does give us a certain degree of control over what we're doing.

Which is why we're struggling so much with Mach3 - and in particular importing dxf files.
Mach3 is simple when it comes to "load some g-code and run it". We can even make our own simple g-code files, load them and run them in Mach3. But getting the drill data out of our ExpressPCB files is pretty tricky.

We've already successfully created a .dxf file from ExpressPCB, via Inkscrape, but now, getting the drilling data into Mach3 is proving difficult: so we're writing our own Inkscape-to-gcode app to get us up and running. After all, the pdf loads easily enough into Inkscape, and saving as .svg gives us a whole load of co-ordinates in a nice, easy to read/parse, xml-formatted file.

Here's our PCB layout, loaded from a PDF (which in turn was generated by printing via CutePDF from ExpressPCB). We've picked out the drill holes and coloured them red, the board outline and coloured it gree and ditched everything else. We used a technique discussed earlier to do this.


Saving as plain svg and opening the file in Notepad/Editplus (or any other text editor) gives us our xml which we can parse away at leisure.

One thing to note is that all the co-ordinates listed in the file are in pixels (not mm) as per the .svg specification. It's worth noting that Inkscrape, by default, exports at 90dpi. Knowing this, we can multiply all co-ordinates in the file by 25.4/90 to get the distances in millimetres. (there are 25.4 millimetres in an inch, and the co-ords are saved in a file, where 90 pixels = 1 inch, so 90 pixels = 25.4 millimetres)

Also, Inkscape makes use of translations quite a lot. In this case, the image was drawn in a particular area of the screen. After we got rid of all the extra data that wasn't needed, the result was placed in the bottom left hand corner of the document. It seems that rather than update the points positions, Inkscape simply applies a master translate command over the whole of the image data.
This needs to be kept in mind when parsing the plotting points in the xml file


Where are point is listed as, for example, (390.044, 735.075) it's actually placed at (390.44, 39.06) since the entire image has a translation of [0,-698.16927] applied to it and 735.07543-698.16927=36.90616)

The reason for choosing green and red in our image file is to make identifying the parts easier in the xml. Anything that has a fill colour #ff0000 is red - and therefore a drill point. Likewise, anything with a fill colour of #00ff00 is green - and makes up the board outline.

All of our holes are described as a series of points describing a circle. We're only really interested in the initial (start) point of each hole, not all the junk that comes after it:


With all this in mind, it should be a simple job to knock up some VB to parse an SVG file and create the necessary move-and-peck-and-drill g-code (move to point, z-down, z-up, move to point, z-down, z-up etc). Updates coming soon....

Sunday, 19 June 2011

Calibrating the XAML to Drill application

We've added a calibration PDF to the xaml2drill files posted earlier. We used this to work out what our "scaling" value should be, when converting xaml into g-code.

It turns out it's pretty simple (and obvious) but here's what we did anyway:
In ExpressPCB we placed a number of pads in a small square



Print top copper layer to a PDF and open in Inkscape, then save as .xaml
Load the .xaml into our VB app and set the scaling to one
(so we can see the exact output from the .xaml before it is modified)

The resulting g-code:


G0 Z0
G0 X0 Y0
G0 Z2
G0 Z0
G0 X0 Y60
G0 Z2
G0 Z0
G0 X0 Y120
G0 Z2
G0 Z0
G0 X0 Y180
G0 Z2
G0 Z0
G0 X180 Y180
G0 Z2
G0 Z0
G0 X120 Y120
G0 Z2
G0 Z0
G0 X60 Y60
G0 Z2
G0 Z0
G0 X60 Y0
G0 Z2
G0 Z0


Just by looking at these values, we can see that in our conversion, a value of 60 is the same as 2.54mm. Or, more simply, 0.1". This means that to convert our .xaml into g-code that uses inches as units, we need to set the scaling to 600 (60 divided by 600 = 0.1)

This suddenly seems quite obvious. If our images are drawn at 600dpi, it makes sense that we should set the scaling to 600 to get from screen pixels to inches!

From this simple test we concluded:
To convert the .xaml to g-code in inches, scaling = 600
Since 1 inch = 2.54mm, to convert inches to mm we should multiply by 2.54
So to convert .xaml to g-code in mm, scaling = (600/2.54) = 236.2204724409449

How accurate you want to be when scaling is a matter of how accurate your CNC machine cuts. As far as we're concerned, deviation of up to 0.3mm per hole is still quite tolerable, so we use scaling 236.22 for millimetres and 600 if we want the g-code in inches.

Creating drill files from ExpressPCB

Here's a simple VB app that will parse an xaml file generated from an ExpressPCB PDF and plot the points for drilling in a separate file, and a g-code.
That's sound like more than it is, so let's look at what's involved:

Firstly, create your schematic and PCB layout in ExpressPCB. When placing pads, use pads with 2.03mm size and 0.89mm hole:



Print the top copper layer to a PDF file using CutePDF



Open the PDF file in Inkscape and save as .xaml
The .xaml file should open with later versions of Internet Explorer (amongst others) so you can check the conversion worked properly. Open the file in Notepad to see all the complex XML shape descriptions.



Now start up the VB app and provide it with the path to the .xaml file



There are a few parameters to mess about with here. The main one is the code that describes a circle. If you've used 2.03mm pads with 0.89mm holes, this should be c -7 0 -12 -5 -12 -11 0 -7 5 -12 12 -12 6 0 11 5 11 12 0 6 -5 11 -11 11. You should see this set of commands repeated throughout the .xaml file, each time preceeded by [mX Y] type commands. If you've used different pad sizes, look for something similar - a repeating set of draw commands at different positions, with a fill colour of #FFFFFFFF (the [mX Y] commands are movement commands, the fill colour is white: basically we're looking for the repeating white circles that make up the centre of all the pads).

At the minute, we're not sure what units the .xaml file uses compared to our CNC machine - it will take a bit of messing about to get this right, so there's a scale multiplier parameter. As the app finds all the drill holes, it applies this multiplier, to convert from screen units/co-ordinates to whatever units the CNC machine uses. The final parameters to set at the Z-axis movement axis. The app will create some G-Code which can be loaded straight into the CNC controller software (we use Mach3 but may change once the demo version runs out!). Depending on whether the machine is set up to use inches, mm, or some other unit, this value may need to be changed - it defines the start (retracted) and end (plunged) position of the Dremel for drilling.

Pressing the "create files" button generates two files - one an amended .xaml file, so you can see a preview of the drill pattern generated. Load this into Internet Explorer (or some other software that lets you view .xaml) so see the final output.

The original and amended .xaml files showing drill hole positioning

The VB app also creates a CNC-ready G-Code file with the points plotted, complete with "move-to" commands and "extend/retract drill head" commands.



Load the G-Code into the CNC controlling software and let it go!

Download the VB app here

Friday, 17 June 2011

Building a drilling milling machine

With the arrival of our CNC machine, all kinds of ideas starting springing to mind. But the idea behind getting a machine like this was to help speed up the production of PCBs - to easily create kits of components for workshops, like those run by BuildBrighton, or even to produce products for an online shop or to sell on eBay.

So that's where we're starting - to get the CNC machine to drill a series of holes that match up with a PCB circuit/design.

Following Tom's excellent research into g-code files, we're pretty confident that we can get the CNC to move to specific points above a sheet of copper-clad board, and activate the z-axis (up-and-down axis) to get it to thrust a Dremmel drill into the board. The most challenging part is to create the g-code to begin with!

So far, we've resisted all attempts to learn Eagle for designing and producing PCBs. But it looked like this was on the cards, since it already includes export options for drilling and milling PCBs. The only trouble with Eagle is, well, it's just not very nice. The software we use for schematic design and PCB layout is the excellent (and free) ExpressPCB.



It's just easier and all round nicer to work with - no confusing menus, sub-menus, things hidden inside other windows and so on. It has a really neat library of existing components, and if you can't find what you're looking for, creating your own is a doddle. Because we do a lot of home-etching, you can make big fat pads and traces really easily, and the final boards produced are easy to solder and work with. Eagle, on the other hand, was just confusing and produced boards with nasty lozenge-shaped pads and thin traces that were easily broken during etching.
The problem with ExpressPCB is that although the software is free, it's provided by a fab-shop who want you to send your designs to them for manufacture. As a result, there are no export options supported.

To date, we've always printed a PCB layout either straight to the printer (where the press-n-peel is already loaded and ready to do) or - using CutePDF - to a PDF file for editing.

Inkscape is a great program for editing graphics-heavy PDF files. So naturally we loaded our PCB into Inkscape and choose the "ungroup" command to break the board up into lots of lines and circles.
Then we selected the (black) centre circles found at the centre of each pad and copied them all to the clipboard. By creating a new image and pasting the copied shapes into the top-left hand corner, suddenly we had the basis for our drill file:


From within Inkscape we saved this new image as an .xaml file


This created an XML document, filled with plot and curve commands.
The curve/shape commands are of little consequence to us, but the plotting commands are just what we're after:


<?xml version="1.0" encoding="UTF-8"?>

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Name="svg5395" Width="744" Height="1052"><Canvas.Resources/><Canvas Name="layer1"><Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path4253" Fill="#FF000000" Data="m 44.142826 61.717113 c 0 -1.05 -0.75 -1.8 -1.65 -1.8 -1.05 0 -1.8 0.75 -1.8 1.8 0 0.9 0.75 1.65 1.8 1.65 0.9 0 1.65 -0.75 1.65 -1.65"/><Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path4255" Fill="#FF000000" Data="m 44.142826 70.717113 c 0 -1.05 -0.75 -1.8 -1.65 -1.8 -1.05 0 -1.8 0.75 -1.8 1.8 0 0.9 0.75 1.65 1.8 1.65 0.9 0 1.65 -0.75 1.65 -1.65"/><Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path4257" Fill="#FF000000" Data="m 44.142826 79.717113 c 0 -1.05 -0.75 -1.8 -1.65 -1.8 -1.05 0 -1.8 0.75 -1.8 1.8 0 0.9 0.75 1.65 1.8 1.65 0.9 0 1.65 -0.75 1.65 -1.65"/><Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path4259" Fill="#FF000000" Data="m 44.142826 88.717113 c 0 -1.05 -0.75 -1.8 -1.65 -1.8 -1.05 0 -1.8 0.75 -1.8 1.8 0 0.9 0.75 1.65 1.8 1.65 0.9 0 1.65 -0.75 1.65 -1.65"/>


As you can see, every hole drawn in the .xaml file begins the Data tag with "m" followed by two digits. This is the "move" command. The digits that follow are the curve commands to draw a filled circle. We're not bothered about that - but what is of interest is the co-ordinates of the m command (i.e. where the hole is placed).

In fact, because every single hole on the board is drawn by the same filled circle shape, it should be possible to simplify this process in future. If we save the original PCB as .xaml (without first selecting all the hole points and copying them to a new image file) we should be able to pick out the drill holes, even from a complex PCB image.
As you can see from the .xaml example above, every hole has a move command, co-ordinates to place it, then exactly the same sequence of drawing commands - "c 0 -1.05 -0.75 -1.8 -1.65 -1.8 -1.05 0 -1.8 0.75 -1.8 1.8 0 0.9 0.75 1.65 1.8 1.65 0.9 0 1.65 -0.75 1.65 -1.65"

So in theory we should be able to parse the original PCB image file, even with all the traces and filled plane backgrounds and everything else, and just look for any shapes that include "c 0 -1.05 -0.75 -1.8 -1.65 -1.8 -1.05 0 -1.8 0.75 -1.8 1.8 0 0.9 0.75 1.65 1.8 1.65 0.9 0 1.65 -0.75 1.65 -1.65" in the Data tag. Any shape with this data in it we can say is a black filled circle (a 1mm hole that needs drilling) so our parser can strip out the co-ordinates from the "m" command. All other shapes can be ignored.

Results of a test app will be posted here soon.
If all goes to plan, maybe we won't have to shell out on an Eagle licence that we didn't really want in the first place.....

And now for something completely different....

As is becoming customary with this blog, just as one thing really starts getting going, another thing comes along and knocks it into a cocked hat. The same thing happened again this week. Only the thing that came along was pretty impressive and deserved some real attention.


It was a CNC Machine!

Yay! CNCs are great. They can cut shapes out of all kinds of materials. Laser cutters are great too (we have one at BuildBrighton) but they're limited to relatively thin material (acrylic, sheet mdf, thin plywood) and can't cut anything metallic. So for making enclosures, shapes, plastic objects and so on, a laser cutter is a pretty cool tool. But etching and drilling PCBs is where they fall short.

A CNC router, however, can do all the stuff of a laser AND drill PCBs. Ok, the cutting head is quite a bit fatter than a pin-point laser, so shapes aren't as intricate, but did I mention that it can drill PCBs? That's what we found so exciting about having a massive wooden crate arrive last night with said CNC machine inside it.

After it was unpacked, assembled and gingerly switched on, the big sturdy metal gantry sat there, filled with potential energy. When the control panel was switched on, the stepper motors on each axis suddenly had resistance and the rods were difficult to turn by hand (when switched off, you can easily move the gantry by turning the rods manually).
The motor control gear looked somewhat homemade, but very robust - the control board had a great big fan on it, and plenty of heatsinks all over the place! The CNC came with a genuine copy of RoutOutCNC and a few sheets of paper with some handwritten notes. We fired up the software but with no idea how to use it (and no inclination to read the instructions!) we quickly got bored with just pressing buttons and getting no response from the machine.

The control gear lives in it's own enclosure, unlike a lot of cheaper CNCs which have it under the machine, where it can clog up with swarf and cutting debris

Laser Steve from botbuilder had previous experience of CNC machines, having built one of his own, and suggested we install Mach3 and use that to control the machine. We duly got the demo version of the app and tried it out. With partial success, we managed to jog the gantry to the left, by pressing keys on the PC keyboard. With the gantry at it's limits, we had to find a way of getting it to return again! This meant poking about in the Mach3 config screens - specifically the Ports and Pins section, making sure that the stepper motors used to drive the X,Y and Z axis were connected to the appropriate pins on the parallel port (or, rather, we told the software which pins on the port each axis stepper motor was wired up to!)

Yes, the Mach3 interface is seriously horrible!

Luckily Tom from almostobsolete.net was at BuildBrighton last night and he's spent some time playing about with stepper motors too. It didn't take long for him to have the machine jogging backwards and forwards along all three axis.

Something that did cause a problem was after a few seconds of movement, the stepper motor(s) started making a "slipping" sound - they would spin the leadscrews for a short while and then make a nasty screeching sound and the motors would stop spinning. At first we put this down to the couplers (the bit of nylon connecting the stepper motor to the leadscrew) slipping, but we soon discovered that it was the motor itself that had stopped spinning.
By slowing down the ramp up and down times in Mach3, it seemed that the software was trying to control the motors too quickly - while they were ramping up, they span perfectly well, until they hit a point where they would slip and screech. By reducing the spin speed of the motors down from 120 inch/min to about 20 inch/min, this rather distracting noise was eliminated.
(this might be a bit overkill and too slow, and we've yet to discover where the speed issue lies - it might be the old PC we used as a controller can't send the data quickly enough, it might be that the driver board can't handle the data arriving any quicker than 20"/min or it might be the stepper motors themselves: we don't know enough about any of the hardware to say what the problem is just yet!)

But with the ports & pins settings adjusted and the motor max speeds reduced, the CNC finally came to life and could be controlled properly.

We tested it be loading some g-code for simple shapes - starting with a square, which we then amended (by hand using Notepad) to draw a triangle, and finally a circle. Tom even went so far as to create his own g-code to draw arcs and connect points with lines and paths!

Drawing PacMan with a marker pen instead of a router installed. We figured that if we could change the paper quickly enough between frames we could even play a game ;-)

We've got great plans for this machine and hope to be turning out machined shapes and components and PCBs in the very near future.....