LESSON 16: Controlling a Servo with Arduino

Its time to get moving! In this project we show you how to get things moving with Arduino. You will need an arduino, a servo, a potentiometer and some wires. If you have the sparkfun inventor kit, it has everything you need (You can pick up the inventor kit HERE).

Servo Arduino
Circuit for controlling a Servo from the Arduino using a Potentiometer

For this project, our objective is to control the position of a servo based on the setting of a potentiometer. The servo should “track” the position of the potentiometer. In order to do this, we will need to start with our Voltage Divider Potentiometer circuit from LESSON 10. In addition, we will need to hook the servo up. for the servo in the sparkfun kit, it has three wires . . . red, white, and black. The red line is for power, so it should be hooked up to 5V from the arduino. The black line is ground, and should be hooked up to ground on the arduino. The white line is the control line, and it should be hooked up to one of the arduino pins with a squiggly line.  For this example, I am using pin 9. The small servo that comes with the sparkfun kit can be powered directly from the arduino. Understand that many servos draw lots of power, and require a separate power supply, and just the control line connects to the arduino. Realize that you must be careful and not hook a larger servo to the arduino for power, as that can damage your arduino. The one in the sparkfun kit can be driven by the arduino without a problem.  Also, some servos have a different color code on the wires. Many have red/orange/brown wires. For many of these types, the red is for power, the orange is for the control line, and the brown is for ground. Be sure to check the instructions on your servo to verify the color code.  As a reminder, this is circuit diagram for the potentiometer, which you will be using in this project.

This simple circuit allows you to create a voltage divider with a potentiometer, which we will use to set position of the Servo.

Most servos are designed to be operational in a range from 0 degrees to 180 degrees. The truth is though, that most will not operate over that full range. Also, you need to know that overdriving the servo beyond the range it wants to be in can damage both your arduino and your servo. Each servo is different, and sometimes two servos with same model number from the same manufacturer will have different ranges. Especially in the cheap ones (like in the sparkfun kit) have very different ranges.

So before going to far in any project you need to determine the range that your particular servo will operate in. In order to do this we need to write a simple program that will move the servo. In order to control the servo from the arduino, there are several things that must be done. The first is that you must “load” a library. A library is a special set of code written by the folks who make or sell the device in order to make it easier for you to work with. Libraries allow us to work with components in a more intuitive way. For the servo, you need to load the servo library, which comes with the arduino software you originally downloaded. To load the library, you need the following code at the top of your program:

Then, you need to create a servo “object”. This object will then be something you interact with to make the servo move. You can all the object anything you want, but I think I will call mine “myPointer” since I am going to make my servo point at things. The code to create the servo object would then look like this:

OK, now to make the servo go to a certain position, I would just have to issue a command like this:

This command goes to ‘pos’ which should nominally be between 0 and 180.  But remember that most servos will not go over that full range, so we will need to play around to see what range our servo can safely achieve. Also, the short 15 millisecond delay after moving the servo gives it time to get there and settle down. Never try and write the servo faster than it can naturally move.

The one other thing you need to do is let the arduino know which pin the servo is connected to for the control line. We are using pin 9, and will set up a variable at the top of the code to set servoPin=9, but it can be any pin that can analogWrite (one with a squiggly line).  To tell your arduino where the servo is connected, for the case of my servo which I names myPointer, the following code should be put in the void setup:

What you need to do now is write a program that will input the user for a position, and then write that position to the servo. The purpose of this is to determine the natural range of your particular servo. You should write this program yourself, but if you get stuck you can look at my code below. You should use this as a help if you need it, but your should not cut and paste it. Write your own code!

OK, with this code we should see the arduino prompt the user to a position and then write that position to the servo. The thing to do with this code is play around and figure out what range of motion your arduino can achieve. If you arduino sits and twitches, you have probably overdriven it. Keep playing with the numbers until you determine the range your servo can sweep to without jittering.

