Basically, I'm working on a cutting gears. I have a stepper motor and a driver (with encoder to prevent lost steps) capable of micro-stepping up to 3200 steps/revolution connected to a 60:1 gearbox (192,000 steps per gear revolution).
I want my stepper motor to set the position of the "Blank" (AKA: the material before the teeth are cut) so I can cut each tooth. The setup is easily capable of cutting a 20-tooth gear as 20 steps is 9,600 steps per tooth.
My question is what do I do for a 21-tooth gear (or more precisely, a 127-tooth gear, which is what I want to cut)? there is always a remainder of steps at the end -- even micro-stepping does not solve the problem as 127 is a prime number.
Given that my "drive" takes 192,000 steps per revolution, dividing that by 127 teeth gives me 1511.811023 steps per tooth. Since I cannot cut the decimal, I have 1511 steps between each tooth -- EXCEPT, I have 1619 steps between tooth# 127 and tooth #1 (1511 steps plus the 108 "remainder"). If I "over step" each tooth at 1512/tooth, I will only be 1,487 steps between tooth #127 and tooth #1; Same Problem.
I know the answer is distributing some of the "remainder steps" to different teeth on the gear rather than them stacking up AFTER the last tooth is cut. I'd like to have the Arduino adjust the "step-per-tooth" automatically regardless of how many teeth I want to cut. I CAN write the code manually to add a step here and there, but each sketch would only be for a certain number of teeth (and mind-numbingly difficult to code). I'd like "the math" to work it out regardless of the number of teeth I tell it to cut (right now, I use push-buttons and a OLED screen to input the number of teeth to be cut).
Any of you math-magicians wanna take a crack at it?
I'll look to be sure, but you should be able to exploit phase accumulation or a variation of Bresenham's line algorithm to "properly" handle dropping in the extra micro steps.
This is a good model, but i need to get "the code" to figure out which tooth it will add (or subtract) a step from -- over-stepping (using 1512 steps/tooth) is more logical for the 127-tooth gear as I'd only have to compensate on 24 of the 127 teeth. By using 1511 steps per tooth, I'd have to compensate for 108 teeth, but if the computer is doing it, I don't care if it's compensating for 1 tooth or a million -- it's just math to the machine...
I don't know how your cutting goes, but this program takes 192000 steps, passes 127 teeth, mostly by stepping 1512 steps, and "every once in a while" by algorithm 1511 steps.
Sry, it's just a regular C program. And it may not work too well with 32 bit floating point numbers. And Bresenham most old-timers would be appalled at the use of floating point anyway, but it does show phase accumulation in action.
# include <stdio.h>
# define stepsPerRvolution 192000.0
# define nTeeth 127
float stepsPerTooth;
int main()
{
printf("Hello Math-Magician World\n\n");
stepsPerTooth = stepsPerRvolution / nTeeth;
printf("%f steps per tooth\n\n", stepsPerTooth);
// now take steps, and announce step count and steps to each tooth
long stepCount = 0;
long oldStepCount = 0;
int toothNumber = 0;
float accumulator = 0.0;
do {
stepCount++;
accumulator += 1.0;
if (accumulator > stepsPerTooth) {
accumulator -= stepsPerTooth;
toothNumber++;
printf("tooth %d after %ld steps (%ld steps later)\n", toothNumber, stepCount, stepCount - oldStepCount);
oldStepCount = stepCount;
}
} while (stepCount < stepsPerRvolution);
return 0;
}
Here's the first lines of output, you can see the 1511 sprintzled in there. The algorithm may be inside-out to how you need to do this.
Hello Math-Magician World
1511.811035 steps per tooth
tooth 1 after 1512 steps (1512 steps later)
tooth 2 after 3024 steps (1512 steps later)
tooth 3 after 4536 steps (1512 steps later)
tooth 4 after 6048 steps (1512 steps later)
tooth 5 after 7560 steps (1512 steps later)
tooth 6 after 9071 steps (1511 steps later)
tooth 7 after 10583 steps (1512 steps later)
tooth 8 after 12095 steps (1512 steps later)
tooth 9 after 13607 steps (1512 steps later)
tooth 10 after 15119 steps (1512 steps later)
tooth 11 after 16630 steps (1511 steps later)
tooth 12 after 18142 steps (1512 steps later)
tooth 13 after 19654 steps (1512 steps later)
I think this directly answers the question
which tooth it will add (or subtract) a step from
as would, indeed, the list @gcjr produced - just need to track the deltas and flag the oddballs.
edit: it appears to produce the identical results on an UNO with Arduino floats.
Have you considered that you may have to make one or more 360 degree turns to get rid of the fractional turn to move to the next tooth. Just like the manual method of cutting gear teeth?
This does answer the question. After I translated it over to "Arduino-ese" and ran a few prime numbers thru it, i see that it worked perfect for 127 teeth -- it assumed I was making the first cut, then beginning the step cycle -- so it's final number is 190,489 and if you add 1511, you come out to exactly 192,000. So if it cut there, it would be at the EXACT spot of the first cut.
Thanks for the "magic!" Below is my conversion to arduino code -- feel free to clean it up.
# define stepsPerRvolution 192000.0
# define nTeeth 127
float stepsPerTooth;
void setup() {
Serial.begin(9600);
Serial.println("Hello Math-Magician World\n\n");
stepsPerTooth = stepsPerRvolution / nTeeth;
Serial.print("steps per tooth ");
Serial.println(stepsPerTooth);
}
void loop(){
long stepCount = 0;
long oldStepCount = 0;
int toothNumber = 0;
float accumulator = 0.0;
while (toothNumber <=200){ //stops looping of list
while (stepCount < stepsPerRvolution){
stepCount++;
accumulator += 1.0;
if (accumulator > stepsPerTooth) {
accumulator -= stepsPerTooth;
toothNumber++;
Serial.print("tooth: ");
Serial.print(toothNumber);
Serial.print(" after steps: ");
Serial.print(stepCount);
Serial.print(" Steps Later: ");
long j = (stepCount-oldStepCount);
Serial.println(j);
oldStepCount = stepCount;
}
}
}
}
for any number I put in for the variable nTeeth, if it is LESS THAN 100, it positions "nTeeth" number of times. For any number OVER 100, it positions "nTeeth-1."
Also,
if I put in a "nTooth" that produces a whole number when dividing the 192,000 steps, it adds ONE step to the first position, then the even number of steps thereafter... say if we run a 120-tooth, it should make the first position 1600, but it makes it 1601, then #2 is 3201, #3 is 4801, #4 is 6401, etc...
once again, this won't matter in the outcome, but...
This looks like a manifestation of the inherent accuracy of floating points math.
TBH I "fixed" it, but do not know at what cost.
// if (accumulator > stepsPerTooth) {
if (accumulator - stepsPerTooth > -0.00001) {
Just gives a little fuzz so when the calculation is theoretically exactly equal, but the floating point is just close, it goes ahead with the phase correction.
Note I do not use the absolute value, typically used in fuzzy floating point comparison, as we do want a positive excess of any magnitude to be removed.
This lets in "close enough". It would mean that another set of parameters would leave out a correction.
But does it matter? It just means the extra step, or the skipping of a step, is delayed (or advanced) one tooth. accumulator may technically be negative when we would find by hand that it was 0.00000000000.
The algorithm could be re-worked using mixed point integer math, as I have suggested this was the way in the 20th century to get along without floating point.
The equations in other posts may well work just fine. Since they were not offered in the context of code that runs I did not experiment. And not knowing quite how you would employ any solution, I just wanted to see if phase accumulation / Bresenham would solve it in a more mechanical dare I say step-by-step fashion.
The '+ teeth/2' is not needed here. The only difference is that the rounding difference is accumulated in a different position of the gear wheel. In the case of 127 teeth, most gears are 1512 steps apart. A few are 1511 apart. It does not matter which gears are only 1511 apart, as long as they are evenly distributed over the gear wheel.