SG90 Servo Difficulties

I'm having a number of difficulties with my SG90 servo motor. I have a suspicion that I may be having the same issues as posted here, but it's difficult to tell from the thread.

Initially when I was running the sweep sketch (exact code copied from here, and set up exactly the same way - signal@pin 9, +@5v, -@GND), my servo would whine almost like a fax machine. I figured out that the servo was trying to move beyond the 180 degree barrier, but was incapable of moving further. Winding it back 180 degrees (to the zero position) would correct this problem, but only until it reached the barrier again. Then it would whine once more. It has never successfully completed the sweep program.

I ended up disassembling it, and have cleaned and inspected the gears. They look fine. Reassembling the servo without the gears and running the sweep sketch causes the servo to continually spin, and adjusting the potentiometer (rotating the position of the servo) actually adjusts the speed of the servo, from full speed down to a stutter.

The servo also continually runs (and will not stop unless unplugged) when I upload the following code to the arduino:

#include <Servo.h>

Servo servo;

void setup()
{
  servo.attach(9);
}

void loop()
{ 
}

Adjusting this code to print to the serial monitor:

#include <Servo.h>

Servo servo;

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

void loop()
{
  Serial.println(servo.read());
}

gives me thirteen constant values of 93 returned before they stop.

Can anyone help me figure out what's going on?

Below is some servo test code. The usual things that may cause a servo behave as you describe are malformed control pulses, poor ground between the servo and the arduino, and powering the servo from the arduino, causing the arduino to reset.

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// 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.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7, 500, 2500);  //the pin for the servo control, and range if desired
  Serial.println("servo-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();  //convert readString into a number

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }

    readString=""; //empty for next input
  } 
}

When I upload the given code the servo immediately goes into spin mode, and continually spins without stopping. I have all the gears off, so only the motor portion of it is going. I've also added an AA power source (+ to VIN, - to GND) and I get the same results.

I can also only input 5-6 values into the serial monitor before it freezes (usually mid-statement). I get the following error in the Arduino program:

Binary sketch size: 6,496 bytes (of a 32,256 byte maximum)
java.io.IOException: Device not configured in writeArray
	at gnu.io.RXTXPort.writeArray(Native Method)
	at gnu.io.RXTXPort$SerialOutputStream.write(RXTXPort.java:1124)
	at processing.app.Serial.write(Serial.java:517)
	at processing.app.Serial.write(Serial.java:540)
	at processing.app.SerialMonitor.send(SerialMonitor.java:200)
	at processing.app.SerialMonitor.access$100(SerialMonitor.java:32)
	at processing.app.SerialMonitor$3.actionPerformed(SerialMonitor.java:89)
	at javax.swing.JTextField.fireActionPerformed(JTextField.java:492)
	at javax.swing.JTextField.postActionEvent(JTextField.java:705)
	at javax.swing.JTextField$NotifyAction.actionPerformed(JTextField.java:820)
	at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1645)
	at javax.swing.JComponent.processKeyBinding(JComponent.java:2859)
	at javax.swing.JComponent.processKeyBindings(JComponent.java:2894)
	at javax.swing.JComponent.processKeyEvent(JComponent.java:2822)
	at java.awt.Component.processEvent(Component.java:6159)
	at java.awt.Container.processEvent(Container.java:2083)
	at java.awt.Component.dispatchEventImpl(Component.java:4744)
	at java.awt.Container.dispatchEventImpl(Container.java:2141)
	at java.awt.Component.dispatchEvent(Component.java:4572)
	at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1856)
	at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:722)
	at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1000)
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:865)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:686)
	at java.awt.Component.dispatchEventImpl(Component.java:4616)
	at java.awt.Container.dispatchEventImpl(Container.java:2141)
	at java.awt.Window.dispatchEventImpl(Window.java:2489)
	at java.awt.Component.dispatchEvent(Component.java:4572)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:710)
	at java.awt.EventQueue.access$400(EventQueue.java:82)
	at java.awt.EventQueue$2.run(EventQueue.java:669)
	at java.awt.EventQueue$2.run(EventQueue.java:667)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
	at java.awt.EventQueue$3.run(EventQueue.java:683)
	at java.awt.EventQueue$3.run(EventQueue.java:681)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:680)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

bloogoo:
When I upload the given code the servo immediately goes into spin mode, and continually spins without stopping. I have all the gears off, so only the motor portion of it is going. I've also added an AA power source (+ to VIN, - to GND) and I get the same results.

Do you mean that you have attached your AA power source to the arduino's VIN? The AA source should power the servo, not the arduino, but the grounds should be connected.

wildbill:
Do you mean that you have attached your AA power source to the arduino's VIN? The AA source should power the servo, not the arduino, but the grounds should be connected.

Sorry. I have the AA + to servo +, and AA GND to Arduino GND

Typical wiring setup for external servo power.

zoomkat:
Typical wiring setup for external servo power.

I still have uncontrollable spinning, and freezing while using the serial monitor.

What do you get if you fully reassemble the servo and try zoomkat's test code? It's not uncommon that a servo doesn't have the full 180 degree range of movement - experiment will tell you what yours has.