Once you know that range, you can play around with the code and the servo. Create a program that will smoothly sweep the servo through its range of motion. For my servo, I created the following code. Again, play with it yourself, and use this code only if you get stuck. Also, realize that my servo operates from 15 to 170 degrees, so that is why I used those numbers. You need to determine the range of motion for your servo, and use those numbers in the program.

 Now we need to write a program that will set the position based on the position of the potentiometer. We want the servo to point to the left if the potentiometer is positioned all the way to the left. Similarly we want the servo to point to the right if the potentiometer is all the way to the right. We need to do the math carefully to make sure that we do not try and overdrive the servo.  You must assume the user has no knowledge of servos and will turn the potentiometer to any position. In order to make sure the servo is not over-driven, you must carefully do the math. For this case, what is the independent variable? It is the number coming off the potentiometer. That is what you or the user “sets”, that is the independent variable, that is the horizontal axis. Now, what is the dependent variable? That is the pos (position) number. That is what you want to calculate from the independent variable. To do the math, think about the two points you know. You know that the potentiometer reads from 0 to 1023. You know that for my servo (yours will be different) the range of useful motion is from 15 to 170. So, when the potentiometer is set to 0 we want the position to be 15. There, you have one point, the point (0,15). Now we also know that when the potentiometer reads 1023, we want to position the servo at 170. So, now we have another point, the point (1023, 170). Now we have two points and can create the equation that will allow us to calculate the Pos based on the reading from the potentiometer. You should be able to do this by yourself now, but if you get stuck you can look at my notes. Remember, you need to do it for your values of useful range on the servo, not my numbers of 15 and 170.

linear equation
This shows the math to on how to calculate servo position based on potentiometer reading

So with this equation you can now calculate a pos for the servo based on the reading from the potentiometer. You should be able to write the code now to control the servo position from the potentiometer. If you get stuck watch the video that provides step-by-step directions on the code.

