# Analog Feedback Servos

## About Servos and Feedback

![](https://cdn-learn.adafruit.com/assets/assets/000/010/617/medium800/adafruit_products_2013_08_24_IMG_2105cc-1024.jpg?1377358626)

# What is a Servo?
The word 'servo' means more than just those little RC Servo Motors we usually think of. Servo is a general term for a closed loop control system using negative feedback.   
  
The cruise control in a car is one example of a servo system. It measures your speed and feeds that back into a control circuit which adjusts the accelerator to maintain speed.   
  
For the familiar RC Servo motor, the position of the output shaft is measured and fed back to the internal control circuit which adjusts current to the motor to maintain position. # Open and Closed Loops
An "Open Loop" system has no feedback, so there is no way to verify that it is performing as expected. A common expression among control engineers is "You can't control what you can't measure.". ![](https://cdn-learn.adafruit.com/assets/assets/000/010/609/medium800/adafruit_products_OpenLoop.png?1377276330)

A "Closed Loop" system can use the feedback signal to adjust the speed and direction of the motor to achieve the desired result. In the case of an RC servo motor, the feedback is in the form of a potentiometer (pot) connected to the output shaft of the motor. The output of the pot is proportional to the position of the servo shaft.

![](https://cdn-learn.adafruit.com/assets/assets/000/010/606/medium800/adafruit_products_ClosedLoop.png?1377275606)

The problem with controlling a standard RC servo motor from a microcontroller is that it is 'closed loop' inside the servo motor case, but 'open loop' with respect to your microcontroller. You can tell the servo control circuit how you want the shaft positioned, but you have no way to confirm if or when this actually happens.

![](https://cdn-learn.adafruit.com/assets/assets/000/010/610/medium800/adafruit_products_OpenLoopMicro.png?1377276340)

The Feedback Servos allow you to close this outer loop by providing the feedback signal to the microcontroller too!

![](https://cdn-learn.adafruit.com/assets/assets/000/010/608/medium800/adafruit_products_ClosedLoopMicro.png?1377275642)

# Analog Feedback Servos

## Using Feedback

 **If a servo motor does what it is told to do, why do we need feedback?**  
  
RC servos _ **usually** _ do what they are told to do, but there are many cases where a servo motor **_might_**  **_not_**. These can include:  

- Insufficient motor size  
- Insufficient power supply  
- Physical interference  
- Electrical interference  
- loose connection  

In these cases, feedback could alert you to the problem.  
  
But even if the servo is adequately sized and functioning normally, it still takes some time to respond to a position command, and in many applications it is just as important to know **_when_** the position is reached.  
  
This following code snippet is from the "Sweep" example in the Servo library. Note the arbitrary 15 millisecond delay after   
"myservo.write(val)". ```auto
void loop() 
{ 
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023) 
  val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180) 
  myservo.write(val);                  // sets the servo position according to the scaled value 
  delay(15);                           // waits for the servo to get there 
} 
```

Without feedback, most servo programming has to make some assumptions about how long a particular move will take. Adding fixed-time delays to servo code works OK for simple applications, but can result in slow and/or jerky performance when trying to coordinate multiple servo motions or interactions between servos and other sensors or actuators.  
  
Or worse: If the delays are not long enough, your servos may not reach the desired position in time. This can cause malfunctions and/or damage to your project. Timing problems are a big problem in battery-powered projects because the motors will run slower as the battery power fades.

![](https://cdn-learn.adafruit.com/assets/assets/000/010/615/medium800/adafruit_products_2013_08_24_IMG_2107cc-1024.jpg?1377358530)

# Reading the feedback
The feedback signal is tapped off the position pot attached to the servo shaft. You can connect the white feedback wire to any of the analog input pins and read the feedback value using analogRead(). ```auto
  int feedback = analogRead(feedbackPin);
```

# Calibrating the feedback
The raw feedback signal is a voltage. In order to convert that voltage into a meaningful position, we need to calibrate it to the servo. By reading the feedback values at two known positions, we can interpolate the expected feedback values for every position in between.  
  
The following bit of code does just that. If you call "calibrate" in your setup function, it will perform the calibration on the two points you specify. These servos operate over a range of about 0 to 180 degrees. For maximum accuracy, you should choose the minPos and maxPos calibration points based on the range of motion required in your project. ```auto
#include <Servo.h> 
 
Servo myservo;  

// Control and feedback pins
int servoPin = 9;
int feedbackPin = A0;

// Calibration values
int minDegrees;
int maxDegrees;
int minFeedback;
int maxFeedback;
int tolerance = 2; // max feedback measurement error

/*
  This function establishes the feedback values for 2 positions of the servo.
  With this information, we can interpolate feedback values for intermediate positions
*/
void calibrate(Servo servo, int analogPin, int minPos, int maxPos)
{
  // Move to the minimum position and record the feedback value
  servo.write(minPos);
  minDegrees = minPos;
  delay(2000); // make sure it has time to get there and settle
  minFeedback = analogRead(analogPin);
  
  // Move to the maximum position and record the feedback value
  servo.write(maxPos);
  maxDegrees = maxPos;
  delay(2000); // make sure it has time to get there and settle
  maxFeedback = analogRead(analogPin);
}

 
void setup() 
{ 
  myservo.attach(servoPin); 
  
  calibrate(myservo, feedbackPin, 20, 160);  // calibrate for the 20-160 degree range
} 

void loop()
{
}
```

# Using feedback in your code
Now that we have a calibrated feedback signal, we can easily convert between servo position and feedback voltages in our code.   
  

## Seeking to a position
The following bit of code will seek to a position and return as soon as we reach it. There is no need to add an arbitrary delay to the code because the feedback signal will tell us exactly when we get there!  
```auto
void Seek(Servo servo, int analogPin, int pos)
{
  // Start the move...
  servo.write(pos);
  
  // Calculate the target feedback value for the final position
  int target = map(pos, minDegrees, maxDegrees, minFeedback, maxFeedback); 
  
  // Wait until it reaches the target
  while(abs(analogRead(analogPin) - target) > tolerance){} // wait...
}
```

## Finding out where you are
Another great thing about feedback is: You don't need to write code to remember the last position command you sent to the servo (assuming it got there). If you want to find out what position your servo is in, you can simply ask it!  
  
Once you have calibrated your servo with the calibration function above, this bit of code will tell you the current position (in degrees) of your servo: ```auto
int getPos(int analogPin)
{
  return map(analogRead(analogPin), minFeedback, maxFeedback, minDegrees, maxDegrees);
}
```

The ability to simply read the servo position opens up the possibility of using it as an input device as well. The next page will show you how.

# Analog Feedback Servos

## Servos as Input Devices

![](https://cdn-learn.adafruit.com/assets/assets/000/010/616/medium800/adafruit_products_2013_08_24_IMG_2107cc-1024.jpg?1377358596)

Another neat feature of feedback servos is that they can be used as an input device too! The Servo Record/Play Demo lets you record a series of servo movements, then it will replay them back for you! The recorded positions are saved in EEPROM, so they will be remembered even after resetting or powering down the Arduino  
  
To run this demo, first wire up your Servo as in the Fritzing diagram below:  
  
**Components used:**

- [Arduino Uno](http://www.adafruit.com/products/50 "Link: http://www.adafruit.com/products/50")  
- [Feedback Servo](http://www.adafruit.com/products/1404 "Link: http://www.adafruit.com/products/1404")  
- [2x pushbuttons](http://www.adafruit.com/products/1119 "Link: http://www.adafruit.com/products/1119")  
- [LED](http://www.adafruit.com/products/299 "Link: http://www.adafruit.com/products/299")(most any 3 or 5mm led will work)  
- 220 ohm resistor  
- [Misc. jumpers](http://www.adafruit.com/products/758 "Link: http://www.adafruit.com/products/758")  
- [Breadboard](http://www.adafruit.com/products/64 "Link: http://www.adafruit.com/products/64")

![](https://cdn-learn.adafruit.com/assets/assets/000/010/613/medium800/adafruit_products_record_play_wiring_bb.png?1377291692)

Next, download the example sketch from Github using this button:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Feedback_Servo_Record_and_Play/Feedback_Servo_Record_and_Play.ino

## To run the Servo Record/Play Demo Sketch:

1. Upload servo\_recordplay to the arduino  
2. press the top button to start recording. (The LED should light up.)  
3. Press the top button once more to stop recording.  
4. Press the bottom button to replay.  
5. You can press the green button as many times as you want.  
6. To record a new sequence, go back to step 2.  

Watch the video below to see it in operation:  
Danger: 

http://www.youtube.com/watch?feature=player_embedded&v=D8BLIr4w2JQ

# Analog Feedback Servos

## Using With CircuitPython

All of the general discussion from the previous sections still apply. Here we simply provide [CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython) versions of the Arduino examples.

For the basics on using servos with CircuitPython, checkout the information in the Essentials guide:

[CircuitPython Servo](https://learn.adafruit.com/circuitpython-essentials/circuitpython-servo)
The following examples show usage with a [Feather RP2040](https://www.adafruit.com/product/4884) and the code is written for the pins shown. Use with a different CircuitPython board should be possible, but may require updating the code for the specific pins used.

## Wiring

The example codes are based on the wiring shown below for connecting the servo:

- **SERVO POWER** wire to **USB**
- **SERVO GROUND** wire to **GND**
- **SERVO SIGNAL** wire to **A1**
- **SERVO FEEDBACK (WHITE)** wire to **A3**

![](https://cdn-learn.adafruit.com/assets/assets/000/119/134/medium800/adafruit_products_servo_basic.png?1677800182)

## Reading the feedback

The basic mechanism is the same as before - simply connect the feedback to an analog input and read the value. To learn more about reading analog inputs, see the Essentials guide:

[CircuitPython Analog In](https://learn.adafruit.com/circuitpython-essentials/circuitpython-analog-in)
All that is needed is to setup an analog input and get its value. Here's a simple code snippet that does that:

```auto
FEEDBACK_PIN = board.A3
feedback = AnalogIn(FEEDBACK_PIN)
position = feedback.value
```

The examples that follow will show this in more detail.

# Analog Feedback Servos

## Calibrating The Feedback

You can use the program below to help determine the feedback values that correspond to your servo's range of motion.

If you want to calibrate over a difference angle range, change these lines at the top. However, 0 and 180 are the maximum limits.

```auto
# Calibration setup
ANGLE_MIN = 0
ANGLE_MAX = 180
```

When the code runs, it will print out the analog reading values that correspond to the min/max angles. Write these values down - they'll be used in the other examples.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Feedback_Servo_Record_and_Play/feedback_calibrate/code.py

When the code runs, it will print out the analog reading values that correspond to the min/max angles.

![](https://cdn-learn.adafruit.com/assets/assets/000/119/136/medium800/adafruit_products_Screenshot_from_2023-03-02_16-21-01.png?1677802885)

In the output above, the two values of interest are **15377** and **42890**. Write these values down - they'll be used in the other examples.

# Analog Feedback Servos

## Finding and Seeking

This example shows how to find the current position and use that to "seek" to a specific angle. Be sure to run the **calibration program from the previous** section first and change these lines at the top of the code with your servo's values:

```auto
# Calibration setup
CALIB_MIN = 15377
CALIB_MAX = 42890
```

If you calibrated over a different range of angles, also change those lines to match.

Here's the complete code listing:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Feedback_Servo_Record_and_Play/feedback_seek/code.py

When the code runs, the servo will move to the specified angles. The amount of time it took to get there will also be shown.

![](https://cdn-learn.adafruit.com/assets/assets/000/119/137/medium800/adafruit_products_Screenshot_from_2023-03-02_16-23-45.png?1677803038)

# Analog Feedback Servos

## Servo Record and Play

This example will let you record servo positions that you manually move to and then play them back. A few extra hardware items are needed:

- 2x push buttons
- 1x LED, any color
- 1x resistor, 220ohm (or anything higher)

Here's a Fritzing diagram of the wiring setup.

![](https://cdn-learn.adafruit.com/assets/assets/000/119/133/medium800/adafruit_products_record_play.png?1677800008)

Button functions are:

- **Left button** (yellow wire) - start/stop recording. The LED will be ON during recording.
- **Right button** (blue wire) - start/stop play back of recorded positions.

Be sure to run the calibration program first and change these lines at the top of the code with your servo's values.

```auto
# Record setup
CALIB_MIN = 15377
CALIB_MAX = 42890
```

Here's the complete code listing:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Feedback_Servo_Record_and_Play/feedback_record_play/code.py

Once running, press and release the record button. Now grab the servo arm and move it around gently and not too fast. You can stop recording by pressing the record button again. Otherwise recording will continue until the entire record buffer is filled up.

To play back what you have recorded, simply press the play button.

![](https://cdn-learn.adafruit.com/assets/assets/000/119/135/medium800thumb/adafruit_products_out.jpg?1677802444)


## Featured Products

### Analog Feedback Standard-Size Servo

[Analog Feedback Standard-Size Servo](https://www.adafruit.com/product/1404)
It looks like a servo; it acts like a servo, but it's more than just a servo! We got a factory to custom-make these classic 'standard' sized hobby servos with a twist - the feedback (potentiometer wiper) line is brought out to a fourth white wire. You can read this wire with an...

In Stock
[Buy Now](https://www.adafruit.com/product/1404)
[Related Guides to the Product](https://learn.adafruit.com/products/1404/guides)
### Analog Feedback Micro Servo - Plastic Gear

[Analog Feedback Micro Servo - Plastic Gear](https://www.adafruit.com/product/1449)
It looks like a micro servo, it acts like a micro servo, but it's more than just a micro servo! We got a factory to custom-make these classic 'micro' sized hobby servos with a twist - the feedback (potentiometer wiper) line is brought out to a fourth white wire. You can read this...

In Stock
[Buy Now](https://www.adafruit.com/product/1449)
[Related Guides to the Product](https://learn.adafruit.com/products/1449/guides)
### Analog Feedback Micro Servo - Metal Gear

[Analog Feedback Micro Servo - Metal Gear](https://www.adafruit.com/product/1450)
It looks like a micro servo, it acts like a micro servo, but it's more than just a micro servo! We got a factory to custom-make these quality metal-geared 'micro' sized hobby servos with a twist - the feedback (potentiometer wiper) line is brought out to a fourth white wire. You...

In Stock
[Buy Now](https://www.adafruit.com/product/1450)
[Related Guides to the Product](https://learn.adafruit.com/products/1450/guides)
### Premium Male/Male Jumper Wires - 40 x 6" (150mm)

[Premium Male/Male Jumper Wires - 40 x 6" (150mm)](https://www.adafruit.com/product/758)
Handy for making wire harnesses or jumpering between headers on PCB's. These premium jumper wires are 6" (150mm) long and come in a 'strip' of 40 (4 pieces of each of ten rainbow colors). They have 0.1" male header contacts on either end and fit cleanly next to each other...

In Stock
[Buy Now](https://www.adafruit.com/product/758)
[Related Guides to the Product](https://learn.adafruit.com/products/758/guides)
### Tactile Switch Buttons (12mm square, 6mm tall) x 10 pack

[Tactile Switch Buttons (12mm square, 6mm tall) x 10 pack](https://www.adafruit.com/product/1119)
Medium-sized clicky momentary switches are standard input "buttons" on electronic projects. These work best in a PCB but [can be used on a solderless breadboard as shown in this tutorial](https://learn.adafruit.com/adafruit-arduino-lesson-6-digital-inputs?view=all). The...

In Stock
[Buy Now](https://www.adafruit.com/product/1119)
[Related Guides to the Product](https://learn.adafruit.com/products/1119/guides)
### Half Sized Premium Breadboard - 400 Tie Points

[Half Sized Premium Breadboard - 400 Tie Points](https://www.adafruit.com/product/64)
This is a cute, half-size breadboard with&nbsp;400 tie points, good for small projects. It's 3.25" x 2.2" / 8.3cm&nbsp;x 5.5cm&nbsp;with a standard double-strip in the middle and two power rails on both sides.&nbsp;You can pull the power rails off easily to make the breadboard as...

In Stock
[Buy Now](https://www.adafruit.com/product/64)
[Related Guides to the Product](https://learn.adafruit.com/products/64/guides)
### Adafruit METRO 328 Fully Assembled - Arduino IDE compatible

[Adafruit METRO 328 Fully Assembled - Arduino IDE compatible](https://www.adafruit.com/product/50)
We sure love the ATmega328 here at Adafruit, and we use them&nbsp;_a lot_&nbsp;for our own projects. The processor has plenty of GPIO, Analog inputs, hardware UART SPI and I2C, timers and PWM galore - just enough for most simple projects. When we need to go small, we use a <a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/50)
[Related Guides to the Product](https://learn.adafruit.com/products/50/guides)

## Related Guides

- [Smart Cocktail Shaker](https://learn.adafruit.com/smart-cocktail-shaker.md)
- [Adafruit Ultimate GPS Logger Shield](https://learn.adafruit.com/adafruit-ultimate-gps-logger-shield.md)
- [WiFi Weather Station](https://learn.adafruit.com/wifi-weather-station-arduino-cc3000.md)
- [Ladyada's Learn Arduino - Lesson #0](https://learn.adafruit.com/ladyadas-learn-arduino-lesson-number-0.md)
- [TMP36 Temperature Sensor](https://learn.adafruit.com/tmp36-temperature-sensor.md)
- [Ladyada's Bento Box](https://learn.adafruit.com/lady-adas-bento-box.md)
- [Current Limiting Stepper Driver with DRV8871](https://learn.adafruit.com/current-limiting-stepper-driver-with-drv8871.md)
- [Adafruit AirLift Shield - ESP32 WiFi Co-Processor](https://learn.adafruit.com/adafruit-airlift-shield-esp32-wifi-co-processor.md)
- [RePaper eInk Development Board](https://learn.adafruit.com/repaper-eink-development-board.md)
- [Wireless Game Show Poppers for the Classroom!](https://learn.adafruit.com/wireless-game-show-poppers.md)
- [Trinket Audio Player](https://learn.adafruit.com/trinket-audio-player.md)
- [Adafruit Data Logger Shield](https://learn.adafruit.com/adafruit-data-logger-shield.md)
- [Arduino "Hunt The Wumpus"](https://learn.adafruit.com/arduino-hunt-the-wumpus.md)
- [Adafruit PN532 RFID/NFC Breakout and Shield](https://learn.adafruit.com/adafruit-pn532-rfid-nfc.md)
- [Arduino Lesson 4. Eight LEDs and a Shift Register](https://learn.adafruit.com/adafruit-arduino-lesson-4-eight-leds.md)
