Sunday 10 February 2013

Servo Offset

Hello everyone,

In this article I will like to describe a method for offsetting the servos.

When working with servos I realised that each servo is different in terms of achieved angle when a command is applied. What I mean is if I apply a command to turn a servo to let's say 90 degrees this will unlikely go exactly to 90 degrees. Almost any servo will go to slightly different angle. I imagine this is due to the assembly of the gears carried by the manufactures.

I tried to move the gears mechanically to overcome this but I didn't succeed so I've decided to correct this on software.

For each servo I need to find its offsetting value and then apply it to my code.

The easiest is to choose an angle easy to measure like 90 degrees. To turn a servo to this position we need to apply a 1500 microsecond pulse. In my code this corresponds to line like:

Serial.println (#0 P1500 T800);    //Move servo 0 to 90 degrees (1500 microseconds) and this movement will take 0.8 seconds

Then increase or decrease the value 1500 until the servo reaches exactly 90 degrees.

Note for Hitec servos: To turn a servo 0 degrees you need to apply around 500 microsecond pulse and to turn a servo 180 degrees you need to apply around 2500 microseconds pulse.

To make this task easy I created a code that increases and decreases the pulse value by typing in my computer keybord the caracters "+" and "-".

This code is also interesting because it shows how to interact with your servos using your computer keyboard.

Code:


int val = 0;
int angle = 1500;
int servo = 24;
int resolution = 10;                                   // This decrements or increments the microseconds value in 10 units.

void setup() {

Serial.begin(115200);
Serial.print ("#");
Serial.print (servo);
Serial.println (" P1500 T800");

}

void loop() {
  val = Serial.read();                                //Reads the value entered in the serial monitor after is sent
  if(val == '+'){

  Serial.print ("#");
  Serial.print (servo);
  Serial.print (" P");
  angle = angle + resolution;
  Serial.print (angle);
  Serial.print (" T");
  Serial.println (800);
  delay(1000);  
  }
  if(val == '-'){
  Serial.print ("#");
  Serial.print (servo);
  Serial.print (" P");
  angle = angle - resolution;
  Serial.print (angle);
  Serial.print (" T");
  Serial.println (800);
  delay(1000);
}}

As you can see in the code I applied 10 units of resolution. If you apply less then you almost will not see the servo move and if you increase the value too much the servo will make bigger jumps and you may not be able to achieve the desired angle.

In this example the right value to bring my servo exactly to 90 degrees was to apply 1440 microseconds.

See the Serial Monitor...


The values we obtain here are still a bit subjective... In my case I stopped at 1440 microseconds but another person may would stopped at 1430. Due to this reason I recommend to do this process with 3 angles... 0, 90 and 180 degrees so you will get 3 pair of values (a pair of values consists on an angle and its equivalent microsecond value).

Then you can apply the offset by using the equation for non-vertical lines:

                                                                 y = mx + c \,

I will explain how to apply the offset in my next post. I promise it will not take long to be published.