27 thoughts on “LESSON 16: Controlling a Servo with Arduino”

  1. how bout simple:
    int p_ANA_RVAL=analogRead(p_ANA); p_ANA – potentiometer at analog pin
    int s_map_p=map(p_ANA_RVAL,0,1023,15,170);

    1. Robert, these lessons are for High School Freshmen. As such, I am trying to use the lessons to emphasize practical applications of the math they are learning, hence I go through math showing that the equations of lines can be used to solve problems on the arduino. Also, since these students have never programmed before, I try to show code that is understandable, not necessarily the most efficient or elegant, but the easiest to understand.

        1. I need help you know in the beginning of your video it has the arrow go left and right can you tell me the code i need it for tomorrow

  2. Just a word of warning. I’ll try to keep it short. I am using the Arduino Pro Mini and up till now I have been following along, writing the code and performing the experiments with out problem.
    I have an application for the Pro Mini, using 17 servos, throwing turnouts on a model railroad. The sketch has already been written but I want to learn how to write my own.
    I was doing the trimpot controlling the servo and had it set at midpoint when it died. I had bought a bunch of these so I stuck a second unit in the setup and tried again. When it also died I thought about it for a moment. These work fine in practice but in practice I will not be moving them or writing to them repeatedly, only when the turnout needs to move. Driving a servo constantly may be ok for the Arduino you are using, but not for the Pro Mini.

    1. disregard! it turns out that my USB to Serial cable only works for a little while, the Pro Mini is still good. It (the cable) worked fine till now. Now it works for about five minutes. Have ordered replacements.

  3. Could you please: The variable pos was declared as int, the last line calculated with int and float(155. ) Is it ok ? or should we declare pos as float. The program is working OK , but still a thought

    1. The servo does not have a resolution greater than 1 degree, hence I just declared it an int. Also, using it as the index on the for loop makes it more reasonable to keep it an int.

  4. Thank you for these tutorials I am learning at an older age and it is fun! Yours are the easiest tutorials to understand that I have found.

    Thanks again!

  5. Thanks for the videos Paul, they are very helpful.

    In a previous video we found that the highest voltage code from the potentiometer is 1023. In the text above it is captured as 1083. The calculation photo shows 1023. Perhaps a typo or is there a concept we don’t know yet?

  6. Dear Paul, Thank you for the tutorials.
    Could you please clearify why you did not //Declare potPin to be an input in the void setup at the last project this lesson?
    How come the arduino still recognized it to be an input?
    & if it does, why are we declaring it to be an input in lesson 10?
    Thank you in advance.

    @ Robert Grzelka:
    how bout a simple explanation for the coding you just shared with us?

    1. We should always declare our variables and do our pinmodes. If I missed one, it was a mistake. Things might work, but it is a bad practice.

  7. Hi Paul I am probably your oldest student at 73, but I have been enjoying H out of following your lessons. I am currently working on lesson 16 and have run into a problem that I am at a loss to rectify. I am getting a Pointer:Servo:.write does not have class type. I have included the sketch as I wrote it and included the line with the error. Hope You can help

    Thanks Don

    #include // include servo library
    int servoPin =9; //tell arduino servo is on pin 9
    int servodelay =25; // delay for 1/4 second
    int pos=0; //declare and initalize pos
    Servo Pointer; //create a servo object called pointer

    void setup() {

    void loop() {
    for (pos=15; pos=15; pos=pos-1);{

    Pointer.write.(pos); at this line I get a Pointer.Servo:;write does not have class type


    1. It looks like you have an extra period after write that should not be there. It should be Pointer.write(pos)

  8. Thank you Paul for the good work, I am bless to have you.
    My question is; you declare a variable to store the servo position to zero (pos=0) but in the void loop, in for loop, the pos is 15, for (pos=15; pos<=170; pos=pos+1), it is working well but I don't understand why they are different (0 and 15).

    1. Servo’s can be flaky / jittery at the end of their movements if forced to drive to point ‘0’ and point ‘180’ so moving end travels maximums to point ’15’ and point ‘170’ is easier on the mechanism.

  9. thanks i learn a lot, i wanna ask what type of servo do you used analog or digital ? cause i using my digital servo then the servo to the position and back again to 0

  10. hello sir i am watching your all tutorial videos of arduino and its really awesome and simple for students like us.i have a request sir please make a tutorial with TFT screen shield and a Shift Register IC used project.i am waiting for respose sir thank u for your all efforts for making it .i Watched and write code by myself and you videos help me a lot.

  11. You are the best tutorial giver i’ve ever seen… ur works r detail.. tnx sir.

    But i hv one question.

    I want to control a motor(run by 220 volt) by arduino.. but 220v is a lot for the arduino…
    So what should be the electrical circuit between the arduino pin and the motor , just to control the motors sequence.

    Am waiting for the answer😢…
    +251 9 20 588 826

  12. Very clear lesson Arduino 16 Servo: which I followed to the letter ( even copied the text to be shure), when my servo did not follow your example.

    When writing a position via the “while-loop” , it correctly positions the servo to the requested position, but less than a second later it repositions itself to zero.
    What am I doing wrong?? or is it a broken servo??

    Thank you for any suggestion

      1. The servo I used was a SM-S2309S.
        Soo, I bought a 4AA batterypack and connected it to another servo I found in my box (Tower Pro microServo99 SG90) .
        Started the program and the servo was quiet, via the monitor I put in the degrees and hit return.
        The servo responded to the correct angle and then returned by itself to zero deg and from there it just kept on rotating clockwise, 360 degrees.

        This servo just keept turning 360 deg with short stops every time I wrote in a new angle

        Common ground for servo and Arduino,
        Arduino A9 as output to servo (via orange servo lead ).
        the positive lead from servo (red) connected directly to the batterypack ( not connected to Arduino !)

        the monitorresponse . . .
        Where would you like the Servo?
        servo position 60grader
        Where would you like the Servo?
        servo position 0grader
        Where would you like the Servo?

        . . . and here it just keeps on spinning without any further inputs.
        If I do another input, it responds with that deflection and returns to zero and starts spinning.

        Coupling the power to the arduino, just makes the servo turn slower (less power).

        hooking up the SM-S2309S. . . . .
        It responds to the correct angle, but returns to zero again, waiting for next input.

        out of options now!

        here is the copied code:

        #include //Load the servo Library
        int pos = 0; // variable to store the servo position
        int servoPin= 9; // Servo is hooked to pin 9
        int servoDelay=50; // 25 millisecond delay after each servo write

        Servo myPointer; //Create your servo object. I call mine ‘myPointer’

        void setup()
        myPointer.attach(servoPin); // attaches the servo myPointer to pin servoPin, which should be pin 9
        void loop()
        Serial.println(“Where would you like the Servo?”); //prompt user for position
        while (Serial.available()==0) { //wait for user input
        // om det är ett input, så hoppa vidare
        pos=Serial.parseInt(); //read user input into pos

        myPointer.write(pos); //set servo position to pos
        delay(servoDelay); // waits 15ms for the servo to reach the position

        Serial.print(“servo position “); //prompt user for position
        Serial.print(pos); //prompt user for position
        Serial.println(“grader “); //prompt user for position

        1. Solution:
          – – – ruling out a faulty servo gave me more time to investigate.
          The error finally emerged when selecting the serial monitor “line ending” to “no line ending”.
          Did not understand that it had such an impact on the behaviour of the servo.
          So. . .all back to normal.

Leave a Reply

Your email address will not be published. Required fields are marked *