I am trying to control a Hitec 785 servo using arduino but am having problems. It is really jerky and I cant get the angles right.
Any ideas?
Post code, post circuit.
I will be paying attention to see how this pans out (i have the same servo lying around)
Ok here is the code. I am trying to move a servo round from a home position by 10 degrees at a time, pause, take a photo and so on. The number of photos is set by a variable called panAngle that will eventually be set by the user by a button and an LCD.
It sort of works but usually after a few turns it rotates by about 45 degrees in the wrong direction before carrying on. I have a feeling i am supposed to keep sending a pulse to the servo to get the right angle but I dont know how to do that and go off and fire the camera shutter at the same time. Any help much appreciated. In terms of the circuit I am using a simple opto-isolator for the motor and camera shutter and have referenced the ground of the power supply and arduino board.
//panorama code for HItec 785 and Canon 350
int selectButton = 8;
int panAngle;
int ledPin = 13;
int imageCount;
int shutter = 9;
int servoPin = 1; // Control pin for servo motor
int minPulse = 900; // Minimum servo position
int maxPulse = 2100; // Maximum servo position
int pulse = 0; // Amount to pulse the servo
int refreshTime = 15; // the time needed in between pulses
int servoAngle;
void setup()
{
pinMode (selectButton, INPUT);
pinMode (ledPin, OUTPUT);
pinMode (shutter, OUTPUT);
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
panAngle = 180;
}
void shoot()
{
digitalWrite(shutter, HIGH);
digitalWrite(ledPin, HIGH);
delay(2000);
digitalWrite(shutter, LOW);
digitalWrite(ledPin, LOW);
}
void homeServo()
{
pulse = minPulse;
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulse); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
delay(refreshTime);
}
void moveServo()
{
pulse = (((float)servoAngle / (float)1260) * 800) + 900; //work out pulse width - 800 figure arrived at by trial and error but I expected it to be more like 1260 becasuse motor turns 3.5 revs
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulse); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
delay(refreshTime);
}
void loop()
{
if (digitalRead(selectButton) == HIGH)
{
delay(250); //debounce button
imageCount = panAngle/10;
homeServo();
servoAngle = 0;
while (imageCount>0)
{
moveServo();
delay(500);
shoot();
servoAngle = servoAngle + 10;
imageCount--;
}
}
}
I think your problem is due to insufficient refreshing of the servo
Servos don't move instantaneously – the servo you have takes almost two seconds to move 360 degrees. So you need to continuously pulse the servo. It probably needs at least four pulse repetitions at 20ms per pulse to start up and move 10 degrees. Your code only pulses once per position. BTW, your code uses 15ms, 20ms is more common.
You could add some code in the moveServo function to provide more pulses. Perhaps pulse once for every 4 degrees of movement.
Another approach is to use the servo library from the 0012 Arduino release. This moves the servo in background using a timer interrupt so you don't have to worry about repeating the pulses. But your code would need to take into account the time it takes for the servo to move so that its in position and settled before you snap your picture.
Thanks for that - really helpful. I will try both methods.
I was guessing there might be a way to pulse the servo in the background but had no idea how it might be done. Can you point me in the direction of some tutorials on using the right servo library? I couldn't find one on the arduino site that dealt with things like if the servo has a different min and max pulse to the default.
thanks again
Have a look at the arduino servo reference pages: Servo - Arduino Reference
The attach function handles modifying the min and max pulse widths
I tried the servo library and it certainly gets the Hitec 785 moving and I like the fact that it works away in the background. However, even setting the min and max pulses to 900 and 2100 doesn't resolve the issue of the angle being wrong. As it rotates 3.5 revs according to the datasheet (1260 degrees?) I expected to have to divide all the angles by 7 but this is not the case. I am doing some trial and error testing to figure out the angles but it doesn't seem obvious yet!
Also, I worked out the jerkiness is caused by the opto-tranisitor or the way I am using it.
If Iplug the motors signal lead directly to the arduino pin it is smooth. However, I am worried it might damage the board. I am using an external power supply. Anyone got any ideas? The opto-transistor I am using is an ILQ74 from maplin.
Good to hear you are making progress.
Trial and error is probably the only way you can calibrate the servo, there is no standard for accurately calculating the angle from the pulse width.
Most motors draw more current then the arduino can safely provide. If you want advice on connecting your motor you need to provide a little more information such as much current it draws with your normal load.
Thanks for that I will calibrate the angles manuallly.
The motor's running current is 250mA, stall current is 1500mA. I have it hooked up to an external power suppply at the moment and in the long run I intend to run it off an external battery pack. I have the grounds of the PSU and arduino tied together.
If all I have connected to the pin on the arduino is the servo control wire is that a problem? If I connect the control wire via an opto transistor it gets very jerky. I am guessing the opto transistor cant switch quickly enough.
Any help on hooking up the motor properly would be appreciated!
"If all I have connected to the pin on the arduino is the servo control wire is that a problem? "
The control input for a servo is simply a TTL level digital input so no problem being driven directly from a Arduino digital output, and of course the servo grounds must also wire to the Arduino ground.
Lefty
Thanks for that. So why do you think it might be jerky? If I try the example called 'sweep' it seems to be fine . But if I try to increment the servo by 10 degrees at a time with a pause between each step it is really jerky.
I am using the servo library and just using servo.write(angle). angle is a variable that increases by 10 each time after a pause of 1 second.
is it only jerkey with the opto transistor ? You don't need one for driving a standard servo
Can't say for sure, but I have been able to drive a servo on a breadboard test basis with no sign of jitter, so it can be made to work.
I would think the most likely candidate is power or ground noise. A scope would be the best tool to try and see what is happening electrically to either the power, ground or signal lines on the servo.
If you can temporary hook up 4 fresh AA alkaline batteries in series for the servo power that you give you a quick way to eliminate your external power supply as a problem or not.
PS: I would not attempt to use opto-isolators for the servo control signal, not need and might effect the shape of the signal pulse somewhat.
I was getting quite a bit of jitter with a servo connected directly and using the servo library
I am not sure why