Servo Control
Here's another one I did a while back & never got around to posting here. Further back, like years (don't remember how many - Evy was small) I got a rather nice RC car kit from my dad. It was a Tamiya "Baja Champ" - the whole deal, dissassembled, two servos, drive motor, trigger controller and such. He also got me a charger for the main power source. It was cool.
So I quickly put the thing together and discovered something interesting - and relevant to this post, I assure you. There were spare parts. Extra cogs, some plastic bits, but also a completely spare servo. I got the thing done and it ran fine, but I was still scratching my head over the spare servo. The answer came later. One of my wife's cousins and family were over for a visit and it turned out her husband had built some of these kits before. He said that the extra servo was kind of a hold over from before there was electronic speed control for the motor. The servo actually was the throttle, or whatever. But my kit came with a component that did the work. One servo for the steering and then this board in some box doing the throttle.
So I've got this extra servo gathering dust for a few years until I get my Arduino. Once I got that every extra electronic gew-gaw and gadget in my house becomes an opportunity. Before I started though, I did some research. The servos I got with the Tamiya were Futaba, specifically S3003. I found a tech sheet on Futaba's site, but wasn't entirely convinced I had the right one. There were some useful links - here and here - that were somewhat close to what I had and were enought to get me started. The best link, though, I seem to have misplaced, so I can't share that.
The servo has a three wire cable coming off of it: black for ground, red for voltage - in the case I fed it the 5v, and white for control. There were warnings here and there about not using the Arduino to directly power the server - something about it needing more amps than the Arduino can provide - but I decided to just blindly ignore this warning and forge ahead.
The pulsing of voltage to the white turned out to be the tricky part. It needs voltage for a given number of miliseconds and then off for like 20 miliseconds to drive it to a particular position. The number of times pulsed - on for a specific number of miliseconds, off for 20 milis, then rinse and repeat - also had some impact. I did not know what the minimum or maximum my servo wanted to move it's full range. I did get a few lines of code that would get it to move, but had no idea how it was working.
After a bit of trial and error I found the limits: 375 miliseconds for minimum position, 2400 miliseconds for maximum position, or 0 to 180 degrees, give or take. I also found that the distance travelled dictated how long you needed to pulse the cycle for. If you were travelling from 375 all the way to 2400 and you stopped pulsing before the servo completed the motion it would indeed stop halfway. Or three quarters or however long you actually pulsed for. So in my code I added some calculation to figure out how long the travel was and ensure a minimum number of cycles before cutting out. This minimum was whatever it absolutely needed to got the max distance cut down to whatever the travel was.
Anyway, here's the code. There's not much for comments in this version, but I'll eventually go back and put some in.
/*
* ServoTest5
*/
int servoPin = 3;
int baseChar = 48;
int maxCycles = 40;
int minPulse = 375;
int maxPulse = 2400;
int distance = maxPulse - minPulse;
int list[4] = {-1, -1, -1, -1};
int input = 0;
int pulse = minPulse;
int lastPulse = maxPulse;
void setup()
{
Serial.begin(9600);
pinMode(servoPin, OUTPUT);
Serial.println("Serial servo ranging - start");
specific();
}
void loop()
{
if (Serial.available())
{
int count = 3;
Serial.print("Input: ");
do
{
input = intFromAscii(Serial.read());
if (input > -1)
{
Serial.print(input);
list[count--] = input;
}
} while (input > -1 && count >= 0);
Serial.println();
//showList();
pulse = intFromList();
specific();
}
}
int intFromAscii(int ascii)
{
int temp = ascii - baseChar;
if (temp >= 0 && temp <= 9) return temp; else return -1; } int intFromList() { int temp = 0; int mult = 1; for (int i = 0; i <> -1)
{
temp += list[i] * mult;
mult *= 10;
}
}
clearList();
return temp;
}
void clearList()
{
for(int i = 0; i < i =" 0;">= minPulse && pulse <= maxPulse) { Serial.print("Last pulse "); Serial.println(lastPulse); Serial.print("Current pulse "); Serial.println(pulse); int travel = max(lastPulse, pulse) - min(lastPulse, pulse); Serial.print("Travel "); Serial.println(travel); Serial.print("Distance "); Serial.println(distance); float cut = (float)travel / (float)distance; Serial.print("Cut "); Serial.println(cut, DEC); unsigned int cycles = (maxCycles * cut) + 1; cycles = max(cycles, 5); Serial.print("Cycles "); Serial.println(cycles); for (int i = 0; i <= cycles; i++) { digitalWrite(servoPin, HIGH); delayMicroseconds(pulse); digitalWrite(servoPin, LOW); delay(20); } lastPulse = pulse; } else { Serial.print("Pulse given "); Serial.print(pulse); Serial.print(" is outside of range: "); Serial.print(minPulse); Serial.print("-"); Serial.println(maxPulse); } pulse = 0; }
Comments
Post a Comment