Try increasing the baud rate and put a delay in your test code. As you have it, it's trying to send data to the serial port far far faster than can be handled.

I rebuilt it, and set the baud rate to 115200. I had a 250ms delay, and still I have constant spinning with no effect from input from the serial monitor.

When it's first plugged in and powered, the servo goes through a range of about 90 degrees: forward, backward, forward, backward, and then tries to drive forward beyond its range and gets jammed. I have to disconnect the power and manually twist it back every time I try again.

bloogoo:
I rebuilt it, and set the baud rate to 115200. I had a 250ms delay, and still I have constant spinning with no effect from input from the serial monitor.

When it's first plugged in and powered, the servo goes through a range of about 90 degrees: forward, backward, forward, backward, and then tries to drive forward beyond its range and gets jammed. I have to disconnect the power and manually twist it back every time I try again.

I'm now not getting any movement/response when connected to the external power source (4 AA batteries), but I do get movement when the servo is connected to the 5V pin on the UNO. It still doesn't respond properly, but there's something there.

I would simplify the test procedure.

First, have you another servo, and does it behave the same. It may even be worth buying one just for this test.

Write a short sketch that has a setup() section and an empty loop() section. Don't bother with anything that might confuse you or the experiment such as Serial.read or baudrates.

In the setup() section just attach the servo and do a servo.write() to (say) 90 degrees. That should cause the servo arm to move to a position and stay there. You can then de-power the servo and manually move the servo arm to see if it it is in the middle position.

Modify the sketch as many times as necessary to see what values of degrees move the arm to the end point locations. When you know the limits of the servo you can try the sweep program between those limits.

It makes no sense to run the servo without its gears because they are what connect it to the potentiometer that it uses to determine when it is in the correct position.

...R

I rebuilt the servo and tested it as you suggested. Unfortunately the same behaviour is happening. I am getting movement when connected to the external power source, however, but it's not the expected movement. I have tested both the sweep code and zoomkat's code with another servo and they work perfectly.

Robin2:
It makes no sense to run the servo without its gears because they are what connect it to the potentiometer that it uses to determine when it is in the correct position.

I disassembled the servo again, and uploaded the following code:

#include <Servo.h>

Servo servo;

void setup()
{
  Serial.begin(115200);
  servo.attach(9);
}

void loop()
{
  Serial.println(servo.read());
}

When I rotate the potentiometer (without gears attached) the only value that's reported back is 93. I can rotate completely from one direction to the other, and the value stays 93. I'm guessing that the potentiometer isn't being detected by the circuitry within the servo.

You haven't read the documentation! Servo.read() just returns the last value you sent with Servo.write(). Servos have no means to send their position back to the Arduino.

I don't understand why you say you "disassembled the servo again" when you were advised not to do that. You will only make sense of the servo library if the servo is fully assembled as it was when it left the factory.

Have you tried a short piece of code that just moves the servo to its mid point - does that work?

...R

I'm using this code, as you've suggested:

#include <Servo.h>

Servo servo;

void setup()
{
  servo.attach(9);
  servo.write(90);
}

void loop()
{ 
}

When I upload this code, my servo spins clockwise until it cannot spin further (let's call that the 180 position), and then tries to spin further. It gives out a little hum while doing so. When I disconnect it, I find that it's not in the middle at all. I wind it back to the midpoint, (call that the 90 position) and try again. It spins clockwise until it reaches 180 and tries to spin further. When I set it back to the 0 position, it does the same thing.

I've also attempted to modify the code above by changing "90" to: 0, 30, 45, 60, 90, 120, 135, 150, 180. For each one, I would change the number in the servo.write() statement and upload it. Each time the servo rotates counterclockwise to the 180 point and tries to spin further.

I don't understand why you say you "disassembled the servo again" when you were advised not to do that.

I'm frustrated trying to get this to work, and I'm trying anything and everything that I can think of to figure out what the issue is.

Well I'm afraid you have a broken servo... There is probably something wrong with the pot or the wiring from the pot to the little controller board in the servo.

Bajdi:
There is probably something wrong with the pot or the wiring from the pot to the little controller board in the servo.

How could I determine if there's an issue with the controller board itself? I've detached and reattached the pot to the board, and I know it's a good connection. Also, the pot is working well.

The simplest test is almost certainly to buy another cheap servo and DON'T TAMPER WITH IT! If that works as expected it's a fair bet that the first servo is broken.

...R

Robin2:
The simplest test is almost certainly to buy another cheap servo and DON'T TAMPER WITH IT! If that works as expected it's a fair bet that the first servo is broken.

Let's go with the assumption that this servo is broken, because my other servo works fine. Is there anything I can do to fix it, or determine exactly where the issue is?

Let's go with the assumption that this servo is broken, because my other servo works fine. Is there anything I can do to fix it, or determine exactly where the issue is?

If your servo is spinning around like a continuous rotation, then two possible things may have happened. First most hobby servos have some type of travel stop to limit the rotation of the servo horn shaft. Your servo appears to not have one. Second, the servo pot must be attached to the servo horn shaft so that the pot rotates with the servo horn shaft. It appears the pot in your servo is either detached from the servo horn, or the pot has been damaged in some way. Below is a typical servo pix.