Potentiometer-Controlled Servo

Potentiometer-Controlled Servo

Introduction

In the Servo Control with Servo Library project, we learned how to control a servo motor using a chipKIT™ board. In that project, our method of control was rather rudimentary: two pushbuttons were used to tell the servo to rotate either right or left. For this project, we will improve upon that design by replacing the pushbuttons with a single potentiometer (a variable resistor). As we did in the Potentiometer-Controlled LED Brightness project, we will use a potentiometer to build a voltage-divider circuit that will produce an analog signal that we will “read” using a chipKIT board. That signal will then, in turn, tell the chipKIT board angle to which the servo should rotate. Essentially, the angle of servo will match the position of the potentiometer dial.

Before you begin, you should:
  • Understand how servos work.
  • Understand how potentiometers work.
  • Understand how to obtain analog input.
  • Understand pulse-width modulated (PWM) signals.
After you're done, you should:
  • Understand how a potentiometer can be used to control the shaft position of a servo.

Inventory:

Qty Description Typical Image Schematic Symbol Breadboard Image
1 Potentiometer

(resistance ranging from 10 Ω to 10 kΩ)

1 Tower Pro SG92R servo

Background

This project uses concepts from previous projects and applies them to a new application. In the Potentiometer-Controlled LED Brightness project, we learned that you could use a potentiometer to provide a range of input values, as opposed to simple binary inputs. That project focused on creating an input device that would output an analog signal ranging from 0V to 3.3V. The signal was read by the chipKIT board, which, in turn, controlled the brightness of an LED according to strength of that signal.

Figure 1. Voltage divider circuit.

The tasks of changing the brightness of an LED or changing the angle of a servo actually share similar underlying features. In fact, for this project we can use the same method of input as was used in the Potentiometer-Controlled LED Brightness project. Thus we will re-use the same voltage divider circuit from the LED project. Figure 1 shows the voltage-divider circuit we will use.

The servo used for this project is the SG92R, which was also used in the Servo Control with Servo Library project. The servo configuration for this project is almost identical to the previous project, and we will again use the servo library to control our device.

Step 1: Setting up the Circuit

  1. Place the potentiometer dial so that it spans the gap between rows in the breadboard (as depicted in Fig. 2). Note that potentiometers can come in various configurations, and some have all their pins located on the same side (Fig. 3 shows both configurations). It is only important to make sure that each pin occupies its own row.
  2. Figure 2. Circuit diagram.
  3. With a wire, connect pin “A” of the potentiometer to the 3.3V pin of the chipKIT board.
  4. Connect the 5V pin of the chipKIT board to the “power” line of the servo. Note that the servo has a female connector, so you can plug straight into the connector, or you can use a gender changer to plug the connector into the breadboard. The servo cable color code is presented in Fig. 4.
  5. Figure 3. Alternate potentiometer pin configuration.
    Figure 4. Servo pin-out and color code.
  6. Connect pin “C” of the potentiometer to the ground (GND) pin of the chipKIT board. The row that pin “C” occupies will be designated ground row.
  7. Next, connect the “ground” line of the servo to the ground row.
  8. Using a long wire, connect pin “B” of the potentiometer to pin “A0” on the chipKIT board.
  9. Finally, connect the “control” line of the servo to pin 9 on the chipKIT board.

Software

The sketch for this project primarily uses the analogRead() and analogReference() functions as well as the Servo class member functions. A brief review of these function is provided below, but if you are unfamiliar with these functions, it would be best to work through the projects mentioned in the “Before You Begin” section above.

The analogRead() function does what its name implies: it provides a way for the chipKIT board to read a variable voltage signal from one of its analog inputs. The signal applied to one of these pins ranges from 0V to a maximum value of 3.3V. Exceeding 3.3V will result in incorrect readings (or may damage the board).

chipKIT boards use 10 bit analog-to-digital converters (ADC), so it quantizes the analog input to one of 1024 levels (210 = 1024), i.e., when you call analogRead() it maps the input to a number from 0 to 1023, where zero is the lowest voltage and 1023 is the largest voltage which corresponds to the “reference” voltage. The analogReference() function sets the voltage level that the ADC associates with 1023. Within this project, we will use the DEFAULT value, which is 3.3V for chipKIT boards.

For the Servo class, we will only be using the attach() and write() member functions. The attach() function simply tells the Servo object the pin to which it will output the control signal. The write() function sets the duty cycle of the PWM signal controlling the servo (essentially this tells the servo the angle to which to rotate the motor shaft).

Step 2: Writing the Sketch

Finally, the sketch must read the analog voltage value from the potentiometer, scale this value to an angle (between 0 and 180 degrees), and then tell the servo to move accordingly. The sketch, shown below, includes a 10 ms delay to allow time for the servo to (physically) move.

                  #include <Servo.h>
                  
                  Servo myServo;          // Instantiate a Servo object.
                  
                  const int aPinGlb = 0;  // The analog input pin.
                  
                  // Define a scale factor for converting from the quantized analog 
                  // input value to a degree in the range from 0 to 180.
                  // => scaleFactorGlb = 180/1023 = 0.17595
                  const float scaleFactorGlb = 0.17595;
                  
                  void setup() 
                  { 
                    // Setup the Servo class object to output on pin 9.
                    myServo.attach(9); 
                  
                    // Tell the chipKIT AD converter that the maximum analog
                    // voltage will be the default value of 3.3V.
                    analogReference(DEFAULT);
                  }
                   
                  void loop()
                  {
                    // Read the value from the analog pin connected to the potentiometer.
                    // The value will be between 0 and 1023.
                    int degree = analogRead(aPinGlb);
                  
                    // Convert input value to a degree.
                    degree = (int)((float)degree * scaleFactorGlb);
                  
                    // Write the input degree to the servo.
                    myServo.write(degree);
                  
                    // Wait 10 ms to allow the servo to move to desired position.
                    delay(10);
                  } 
                

  • Other product and company names mentioned herein are trademarks or trade names of their respective companies. © 2014 Digilent Inc. All rights reserved.
  • Circuit and breadboard images were created using Fritzing.