Servo Library's write function giving unexpected results

Hi,

I have recently purchased a servo motor. I think it is a rip-off, not sure of which model though. The specs that are given are in the link

http://robokits.co.in/shop/index.php?main_page=product_info&cPath=2_5&products_id=541

Anyway, I've been trying to use the write function and I have read the description in the library which says that the motor will move to a certain position if it is a standard servo or it will have a certain speed if it is a continuous servo.

Now I haven't tampered with the servo and the site says that it is modifiable to a continuous servo.

However, when I use the code

servo.write(0) It rotates in one direction

servo.write(180) It rotates little over 180 and then goes back and forth(sweeps) [Even if it was a cont. servo , why is this happening?]

servo.write(90) Stops

This happens instead of moving to a certain position.

I've also read that alternatively I can give a PWM signal to the signal pin of the servo but the resolution of the analogWrite() function is only 8-bit and the duty-cycle should be maintained at 1-2ms ON 18s OFF which means that the positions that the servo can take are limited.

I'm just a beginner. I'm tired of googling :( Help would be much appreciated.

Thank You!

Please post the actual code used, so we can check if there is something wrong with it.

How did you connect the servo's ? can you post a schema?

The connections are:

Powering the Vcc Ground of the servo with an external adapter of 5v O/P
Connecting Ground of the adapter with Ground of the board
And using a PWM pin for the control signal on the servo.

It’s a basic schematic I just googled the most basic one i could find.

As for the code :-


#include <Servo.h>

Servo myservo; // create servo object to control a servo

int pos ; // variable to store the servo position

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

void loop()
{
myservo.write(0);
delay(3000);
myservo.write(90);
delay(3000);
myservo.write(180);
delay(3000);
}


Also the output I get is as follows in the loop part of the code

myservo.write(0); //Rotates in one direction till it reaches the end and then stops
delay(3000);
myservo.write(90); //Stops
delay(3000);
myservo.write(180); //Rotates in one direction till it reaches the end , then the other direction(Sweeps)
delay(3000);

Thank you for replying.

You can use a PWM pin for a servo but there is no need to do so.

Have you experimented to see what happens with servo.write(170); and similar values to find out what is the maximum before the strange behaviour happens?

Can the servo power supply provide enough current? - how many amps?

If the power supply is OK it seems like a faulty servo. Do you have another servo that you could try?

...R

The power supply is a micro USB cable that i took apart and soldered. It's rating is 5.1v and 0.7A. I checked the voltage with a multimeter and that's fine and I just assumed that 0.7A was good enough.

So I did what you said and it seems that from the range of values 20-160 the motor stops(like the 90 condition I mentioned) and the lower and upper (0-20 and 160-180) perform a similar action to the 0 and 180 case I mentioned.

I had with me another Servo and on trying the same things on it I got completely different results. In this case the servo would go to different positions and stop for values between 20-160 (although most of these angles seemed legit, most of the angles were off) and the behaviour for 0-20 and 160-180 was the same as the first servo. Also both of them can go more than 180 deg but they lock at somewhere around 230 deg.

Usually when I'm having problems like these there is some fatal mistake I'm making or is just something I'm not aware of. So I'm really open to trying anything.Feel free to suggest anything.

Below is some servo test code you can try using the serial monitor to test your servo.

// zoomkat 12-25-13 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// Send an a to attach servo or d to detach servo
// for IDE 1.0.5 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

#include <Servo.h> 
String readString; //String captured from serial port
Servo myservo;  // create servo object to control a servo 
int n; //value to write to 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 all-in-one test code 12-25-13"); // so I can keep track of what is loaded
  Serial.println();
}

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 

      // attach or detach servo if desired
    if (readString == "d") { 
      myservo.detach(); //detach servo
      Serial.println("servo detached");
      goto bailout; //jump over writing to servo
    }
    if (readString == "a") {
      myservo.attach(7); //reattach servo to pin 7
      Serial.println("servo attached");
      goto bailout;
    }    

    n = readString.toInt();  //convert readString into a number

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

