Saturday, December 25, 2010

Tool Path Simulation

In my last post, I described generally what I want for the tool path software. It was important for me to find out how difficult this part was going to be since it was critical to the whole process. I work on a Mac and it's hard to find CAD/CAM/CNC software for it, particularly cheap or free software. If I couldn't put something together myself, I would not be able to achieve the main goals of the project. A few months ago I took the first stab at the host software for building tool paths. I gave an overview in my last post.

I write server-side Java for web applications by day, so naturally I want to write the host software in Java. Working with points and lines to describe the path seems easy enough, but I didn't want to get too bogged down in Pythagorean Theorem implementations and whatnot. Nor did I feel like learning how to do 2D and 3D graphics in Java. Fortunately there's a programming environment called Processing. (Notice I didn't call it a language, it's ultimately Java at the core.) This environment has a number of great libraries I was able to leverage to get 3D modeling code off the ground. The toxiclibs library in particular is really useful for working with 3D geometry. I can create a 3D line with the X/Y/Z coordinates and ask the line for the length, direction vector, etc.

I had a little bit of learning to do but the basic 3D path modeling and manipulation went together very quickly. It should be pretty easy to imagine how a 3D "turtle graphics" program would create lines in 3D space. Here's a basic rendering of a test path:


In my previous post I stated that the cone represents the spindle or cutting bit and is animated along the path. This required some real thinking that the path generation did not. I could have used some available linear interpolation code to move the cone, but decided to write the code myself using the same approach that the Arduino code would use to move the real spindle. Then my 3D preview would also serve as a simulation of the stepper driver sub system.

Ultimately the only thing the Arduino will do is send a signal to step one or more motors, wait a bit then do it again. If the cutter is moving along more than one axis, then the motors need to be stepped with a proper ratio. Step X three times, then step X and Y together, then X three times, etc. A graphical representation of such a move would look like this:


Sometimes the line is not so smooth. We might step the axes in a ratio of 3:2 for example (I'm illustrating only 2 axes for simplicity, but we'd be dealing with 3). Because I want to minimize the workload on the Arduino, I'd like to have only integer math, adding and subtracting only. I define 3 variables to hold counters for each axis, XC, YC, and ZC. I also define a loop variable L. This defines the number of steps to take total (more details later). Suppose I move in a line defined by this ratio:

XC = 3
YC = 5
ZC = 7

If I subtract one from each, eventually one or more axes counters will reach zero and I then step it/them and reset the counter to the original value. I can speed things up a bit by subtracting the smallest non-zero value from all non-zero axes. Here's an illustration:


The starting position is at the left with XC, YC, and ZC holding 3, 5, and 7. XC holds the smallest non-zero value so we subtract 3 from all counters and we get the second frame. XC has reached zero so we step the XC axis. In the third frame we restore XC to its original value. Now YC holds the smallest value so we subtract 2 from all three. This leaves YC at zero so we step it and the process continues.

Pretty crafty solution, eh? I thought so. Well it turns out there's a name for it, the Bresenham line algorithm. Developed in 1962. Well if I came up with it on my own, I think it must be kinda obvious, no disrespect to Mr. Bresenham. I did study graphics programming in college, so maybe there was some lingering impression on my brain. Anyway, I got it to work, so I'm happy. Thomas has some interesting things to say about this approach. If I have any smoothness problems with this, perhaps I will have acquired enough experience working with Arduino timers to step each axis in independent time rather than one, two, or three at once "in time" with each other. Does that make any sense?

The above stepping algorithm will be repeated as many times as it takes to move the longest axis its full distance (the variable L above). The 3D line library I'm using makes it pretty easy to get the axis lengths from a line. One thing I've thought about but haven't tested yet is if I need to deal with remainders. If I get to the end of the line and XC, YC, and XC counters have 2, 1, and 3 in the counters, should I leave those values in and add the next set of values for the next move. I may lose accuracy if I don't do this, but it may take a rather long series of moves for that to translate into any distance I can measure with my tools.

No comments:

Post a Comment