Servo motor not rotating to specified angle

I have two servo motors that were purchased from amazon https://www.amazon.com/gp/product/B071N9MCJL/ref=ppx_yo_dt_b_asin_title_o08_s01?ie=UTF8&psc=1.

I attached my servo motor to pin 9. I also powered the motor with 6 volts with an external battery and connected the grounds of the Arduino Uno and the battery.

Using the Arduino Servo library, if I simply tell the motor to go to a position, I have to physically rotate the shaft until it is within a certain range of the intended position.

When I run the servo library sweep example the motor appears to work correctly.

I tried adjusting the degree increments of the for loops in the sweep example. It appeared that the largest number that successfully worked was 21. Increments beyond 21 will cause the motor to just freeze and vibrate and sometimes it will rotate.

I also tried using a PCA9685 module and PCA9685 arduino library with the servo and got basically the same results.

Both motors behave the same.

Thank you for your time and any help you can give me!

The sweep example:

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Sweep
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

Arduino67G:
Thank you for your time and any help you can give me!

It seems as if you have posted the program that works properly.

If so it would be more useful if you post the program that causes a problem.

...R

What you describe sounds like the servo isn't getting enough power and those servos do need fairly high current for full speed runs. So exactly what is the external 6V battery? AAs, AAAs, alkaline, NiMH, something else?

The next most likely alternative is bad wiring. You aren't connecting power through a breadboard are you? Can you post a picture of your setup showing how everything is wired.

Steve

Simple servo test code you might use to verify your servos are operating as expected.

// zoomkat 7-30-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.attach(9);
}

void loop() {

  while (Serial.available()) {

    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
      delay(3);
    } 
  }

  if (readString.length() >0) {
    Serial.println(readString);
    int n = readString.toInt();
    Serial.println(n);
    myservo.writeMicroseconds(n);
    //myservo.write(n);
    readString="";
  } 
}

slipstick:
What you describe sounds like the servo isn't getting enough power and those servos do need fairly high current for full speed runs. So exactly what is the external 6V battery? AAs, AAAs, alkaline, NiMH, something else?

The next most likely alternative is bad wiring. You aren't connecting power through a breadboard are you? Can you post a picture of your setup showing how everything is wired.

Steve

For the servo power I am using a 4 AA battery pack. I checked the voltage of the battery pack and got 6.5 V. I am also using a breadboard. I attached a photo of my setup.

Robin2:
It seems as if you have posted the program that works properly.

If so it would be more useful if you post the program that causes a problem.

...R

The program I posted does work, but if I adjust the increment in the for loops to, for example, 25, the motor will freeze and vibrate and will sometimes move a little.

Here is the adjusted code which causes the motor to not work:

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Sweep
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 25) { // increment adjusted from the original 1 from the sweep example to 25
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(1000);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 25) { // increment adjusted from the original 1 from the sweep example to 25
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(1000);                       // waits 15ms for the servo to reach the position
  }
}

Arduino67G:
Here is the adjusted code which causes the motor to not work:

I tried that program on my Uno with a small servo and it worked fine.

if you are using a large servo the bigger movement might cause it to draw a bigger current that is beyond the capability of some of your connections. I presume the AA batteries are new.

...R

That's a high current servo so from my point of view you have two obvious problems. Trying to run what may be several amps through a breadboard is always a bad idea. And that's made much worse by using those terrible unreliable alligator clip leads in your main power connection.,

When you're using servos like that you're going to need to do some soldering. The battery really needs to be DIRECTLY connected to the servo leads.

But for now, just to check, if you have a small 9g servo like an SG90 try putting that in place of your 60g 17Kg.cm servo and see if it works.

Steve

slipstick:
That's a high current servo so from my point of view you have two obvious problems. Trying to run what may be several amps through a breadboard is always a bad idea. And that's made much worse by using those terrible unreliable alligator clip leads in your main power connection.,

When you're using servos like that you're going to need to do some soldering. The battery really needs to be DIRECTLY connected to the servo leads.

But for now, just to check, if you have a small 9g servo like an SG90 try putting that in place of your 60g 17Kg.cm servo and see if it works.

Steve

As mentioned previously, I also tried controlling the servo with a PCA9685 and got similar results, so I don't understand how it could be a good connection problem. This PCA9685 setup has better wiring. I attached a photo of my PCA9685 setup.

