Controlling Servos with Arduino

Here’s the one minute overview of how you control servos. Most servos rotate 180 degrees. Servos are controlled by a single digital pin. The way to tell a servo what to do is by sending them a high pulse for a certain duration. Most standard RC servos use a pulse of 1 millisecond to indicate 0 degrees of rotation and 2 milliseconds for 180 degrees. For you math geniuses out there that means 90 degrees is set via a 1.5 millisecond high signal.

One problem is that these servos are stupid. One of their few jobs is to remember the length of that last pulse you sent them and they can’t do it. They forget how long that last high pulse was after 50 milliseconds or so. This means just telling a servo what what position to go to is not enough. You need to constantly remind it because it’s retarded (sorry the politically correct term is mentally challenged). This means the signal you send to a servo needs to look something like this:

Servo Waveform

Now that you understand the theory, it’s pretty easy to write some code for a microcontroller and I did just that for Arduino. My code was pretty dumb and it just waited around until it was time to send the high pulse. There are lots of ways you could try to improve this. Instead of waiting you could just check how much time has passed since the last pulse and send a new one if needed. Or you could get fancy with interrupts and/or timers. I decided to get lazy and just use someone else’s fancy code. There are a lot of libraries for Arduino that control servos. I picked the Software Servo Library (you can download it from this link). To install it you just put the downloaded servo folder in the arduino-0011\hardware\libraries directory.

The power provided by the Arduino board should be enough for a standard servo. If you want to control a lot of servos or a bigger one then you’ll need to wire in an external power supply. If you’re doing this make sure you connect the grounds for the Arduino board and your servo power supply or weird things will happen. Trust me I know. I spend an hour dreaming up ways of torturing my Arduino board into telling why the hell it was acting so strange. Finally I got a small servo and it worked fine because I used the Arduino board’s ground. Instantly I apologized to Arduino for all my mean words and now we’re great friends again!

Here is the circuit and a photo on the actual hardware I used.

Servo Circuit

Arduino and Servo

Last but not least is the code I wrote that uses the Software Servo Library. Here’s a link to the code. I’ve also listed it below.

// Maurice Ribble
// 4-6-2008
// http://www.glacialwanderer.com/hobbyrobotics

// This code depends on the Servo Software Library.  You can get
// this lib from http://www.arduino.cc/playground/ComponentLib/Servo

// To use this app just send the board a number followed by an 's'
// to set the angle of the servo (0-180 are valid)

#include <Servo.h>
// This is the pin you need to attach the servo to
#define SERVO_1_PIN 2

Servo g_servo1;

void setup()
{
  pinMode(SERVO_1_PIN, OUTPUT);
  g_servo1.attach(SERVO_1_PIN);
  Serial.begin(9600);
  Serial.println("Enter number and press 's' to send it to servo.");
}

void loop()
{
  static int val = 0;

  if (Serial.available())
  {
    char ch = Serial.read();

    switch(ch)
    {
      case '0'...'9':
        val = val * 10 + ch - '0';
        break;
      case 's':
        g_servo1.write(val);
        Serial.print("Servo1 is set to: ");
        Serial.print(val, DEC);
        Serial.println(" degrees");
        val = 0;
        break;
    }
  }

  Servo::refresh();  // Should try to call this every 20 ms to insure servo stays set
}

9 Comments

  1. Wes said,

    January 10, 2010 @ 9:46 pm

    your forgot the ” ” in the include.

  2. Maurice Ribble said,

    January 10, 2010 @ 10:05 pm

    Thanks Wes. I fixed this. I noticed the link (http://www.glacialwanderer.com/_blog/blog2008/04_April/servo.pde) to this code was correct before so you could have gotten it there.

  3. registration said,

    February 11, 2010 @ 3:32 pm

    На данном сайте варезнике вы можете легко и бесплатно скачать все для рабочего стола и всё это бесплатно и без регистрации.

  4. Roy said,

    February 29, 2012 @ 9:13 pm

    I don’t understand this line;
    val = val * 10 + ch – ‘0’;

    it seems like val will always = 0 because of ‘static int val = 0;’ at the start of loop().
    so why multiply it here? and why subtract zero..?

  5. Maurice Ribble said,

    March 1, 2012 @ 6:01 am

    A static variable acts as global so it is only set to 0 an the first iteration. We subtracted the ascii character zero which has a value. See here for more info: http://en.wikipedia.org/wiki/ASCII

  6. Sean said,

    April 25, 2012 @ 7:00 pm

    When I try to upload this code, the sketch tells me ‘refresh’ is not a member of ‘Servo’. Why is this happening and how do I fix it?

  7. alex said,

    April 11, 2013 @ 2:25 am

    Hi, thank you to share the code. But i have the same problem than Sean : ‘refresh’ is not a member of ‘Servo’. I m a beginner, would yoy explain me the problem ?
    thanks again !

  8. Emre said,

    April 26, 2013 @ 9:01 am

    I also had the same problem. The reason might be “refresh” is not defined in the default servo library. So you might download the “Software Servo Library” and recompile the sketch. This would probably solve your problem. Correct me if I am wrong

  9. Pete said,

    August 22, 2013 @ 9:44 pm

    Should a flyback diode be used with the servo? Or does the arduino handle it?

RSS feed for comments on this post