bailout: //reenter code loop
    Serial.print("Last servo command position: ");    
    Serial.println(myservo.read());
    Serial.println();
    readString=""; //empty for next input
  }
}

Lots of servos out there have about 150 degree range, not 180 degree. Servos are designed to move ailerons on model aircraft, don't expect them to be precision repeatable pieces of engineering, they are cheap and cheerful.

don't expect them to be precision repeatable pieces of engineering, they are cheap and cheerful.

Except the expensive, precision digital ones.

From Reply #2

myservo.write(0); //Rotates in one direction till it reaches the end and then stops

I thought what you meant by this was that the servo behaves as normal by rotating to the zero deg position and stopping.

If that is not what you meant, please explain in more detail - assuming the servo is at 90deg to start with.

One possibility is that the servo gets to its end stops before it reaches the commanded position. It then tries to push past the end stop and draws much more current - probably far more than 0.7amps. That would cause the voltage to drop with unknown consequences. Try using a servo power supply with plenty of amps - 4 x AA NiMh batteries, for example.

I just noticed that you said this servo could be changed to a continuous rotation servo. If that change can be made without opening up the servo it cannot have end stops and I suspect that you are required to keep the movement within the range of "normal" operation - which seems to be 20-160 according to your experiments.

...R

I think my problem is now mostly solved.

The main thing was using a correct range which was about 15-159 which I could find using the above code. Thanks for that.Even though the position for about 15-30 is being considered the same with my servo and it rotates 180 deg when I ask it to move from 20-160 , it seems it just needs to be scaled and its operation thus covers 180 deg.

My point being once the range is discovered it becomes a scaling problem for which using the microseconds command will provide enough resolution to cover most angles rather than using the write command.

The thing that bothers me now is that when I ask it to move from one position to another , for certain values it does not go directly, rather it goes back the other way and then goes. For example if I ask it to go from 35deg to 160deg , rather than going directly, it goes to 20deg and then to 160deg.

My problem is solved, I just wanted to know if I could alter this behaviour or if it is standard.

if it is standard.

No, it is not standard. The specs for the servo say that it is “360 Modifiable” but then so are most servos with a bit of surgery, so I doubt if there is anything special about this one.

UKHeliBob:
No, it is not standard.

So are you saying that this behaviour of the servo should not happen?

It should not happen. The servo should move from its current position directly to the new position with no movement in the opposite direction first.

What happens when you run the Sweep example that comes with the servo library ? How is the servo connected to the Arduino ? How is the servo powered ?

Accounting for the proper range which is 35-145 rather than 0-180 in the sweep program, it sweeps 180deg and back.

This is with increments of 1deg given by the for loop in the sweep program.

I increased the increments up to a value of 10deg and then 15deg in the for loop.

For 10 it works fine going directly but for 15 - certain values show the odd behaviour that i mentioned.

I used a micro USB adapter to power it which has a rating of 5v and 0.7A.

PWM pin 9 to the control signal of the servo.

Common grounds for adapter and the board.

ornuthewolf: I used a micro USB adapter to power it which has a rating of 5v and 0.7A.

As I said earlier, the servo will probably draw a lot more than 0.7amp when it is under load.

...R

Ahh finally.

It's working fine now.

I realize my problem was the power itself.

Knew it was something careless , my mistake.

Thanks to everyone for the help.

I know this isn't the forum for it but if I did want to power it using multiple adapters would it be safe to connect multiple adapters in parallel?

Also more importantly how much current would be sufficient to run a servo.

I would have no hesitation in connecting two DC power sources in series to increase the voltage but it is probably not a good idea to connect them in parallel to increase the current because one may feed into the other.

I reckon 1 amp is a minimum and if there are 2 or 3 amps available, so much the better. If it is a powerful servo it might need even more. Rechargeable batteries are good because they can supply a lot of current for a short period.

...R

Alright, Thanks for the reply.