Following is a modified example program (I just changed the servo's increment) to control the servo with the PCA9685 which is similar to the Arduino Servo sweep example:

/* FILE:    HCPCA9685_Servo_Example
   DATE:    10/06/16
   VERSION: 0.1
   AUTHOR:  Andrew Davies

   Sketch created by Hobby Components Ltd (HOBBYCOMPONENTS.COM)

  10/06/16 version 0.1: Original version


  This example demonstrates how to use the HCPCA9685 library together with the PCA9685
  to control up to 16 servos. The sketch will initialise the library putting it into
  'servo mode' and then will continuously sweep one servo connected to PWM output 0
  back and forth. The example has been written particularly for the 16 Channel 12-bit
  PWM Servo Motor Driver Module (HCMODU0097) available from hobbycomponents.com

  To use the module connect it to your Arduino as follows:

  PCA9685...........Uno/Nano
  GND...............GND
  OE................N/A
  SCL...............A5
  SDA...............A4
  VCC...............5V

  External 5V Power for the servo(s) can be supplied by the V+ and GND input of the
  screw terminal block.

  PLEASE NOTE: Depending on your servo it is possible for this sketch to attempt
  drive the servo beyond its end stops. If your servo is hitting its end stops then
  you should adjust the the min and max values in this sketch.

  You may copy, alter and reuse this code in any way you like, but please leave
  reference to HobbyComponents.com in your comments if you redistribute this code.
  This software may not be used directly for the purpose of selling products that
  directly compete with Hobby Components Ltd's own range of products.

  THIS SOFTWARE IS PROVIDED "AS IS". HOBBY COMPONENTS MAKES NO WARRANTIES, WHETHER
  EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ACCURACY OR LACK OF NEGLIGENCE.
  HOBBY COMPONENTS SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR ANY DAMAGES,
  INCLUDING, BUT NOT LIMITED TO, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY
  REASON WHATSOEVER.
*/


/* Include the HCPCA9685 library */
#include "HCPCA9685.h"

/* I2C slave address for the device/module. For the HCMODU0097 the default I2C address
   is 0x40 */
#define  I2CAdd 0x40


/* Create an instance of the library */
HCPCA9685 HCPCA9685(I2CAdd);


void setup()
{
  /* Initialise the library and set it to 'servo mode' */
  HCPCA9685.Init(SERVO_MODE);

  /* Wake the device up */
  HCPCA9685.Sleep(false);
}


void loop()
{
  unsigned int Pos;

  /* Sweep the servo back and forth from its minimum to maximum position.
     If your servo is hitting its end stops then you  should adjust the
     values so that the servo can sweep though its full range without hitting
     the end stops. You can adjust the min & max positions by altering
     the trim values in the libraries HCPCA9685.h file*/
  for (Pos = 10; Pos < 450; Pos += 20) //I only adjusted the increment from the original 1 to 20
  {
    /* This function sets the servos position. It takes two parameters,
       the first is the servo to control, and the second is the servo
       position. */
    HCPCA9685.Servo(0, Pos);
    delay(10);
  }

  for (Pos = 450; Pos >= 10; Pos -= 20) //I only adjusted the increment from the original 1 to 20
  {
    HCPCA9685.Servo(0, Pos);
    delay(10);
  }
}

Also, I'm not sure if this is helpful, but I measured the current going through the motor and got 0.001 A when it wasn't working (when the servo was told to rotate 20 degrees, for example) and got 0.085 A when it was rotating (for example, when the rotation increment is 1).

Robin2:
I presume the AA batteries are new.

The AAs are fresh (6.32 V).

Thanks!

If you are measuring current with a multimeter you will not catch very short duration flows that would only show up on an oscilloscope.

Have you tried the small servo as suggested by @slipstick?

...R

Try measuring the voltage AT THE SERVO (not at the battery) while you are trying to move the servo.

BTW if you're running the PCA9865 from the same power supply and it is inadequate then it will naturally behave the same way.

Steve

I'd tried out some of your suggestions.

slipstick:
Try measuring the voltage AT THE SERVO (not at the battery) while you are trying to move the servo.

I did some voltage testing on the PCA9685 setup as follows:

  • motor is rotating in increments of 1: sometimes drops to 5.99 V
  • motor is told to rotate (but isn't rotating) in increments of 20: 6.19 V
  • voltage at motor connection terminals with motor disconnected: 6.20 V

slipstick:
But for now, just to check, if you have a small 9g servo like an SG90 try putting that in place of your 60g 17Kg.cm servo and see if it works.

I tried a small servo and It seemed to work fine.

Try a beefy capacitor across the servo supply (close to the servo connector).
1000uF, 4700uF, whatever you have.
That will help the battery with the high stall (startup) current.
You can't measure that short brownout with a DMM. Only with a scope.
Leo..

Just a thought, is the 15ms delay enough time for the servo to react?