I've designed an apparatus that uses stepper motors, and they are linked together so that when armature A turns, it consequently moves armature B by a ratio of 1/4. In order to keep armature B in the same position, for every 4 steps stepper A takes, I need stepper B to take 1 step. I want to "round" the amount of steps required so that A will always move an amount divisible by 4, otherwise armature B drift over time with (this thing runs for 12 hours at a time). I'm trying to find an efficient way to code this:
My formula for deriving motor A's steps from degrees is: steps = degrees / 0.45
So let's say I want to turn 93 degrees. That would be steps = 93 / 0.45 = 206.66-> I cannot simply round 206 up or down because neither 206 or 207 are evenly divisible by 4. The closest whole number to 206.667 evenly divisible by 4 is 208.
So I wrote this algorithm (it sounds much cooler than saying function :) that will find this closest whole number.
int calcSteps(float targetDegrees)
{
int gearRatio = 4;
int cwna = 0, cwnb = 0; // Closest Whole Number Alpha/Bravo
float targetSteps = (targetDegrees / 0.45);
for (int x = 1; x * gearRatio < targetSteps; x++) cwna = x;
cwnb = (cwna + 1);
int closestWholeNumber = (targetSteps - cwna * gearRatio) < (cwnb * gearRatio - targetSteps) ? cwna : cwnb;
float newAngle = closestWholeNumber * gearRatio * 0.45;
int calculatedSteps = closestWholeNumber * GEAR_RATIO;
Serial.print("CWNA = "); Serial.println(cwna);
Serial.print("CWNB = "); Serial.println(cwnb);
Serial.print("Closest Number = "); Serial.println(closestWholeNumber);
Serial.print("New angle = "); Serial.println(newAngle);
Serial.print("Steps to turn: "); Serial.println(calculatedSteps);
return calculatedSteps;
}
Example Outputs:
calc(93);
CWNA = 51
CWNB = 52
Closest Number = 52
New angle = 93.60
Steps to turn: 208
calc(87);
CWNA = 47
CWNB = 48
Closest Number = 47
New angle = 84.60
Steps to turn: 192
The good news is that this works, I just can't help but think there's a better mathematical way to do this. Any ideas?