Servo gone crazy: moves without me sending command.

Hello,

I have two of these little servos: http://www.dealextreme.com/p/sg90-mini-servo-with-gears-and-parts-2kg-torque-35764

1- I tested them with the code bellow (from playground). They were working fine connected to an arduino:
2- Now that I almost fish assembling my robot and have them connected to a serial servo controleur, I started programing.
3- All my servos work fine expect for these two. They move like crazy without me sending any command.
4- I thought it might be some kind of incompatibility with the servo controller. But when I plug them back to a stock arduino with same code as before they keep moving continuously in one direction or alternatively.

May I have damaged them somehow? Here is the model of the serial controller I used: Pololu Micro Serial Servo Controller (assembled)

Any help would be welcome!

#include <Servo.h>
int minPulse1     =  0;   // minimum servo position
int maxPulse1     =  180; // maximum servo position
int turnRate1     =  10;  // servo turn rate increment (larger value, faster rate)
int minPulse2     =  0;  // minimum servo position
int maxPulse2     =  180; // maximum servo position
int turnRate2     =  10;  // servo turn rate increment (larger value, faster rate)
int buttonPin     = 13;    // pin that the trigger will be connected to
/** The Arduino will calculate these values for you **/
int centerServo1;
int centerServo2;
int pulseWidth1;	    // servo pulse width
int pulseWidth2;	    // servo pulse width

Servo servo1;
Servo servo2;

void setup() {
  pinMode(buttonPin, OUTPUT);
  servo1.attach(4);
  servo2.attach(10);
  centerServo1 = maxPulse1 - ((maxPulse1 - minPulse1)/2);
  centerServo2 = maxPulse2 - ((maxPulse2 - minPulse2)/2);
  pulseWidth1 =  centerServo1;
  pulseWidth2 =  centerServo2;
  Serial.begin(9600);	// opens serial port, sets data rate to 9600 bps
  Serial.println("	Arduino Serial Servo Control");
  Serial.println("Press a, s, d, or w to move, spacebar to center, and f to fire");
  Serial.println();
}

void loop() {

  // check for serial input
  if (Serial.available() > 0) {

    int data = Serial.read();	 // read the incoming byte:
    digitalWrite(buttonPin, LOW);  // turn the pin off on any incoming data
    switch(data)
    {
	case 'a' :  pulseWidth1 = pulseWidth1 - turnRate1;  break;
	case 'd' :  pulseWidth1 = pulseWidth1 + turnRate1;  break ;
	case ' ' :  pulseWidth1 = pulseWidth2 = centerServo1;  break;
	case 's' :  pulseWidth2 = pulseWidth2 - turnRate1;  break;
	case 'w' :  pulseWidth2 = pulseWidth2 + turnRate1;  break ;
	case 'f' :  digitalWrite(buttonPin, HIGH); delay (1000); digitalWrite(buttonPin, LOW); break;

    }
    // stop servo pulse at min and max
    if (pulseWidth1 > maxPulse1) { pulseWidth1 = maxPulse1; }
    if (pulseWidth1 < minPulse1) { pulseWidth1 = minPulse1; }

	// stop servo pulse at min and max
    if (pulseWidth2 > maxPulse2) { pulseWidth2 = maxPulse2; }
    if (pulseWidth2 < minPulse2) { pulseWidth2 = minPulse2; }

     servo1.write(pulseWidth1);
     servo2.write(pulseWidth2);

    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    Serial.print("Servo 1: ");
    Serial.print(pulseWidth1);
    Serial.print(" Servo 2: ");
    Serial.print(pulseWidth2);
    Serial.println("degrees");
  }
}

Did you try connecting the 'bad' servos in place of two of the servos that 'work fine'? If the 'bad' servos work fine when you put them in place of known working servos then either they were connected to bad channels on the controller or the software driving those channels is faulty. If the servos misbehave with known good channels, the problem is the servos.

Hello, Thanks for your answer,

Yes I did connect the 'bad' servos to the known to work channels: same issue, they move unexpectedly.
I don't know much about servos, but the only reasons I see is that there electronics went bad. Do you know any way to correct that ?

