Sunday, November 13, 2011

Improved Stepping Algorithm

It would be good to re-read the post on the original approach to movement to get a good understanding of what's to follow.

This is a follow-up to yesterday's post about the resonance problems I was having. I concluded that I had 2 possible solutions to the problem, change the inter-step timing or adjust the vector so the "long" axis always steps when the other(s) step. I thought I'd do this in the host software by scaling up the values so we had common denominators or power factors or fractal deconversions or something. I thought that this might result in Really Large Numbers that would pose a problem for limited resources of the microcontroller. I briefly considered some sort of mathematical simplification of the vectors but thought I might lose accuracy. It seemed like I could produce something that would be good enough but it didn't seem like it was going to be easy.

I'll try to give a better idea of the problem. Referring to my earlier post and this illustration:


If we ignore the Z axis to simplify things, consider a vector of X:3 Y:5. This is actually a rise over run of 3 over 5. The inversion of what it sounds like, the lower number steps more frequently thus moves farther. First we take the lowest value and subtract it from all axes. This takes us from 3:5 to 0:2. The X axis is at zero, so we step it and reset it to 3. Then we subtract 2 from both leaving us with 1:0. Y is 0 so we step it. It continues like this:

X Y
3 5
0 2 X
1 0 Y
0 4 X
0 1 X
2 0 Y
0 3 X
0 0 XY

This can be illustrated like this, a time line of steps left to right. Red is X, blue is Y:

The top line is the original implementation. Given constant speed, the time between each number is the same. So the time between X steps varies as it does for Y. For low speeds or ratios where the variations are frequent enough, this doesn't seem to be a problem. The vector that was failing had a ratio of greater than 1:22. At full speed this produced resonance. I can't really say why, I just seem to have an intuitive understanding of it. It seems a good solution is to adjust the timing between the events, that way both axes could have regular timing. I gave it shot, it was fairly easy to code. But it didn't work. I'm working in integers and there isn't enough resolution in the timing to make this work. That's the way it seems, I'm not yet positive it CAN'T be done this way.

I went kite flying with my father and my son this afternoon. I was pondering the problem when an elegant solution presented itself. Rather than step an axis when the counter gets to zero, if I step all axes that are less than what was the smallest value prior to the subtraction, then instead of resetting the stepped axes to the original value, I add the original value back in. This produces the second line in the picture above. The X axis is the longest axis and it steps with every loop. It appears in this example that Y also steps at regular intervals, but another cycle through will show that Y has back-to-back steps from 5 to 6.

It was very easy to make this change to the code and it works very nicely. The problem vector is now perfectly smooth at full speed.

I ran a test path with a ball-point pen in the chuck traced on paper. The run took 4 minutes. Just as it finished the last part of the trace I got a phantom limit switch trigger. The spindle motor was not running. The fan in the controller box was, so that's a possible source. It's also possible my cell phone is a considerable source of noise.

I also forgot to mention a failure from last week. I was running a long test, about 30 minutes. Near the end the spindle motor shut down. It has a built-in thermal breaker. I wasn't cutting anything so no loss. I was running at 2000 RPM. I need to look at the brushes on the motor and see if they need replacing. If they look good I'll run a test at 1500 RPM and see how long the motor runs before a thermal shutdown.

I'm going to look into rewiring my limit switches with a shielded cable as well.

No comments:

Post a Comment