Two servos behave very differently - why?

I have just started to experiment with servos for the first time.

I started experimenting with some basic example sketches and a "micro servo 9g A0090" - the sweep example from the IDE, and another from sparkfun. All fine and makes sense.

I started modifying code to try & achieve a 'bouncing' action. I realised I needed some acceleration control but so far haven't found an easy way to do that so there's a fair bit of code in the sketch just to achieve this. All is well with this servo and I'm getting some very convincing bouncing action.

I then connected an EMAX 08DE. The first thing I notice is that this servo is much quieter. The second is that the movements are executed with quite a degree of vagueness. The precise 'bounces' performed by the first servo are only lazily performed by this second one. It barely registers the smallest bounce at all and the acceleration isn't that noticeable.

What would be causing this? Both servos are rated at 6v - using an external power source seems to make no difference compared to using the 5v power off the arduino uno (Sparkfun redboard). I've tried increasing time between movements, in case the EMAX is slower to move or respond or something but it makes no difference to the precision of the movement, just slows it down.

I'll include the sketch I'm experimenting with, but I warn you, it's the sketch equivalent of 'thinking out aloud'...

EDIT: Apparently my code exceeds 9600 characters allowed for a post, so that idea's out, then...

I realised I needed some acceleration control but so far haven't found an easy way to do that

Not only is there not an easy way to do this, there is no way to do this.

Servos have their own control logic in them. They will respond at different speeds. You can slow them down to some extent by breaking any movement into small pieces but that will not get round the fact that they can be very different inside.

Apparently my code exceeds 9600 characters allowed for a post, so that idea's out

No. Read the how to use the forum sticky post. We do our best to hide it by only putting it at the top of every section.

If you are experimenting with / learning about steppers (or anything else) just use a very short sketch - for example the stepper sweep example.

...R

Thanks for your replies.

So Mike, are you saying that sketches have to effectively be written specifically for each individual servo? If certain brands of servo translate code in very different manners, this must cause havoc in some situations??

As I said in my original post, my code appears to work really well with the 9g servo with visually apparent acceleration, albeit executed in steps, but it appears smooth enough to my eyes.

I’ve noticed that the EMAX is referred to as a ‘digital’ servo, but can’t find anything about the 9g. What is the difference between an analog and a digital servo?

I did in fact read through the ‘how to use’ post when I got the error about too many characters, but found nothing specifically about that. I’ve had another read through just now and still not found anything. Perhaps I’m reading the wrong post - I’ll have a browse through the other sections meanwhile.

Read the bit about using attachments, the triangle at the bottom left of the reply box.

Yes trying to make a servo do anything other than just go to a position is hardware dependent. So younare best to write your own software and make your own servo or use a stepping motor. The reasion is that the mechanical damping, speed and overshoot are different on all servo designes.

http://www.rchelicopterfun.com/rc-servos.html

Thanks Mike - sketch attachment now included, for what it’s worth.

Thanks for the link. So it seems it’s the extra processing/translating the EMAX is doing, being digital, that is affecting it’s movement. Which would therefore lead me to assume that the 9g is analog, although it doesn’t seem to specifically say so on the webpage:

So if my analog assumpsion were correct and this sketch were to become a concept I used in a project, I would have to be sure I use an analog servo.

bounce_code_for_forum.ino (9.25 KB)

If its a cheap servo its analog, I think you can safely assume.

Thanks for posting the code. A few observations.
You have a delay 20 all over the place. Why not make that a variable and then in just one line you can change the value of that variable to see the effect without having to edit lots and lots of lines.

The other thing is your code looks a bit pedestrian, that is a lot of the same line over and over. When you find yourself writing code like that then you are doing something wrong and you could encode your idea with a better algorithm. Normally this will involve using arrays, that is making a variable variable. Here you move the servo at different rates with the loop. If you had an array that contained the servo increment rate at different points you could just look up what rate you need to go at. Then that code could all be done in about 10 to 20 lines tops.

I would expect some differences between servos but not a huge amount. The sort of differences that are common are

  • the extremes of movement - some will not move through 180 degrees, others will move a little more
  • the value in servo.writeMicroseconds() that corresponds to the extremes of movement. Notionally the extremes are 1000 (equivalent to 0 degrees) and 2000 (equivalent to 180 degrees) but in practice a servo might require a 100 to 200 microseconds either side of those values.
  • the natural speed at which the servo moves.

I think for the sort of effect you are trying to get you will have more control if you use servo.writeMicroseconds. And I think you should be able to match the behaviour of two servos by a simple correction - perhas an addition, subtraction or multiplication.

I share @Grumpy_Mike's views on your code structure.

...R

Thank you all for your replies.

I will look into writing in microseconds - perhaps this will improve my experience with the EMAX digi servo. This is how the Pololu maestro code seems to work as I’ve been experimenting with that as well & it’s very accurate down to very small steps. It just lacks the acceleration finesse that I seem to be getting with arduino & analog servo.

As for my code, I’ve been mulling it over but struggling to visualise an array that would work with the variable speed steps I’ve implemented. I thought as I typed it all out it seemed daft and hoped I’d find a way of cutting it down later. Could anybody nudge me in a direction or offer a clue as to how to go about it please?

The delays can certainly be a variable. They came about while on a cutting & pasting spree as I was thinking out aloud!

I also wanted to be able to vary the upper & lower limit of the servo’s movement with two pots. I had an idea to refer to the bounce points as percentages somehow, so that when the upper & lower limits were changed the bounce points were also compressed or expanded in proportion. My first thoughts were instead of referring to servo angles 0-180, I’d use something resembling this equation (X = lower servo limit angle & y = upper limit):

(((y-x)/100)xBOUNCEPERCENTAGE)+x

So the code resembled something like:

  for(position =(((y-x)/100)x50)+x ; position < (((y-x)/100)x80)+x; position += 1)
  {
    servo1.write(position);  // Move to next position
    delay(20);               // Short pause to allow it to move
  }

Etc etc

The servo just shook slightly and that was it - hardly a surprise. The “+x” would make it overshoot the upper limit anyway in certain conditions even if it did work, - I new my maths were on dodgy ground from the start!

Anyhow, I think I’d better just concentrate on simplifying my code for now…

“two finger” servo test code for testing servo movement using the serial monitor and pc keyboard keys.

// zoomkat 3-28-14 serial servo incremental test code
// using serial monitor type a character (s to increase or a 
// to decrease) and enter to change servo position 
// (two hands required, one for letter entry and one for enter key)
// use strings like 90x or 1500x for new servo position 
// for IDE 1.0.5 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

#include<Servo.h>
String readString;
Servo myservo;
int pos=1500; //~neutral value for continous rotation servo
//int pos=90;

void setup()
{
  myservo.attach(7, 400, 2600); //servo control pin, and range if desired
  Serial.begin(9600);
  Serial.println("serial servo incremental test code");
  Serial.println("type a character (s to increase or a to decrease)");
  Serial.println("and enter to change servo position");
  Serial.println("use strings like 90x or 1500x for new servo position");
  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) {
    if(readString.indexOf('x') >0) { 
      pos = readString.toInt();
    }

    if(readString =="a"){
      (pos=pos-1); //use larger numbers for larger increments
      if(pos<0) (pos=0); //prevent negative number
    }
    if (readString =="s"){
      (pos=pos+1);
    }

    if(pos >= 400) //determine servo write method
    {
      Serial.println(pos);
      myservo.writeMicroseconds(pos);
    }
    else
    {   
      Serial.println(pos);
      myservo.write(pos); 
    }
  }
  readString=""; //empty for next input
}