Thanks

Now that I almost fish assembling my robot

I love the idea of fish assembling a robot, what sort of fish bass, bream or salmon?

The reason why a servo moves like this is that it's input line is floating. This can be due to not initialising the pins connecting the servo as an output. I see in your code you don't do this, so add those lines and try again.

Simple servo test code that can be used to test individual servos.

// zoomkat 10-14-11 serial servo test
// type servo position 0 to 180 in serial monitor
// 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(2000); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-test-22"); // 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);  // allow buffer to fill with next character
    }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    myservo.writeMicroseconds(readString.toInt()); //convert readString to number for servo
    //myservo.write(readString.toInt()); //for degees 0-180
    readString=""; //empty for next input
  } 
}

Grumpy_Mike:

Now that I almost fish assembling my robot

I love the idea of fish assembling a robot, what sort of fish bass, bream or salmon?

I meant 'finish', never mind my tuna brain :smiley:

Grumpy_Mike:
The reason why a servo moves like this is that it's input line is floating. This can be due to not initialising the pins connecting the servo as an output. I see in your code you don't do this, so add those lines and try again.

OK will try the code bellow. But though it use to work fine with this code. And I expect the servo controller to initialise the servo correctly.
Could you be more precise about what you mean by 'input line is floating'?

Thanks a lot for your help.

When a line is an input it is not exerting any voltage pull in any direction. Doing a digitalWrite() on an input pin turns on an off the 30K internal pull up resistor. This is too high an impedance for some of your servos (your bad ones) but it looks like it is just enough for your other servos, but it is not very good.

And I expect the servo controller to initialise the servo correctly

You might expect it but no.

For more on floating inputs, see:-
http://www.thebox.myzen.co.uk/Tutorial/Inputs.html

Grumpy_Mike:

And I expect the servo controller to initialise the servo correctly

You might expect it but no.

That call to pinMode( pin, OUTPUT) in the Servo library looks like it should initialize the pin correctly:

uint8_t Servo::attach(int pin, int min, int max)
{
  if(this->servoIndex < MAX_SERVOS ) {
    pinMode( pin, OUTPUT) ;                                 // set servo pin to output
    servos[this->servoIndex].Pin.nbr = pin;  
    // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128 
    this->min  = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
    this->max  = (MAX_PULSE_WIDTH - max)/4; 
    // initialize the timer if it has not already been initialized 
    timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
    if(isTimerActive(timer) == false)
      initISR(timer);    
    servos[this->servoIndex].Pin.isActive = true;  // this must be set after the check for isTimerActive
  } 
  return this->servoIndex ;
}

Grumpy_Mike:
When a line is an input it is not exerting any voltage pull in any direction. Doing a digitalWrite() on an input pin turns on an off the 30K internal pull up resistor. This is too high an impedance for some of your servos (your bad ones) but it looks like it is just enough for your other servos, but it is not very good.

And I expect the servo controller to initialise the servo correctly

You might expect it but no.

For more on floating inputs, see:-
Inputs

Hmm not sure I understood this, to me I'm using an output which send a pulse of X ms to the servo and not an input.
Maybe it would help me if you tell me between which pin of the servo you advise to put a pull up resistor?

Thanks!

to me I'm using an output which send a pulse of X ms to the servo and not an input.

So initialise the pin as an output, you were not doing that in your code.

Looks like a confusion of pulse widths ( microseconds) and angles.
Have a good read of the sources of the servo library, and get back when you understand the ranges of values involved.

Servo test code that takes either angle input or microsecond input. In this code pin seven is used for the servo control signal. If this doesn't work, you probably have a power supply problem and/or the external power supply does not have a common ground with the arduino.

// 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);  //the pin for the servo control 
  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
  } 
}

I have 4 of those servos, in 2 of the 4 the signal wire had come loose inside the servo,from new, causing it shimmy and shake and turn one direction hard against the stop. if you have a small screw driver and a soldering iron it is an easy 2 minute fix. Hope this helps.
Charley

Sorry, it wasn't the signal wire , it was a wire on the little pot inside the servo, i just remembered.
Charley