An Electronic Lead Screw controller using a Teensy 4.1

My processor has double precision floating point, but Bresenham is computed with fixed point math. The error is fixed by the integer values chosen for N and D, and the true required ratio. The error doesn't change at runtime, which is important.
 
For further clarification on thread pitch error, I calculated total thread pitch error between 10 perfect threads, and 10 approximated threads. For my worst case, at 4 TPI, I have 0.0002" error after 10 threads, or 2.5 inches. Won't be a problem.

At the opposite end, at 100 TPI, the thread cut by the approximated ratio is 5.33e-5" shorter than made by ten perfect 100 TPI threads. 10 perfect threads would be 10/100" (0.1000") long, whereas 10 approximated threads would be 0.09995" long. Consider a 1" long thread (100 threads). Then the thread cut by my lathe would be 0.9995" long. Not sure if this would cause a binding problem. I think this should be ok. Jeepers, can't even imagine single pointing 100 pitch thread.
 
I've mostly been following, but why are you limited to selecting a thread with some (seemingly significant) error %? Is this a function of the discretization of the encoder/motor pulses? Or a concern to stay away from floating point math?
You struck a nerve, but in a good way. Made me think.

My first pass at this showed the error just as a drift. Today, decided to add in the effect of the Bresenham algorithm with its discrete math and stepper control. What I see for the 100 TPI case is an overall drift due to the pitch error, and quantization due to the discrete nature of the algorithm. I plotted the pitch error in % between the ideal position and that given by the discrete Bresenham, vs. the number of thread pitches. Due to laziness, I only plotted out to 24 pitches. At 24 threads, there is a cumulative error of 1.3% of the thread pitch, or 0.013 x 0.01 = 0.00013". Yes, that is 1.3 tenths. So for 100 threads, it would be 0.00013 x 100/24 = 0.00054 or 5.4 tenths. That would mean the thread pitch for the 100th pitch would be 0.01000 - 0.00054 = 0.00946" instead of 0.01000".
Bresenham100TPIError.pngBresenham100TPIErrorQuantizationDetail.png
I suspect the error won't be a practical issue, but have to agree it doesn't look pretty! Would be nice if the error was 0 and a flat line.

The advantage of the Bresenham algorithm is it is extremely simple to implement and executes very quickly. My version will execute at spindle RPM's over 6000, which is 3 times faster than my chuck is rated for. The disadvantage is the sawtooth error, and the pitch error. The overall pitch error can be controlled by how many decimal points we choose in the truncated fraction that is needed. Not sure how to control the sawtooth amplitude, but I haven't thought much about that yet.

For the example above I used 4 points after the decimal and have -0.53% error at 10 pitches, using N=469, D=10000. If I use 5 decimal places after the decimal, (N=293, D=6250) I can reduce the error to -0.11 %. However the peak quantization error of 0.5% stays pretty much the same.

In the case of N=3, D = 64, the ratio is exact compared to what is required. Then all we have is quantization error, of 0.5% of thread pitch. There is no cumulative error.
BresenhamErrorExactNoverD.pngBresenhamErrorExactNoverDdetail.png
So thanks for forcing me to think about this. Will do a more exhaustive search for the ratios to reduce my error.
 
Interesting analysis. I had been thinking about it in terms of time error (clock jitter) caused by using the encoder as the “clock” for stepping but your position error is much more useful. I was thinking of using timing interpolation between the encoder pulses. Use a 2 point running exponential average across recent encoder pulse intervals. If a step is needed before the predicted next encoder pulse, schedule the next step based on the predicted time. Effectively you can increase D, at the cost of some loss of accuracy due to the difference between the prediction and actual time for the next encoder pulse. That gets rather messy but maybe allows a few other fun things.
 
Last edited:
It does appear the teensy 4.0/4.1 processor has hardware support for input timing capture, (GPT_CAPTURE) which would facilitate accurately noting the time of an encoder pulse.
 
It does appear the teensy 4.0/4.1 processor has hardware support for input timing capture, (GPT_CAPTURE) which would facilitate accurately noting the time of an encoder pulse.
I had the HW encoder running, but I found it difficult to manage, ie. know where to modify the code to get what I wanted. I ended up using a SW encoder library instead. Honestly, see no difference in performance. The SW version has nice callbacks to put in your own code. I merely embedded Bresenham into the callback. That in turn emits a single (one shot) stepper pulse if needed. The SW encoder runs up to 6000 RPM without missing a beat, with a 4096 count/rev input. Didn't test it higher, but I'm not threading at those speeds!
 
After my analysis shown above, I went back and re-did my tables. Must of had an error in my original code. Instead of relying on some weird (not documented in a way that I understood) function, I went back to the original math, and reduced the fractions myself. At least for the imperial threads, I can get them all reduced with no error. All that remains is the quantization error. I could reduce the quantization error by decreasing the step size, ie. having more microsteps. This seems to be a bit of a fools game, since the torque collapses rapidly with increasing microsteps. Also, changing microsteps dynamically isn't easy.

So, for now, I need to accept that I could have 0.0005" peak error in my 100 TPI threads. The error is cyclic, with the error being corrected to zero roughly every 1.8 degrees of spindle rotation. Doesn't sound all that bad to me. Will be fun to cut such a thread and check it with a nut.

At 40 TPI, the peak error (relative to the actual pitch) is 45.5 micro inches with corrections every 0.72 degrees.

For many of these threads, there is a mean pitch error though, since the quantization error is not centered around zero. So for the purpose of discussion, let's take the 100 TPI case. There is a mean pitch error of 0.25%. Therefore the new pitch is 1/100*(1+ 0.25*0.01) = 0.01000025". How many threads can we cut before one exceeds 1% error of the base 1/100 pitch?
Code:
N * (newpitch - basepitch) = 0.01 * basepitch
Solving for N, we have:

N = (0.01 * basepitch)/(newpitch - basepitch)
N = (0.01 * 1/100)/(0.01000025 - 0.01)
N = 400

So one is safe to cut 400 threads at 100 TPI before exceeding 1.01 x 0.01. That's 4 inches of 100 TPI thread. For most people, that is good enough. If not, well, design a better way!
 
Last edited:
So, for now, I need to accept that I could have 0.0005" peak error in my 100 TPI threads.
For comparison I googled tolerances on Class 3 thread fits (tight tolerance). Quick check but the finest thread I found tabulated was for a 0-80 screw (80 TPI), with a tolerance of .060 - .0568 on the major diameter of the screw. Given 3.2 thou to play with, I think you could make a class 3 thread fit with the errors you are at. Diameter vs TPI, etc, so it is not a straightforward comparison but it does give some idea of what is acceptable.
 
For comparison I googled tolerances on Class 3 thread fits (tight tolerance). Quick check but the finest thread I found tabulated was for a 0-80 screw (80 TPI), with a tolerance of .060 - .0568 on the major diameter of the screw. Given 3.2 thou to play with, I think you could make a class 3 thread fit with the errors you are at. Diameter vs TPI, etc, so it is not a straightforward comparison but it does give some idea of what is acceptable.
Hope I calculated everything correctly. Tried to implement calculating all the errors and something doesn't make sense. Shouldn't post and calculate at the same time :D. I did redo the metric thread calculations and found I could get nice whole number fractions without error, with a little bit of extra effort. This means no accumulating error, but there is a cyclic quantization error for metric, the same as for imperial.

Although I haven't looked into it, I am wondering what the allowable instantaneous pitch error is. Not sure if Class 3, or 2, or 1 even specify this, they may assume perfect pitch. The cut depth won't change, since it is fixed and not under CNC control. Think that means the major diameter won't change even if cutting a non-uniform pitch. Interesting question, wonder if there is an specification for maximum allowable instantaneous pitch error.
 
I was able to reduce the peak pitch error for 100 TPI from 0.228% to 0.0976% by increasing the microsteps to 32. Not sure if the stepper can even do this and drive the lead screw. Only saving grace is the total thread depth for a 100 TPI thread is tiny at 0.00866". Might be worth a try later on, when everything gets sorted.

Found out that some rotational errors of lead screws are called lead screw drunkenness.
In DIN ISO and JIS standards, this travel deviation within one revolution of the screw is defined by the specification ν2π, whereas the ASTM standard refers to this specification as wobble error.

Phew, lots of stuff to absorb.

Any how, I have to get back to graphics screens and state machines. Eliminated the cumulative pitch error for both imperial and metric threads, so that is good. Don't know if the wobble error will get me or not!
 
Last edited:
Back
Top