(edit sidebar)
Intro to Physical Computing Syllabus

Research & Learning

Other Class pages

Shop Admin

ITP Help Pages
Tom's pcomp site
DanO's pcomp site


Servo Motor Control with an Arduino

Labs.Servo History

Hide minor edits - Show changes to output

March 17, 2014, at 07:53 AM by Henchi Greg -
Changed line 37 from:
Pick any analog input and connect it to Analog pin 0 as you did in the [[Labs.AnalogIn|Analog Input and Output Lab]].  Then connect an RC servomotor to digital pin 2.  The yellow wire of the servo goes to the pin, and the red and black wires go to +5V and ground, respectively.
to:
Pick any analog input and connect it to Analog pin 0 as you did in the [[Labs.AnalogIn|Analog Input and Output Lab]].  Then connect an RC [[http://www.servomotor.co/| servomotor]] to digital pin 2.  The yellow wire of the servo goes to the pin, and the red and black wires go to +5V and ground, respectively.
Deleted line 44:
Attach:servo_control_fsr_bb2.png
Changed line 45 from:
Attach:servo_control_fsr_bb.png
to:
Attach:servo_control_fsr_bb2.png
Deleted line 32:
Attach:arduino_and_breadboard_bb2.png
Added lines 44-45:

Attach:servo_control_fsr_bb.png
Added lines 32-33:

Attach:arduino_and_breadboard_bb2.png
Added lines 127-128:
''This is just a suggestion for a short project.  It's not a requirement for the class homework.''
Changed lines 5-6 from:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor. Servos are the easiest way to start making motion with a microcontroller. Even though they don't turn 360 degrees, you can use them to create all sorts of periodic or reciprocating motions.  Check out some of the [[http://flying-pig.co.uk/mechanisms/index.html |Flying Pig]] mechanisms for ideas on how to make levers, cams, and other simple machines for making motion.
to:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor. Servos are the easiest way to start making motion with a microcontroller. Even though they don't turn 360 degrees, you can use them to create all sorts of periodic or reciprocating motions.  Check out some of the mechanisms at [[http://www.robives.com/mechs | Rob Ive's ]] site for ideas on how to make levers, cams, and other simple machines for making motion.
Changed lines 38-39 from:
Not all servos have the same wiring colors.  For example, the Hextronik servos that come with Adafruit's ARDX kit use red for +5V,brown for ground, and mustrard yellow for control.
to:
'''Not all servos have the same wiring colors.  For example, the Hextronik servos that come with Adafruit's ARDX kit use red for +5V,brown for ground, and mustrard yellow for control.'''
September 28, 2011, at 04:45 PM by shf220 - changed the range in the map() function from 0,255 to 0, 179
Changed line 89 from:
  int servoAngle = map(analogValue, 0, 1023, 0, 255);
to:
  int servoAngle = map(analogValue, 0, 1023, 0, 179);
Changed line 117 from:
  int servoAngle = map(analogValue, 0, 1023, 0, 255);
to:
  int servoAngle = map(analogValue, 0, 1023, 0, 179);
Changed lines 52-53 from:

to:
[[<<]]
Changed lines 51-53 from:
%lframe alt='Voila, your headers fit better!' hspace=10 width=200%[[Attach:servo_longer_headers.jpg | Attach:servo_longer_headers.jpg]] | Voila, your headers fit better!

to:
%lframe alt='Voila, your headers fit better' hspace=10 width=200%[[Attach:servo_longer_headers.jpg | Attach:servo_longer_headers.jpg]] | Voila, your headers fit better!

Changed lines 51-54 from:
%lframe alt='Voila, your headers fit better!' hspace=10 width=200%[[Attach:servo_longer_headers.jpg | Attach:servo_longer_headers.jpg]] | Put them in and push gently \\
on a firm surface


to:
%lframe alt='Voila, your headers fit better!' hspace=10 width=200%[[Attach:servo_longer_headers.jpg | Attach:servo_longer_headers.jpg]] | Voila, your headers fit better!

Added lines 45-54:
When you attach the servo, you'll need a row of three male headers to attach it to a breadboard.  You may find that the pins don't stay in the servo's connector holes. Put the pins in the servo's connector, then push them down on a table gently.  They will slide up inside their plastic sheaths, and fit better in your servo's sonnector.

%lframe alt='header pins don't always stay in a servo connector' hspace=10 width=200%[[Attach:servo_short_headers.jpg | Attach:servo_short_headers.jpg]] | header pins don't always\\
 stay in a servo connector
%lframe alt='Put them in and push gently on a firm surface' hspace=10 width=200%[[Attach:servo_headers_push.jpg | Attach:servo_headers_push.jpg]] | Put them in and push gently \\
on a firm surface
%lframe alt='Voila, your headers fit better!' hspace=10 width=200%[[Attach:servo_longer_headers.jpg | Attach:servo_longer_headers.jpg]] | Put them in and push gently \\
on a firm surface

Deleted line 94:
Changed lines 117-118 from:
 
(
:divend:)
to:
!!! Get Creative

Servo motors give you the power to do all kinds of things.

They can be used to push a remote contro button, in a pinch
:

http
://tigoe.net/ESBflash/img/remote.jpg ([[http://tigoe.net/ESBflash/celltoserial.shtml|Project]]: Tom Igoe)

You can [[http://itp.nyu.edu/~ndy204/blog/?p=141|play drums]] (Project: Nick Yulman)

You can make a [[http://itp.nyu.edu/~gg964/blog/archives/tag/rufus|rat's tail move]] (project: Gabriela GutiƩrrez)

If you've got 800 or so of them and a lot of time, you can build a [[http://smoothware.com/danny/woodenmirror.html| wooden mirror]] (project: Daniel Rozin).

Come up with a project of your own that needs a little movement, and see if you can solve the problem with a servomotor.
Changed lines 40-42 from:
%lframe alt='Arduino connected to a servomotor' hspace=10 width=300%[[Attach:Attach:servo_control_fsr_bb.png |Attach:Attach:servo_control_fsr_bb.png]]
to:
%lframe alt='Arduino connected to a servomotor' hspace=10 width=300%[[Attach:servo_control_fsr_bb.png | Attach:servo_control_fsr_bb.png]]
%lframe alt='Schematic:Arduino connected to a servomotor' hspace=10 align=top width=300 valign=center%[[Attach:servo_control_fsr_schem.png|Attach:servo_control_fsr_schem.png]]
[[<<
]]
Changed lines 44-46 from:
(:cell:)
%lframe alt='Schematic:Arduino connected to a servomotor' hspace=10 align=top width=300 valign=center%[[Attach:servo_control_fsr_schem.png|Attach:servo_control_fsr_schem.png]]

to:
Changed lines 47-55 from:
The following code examples will move the servo as the value of the sensor changes.

The first example shows you how to control a servo motor using a method that is traditionally taught at ITP which pulses the servo motor with a digital pin to set the position of the servo. This method is more complex and exposes the math and timing required to control a servo with a microcontroller.

The second example shows you how to control a servo motor using the Arduino Servo library. This library is very easy to use and is much easier to follow. However, it obscures all the calculations and handles the dirty work for you. This is useful once you've attempted the pulse method and understand it completely.

!!!! Using the pulse method

(:div class=code :)
to:
First, find out the range of your sensor by using analogRead() to read the sensor and printing out the results.

(:toggle question1 init=hide show='What does that look like?' hide='Let me figure it out':)
>>id=question1 border='1px solid #999' padding=5px bgcolor=#e1e7f1<<
(:source lang=arduino tabwidth=4 :)
void setup() {
  Serial.begin(9600); // initialize serial communications
}

void loop()
{
  int analogValue = analogRead(A0); // read the analog input
  Serial.println(analogValue); // print it
}
(:sourceend:)
>><<

Now, map the result of the analog reading to a range from 0 to 179, which is the range of the sensor in degrees. Store the mapped value in a local variable called servoAngle.

(:toggle question2 init=hide show='I give up, how do I do that?' hide='Let me figure it out':)
>>id=question2 border='1px solid #999' padding=5px bgcolor=#e1e7f1<<
(:source lang=arduino tabwidth=4 :)
void setup() {
  Serial.begin(9600); // initialize serial communications
}

void loop()
{
  int analogValue = analogRead(A0); // read the analog input
  Serial.println(analogValue); // print it
Changed lines 78-79 from:
 %color=#7e7e7e%/*
 %color=#7e7e7e% Servo control from an analog input
to:
  // if your sensor's range is less than 0 to 1023, you'll need to
  // modify the map() function to use the values you discovered:
  int servoAngle = map(analogValue, 0, 1023, 0, 255);
}
(:sourceend:)
>><<


Finally, add the servo library at the beginning of your code, then make a variable to hold an instance of the library, and a variable for the servo's output pin. In the setup(), initialize your servo using servo.attach(). Then in your main loop, use servoAngle to set the servo's position.

(:toggle question3 init=hide show='I give up, how do I do that?' hide='Let me figure it out':)
>>id=question3 border='1px solid #999' padding=5px bgcolor=#e1e7f1<<
(:source lang=arduino tabwidth=4 :)
#include <Servo.h>      // include the servo library

Servo servoMotor;      // creates an instance of the servo object to control a servo
int servoPin = 2;      // Control pin for servo motor


void setup() {
  Serial.begin(9600); // initialize serial communications
  servoMotor.attach(servoPin);  // attaches the servo on pin 2 to the servo object
}

void loop()
{
  int analogValue = analogRead(A0); // read the analog input
  Serial.println(analogValue); // print it
 
  // if your sensor's range is less than 0 to 1023, you'll need to
  // modify the map() function to use the values you discovered:
  int servoAngle = map(analogValue, 0, 1023, 0, 255);
 
  // move the servo using the angle from the sensor:
  servoMotor.write(servoAngle);                 
}
(:sourceend:)
>><<

Deleted lines 117-224:
 %color=#7e7e7e%The minimum (minPulse) and maxiumum (maxPulse) values
 %color=#7e7e7e%will be different depending on your specific servo motor.
 %color=#7e7e7e%Ideally, it should be between 1 and 2 milliseconds, but in practice,
 %color=#7e7e7e%0.5 - 2.5 milliseconds works well for me.
 %color=#7e7e7e%Try different values to see what numbers are best for you.
 
 %color=#7e7e7e%This program uses the millis() function to keep track of when the servo was
 %color=#7e7e7e%last pulsed.  millis() produces an overflow error (i.e. generates a number
 %color=#7e7e7e%that's too big to fit in a long variable) after about 5 days. if you're
 %color=#7e7e7e%making a program that has to run for more than 5 days, you may need to
 %color=#7e7e7e%account for this.
 
 %color=#7e7e7e%by Tom Igoe
 %color=#7e7e7e%additions by Carlyn Maw & Rob Faludi
 %color=#7e7e7e%Created 28 Jan. 2006
 %color=#7e7e7e%Updated 10 Jun. 2008
 %color=#7e7e7e%*/
 
 %color=#cc6600%int%% servoPin = 2;    %color=#7e7e7e%// Control pin for servo motor
 %color=#cc6600%int%% minPulse = 500;  %color=#7e7e7e%// Minimum servo position
 %color=#cc6600%int%% maxPulse = 2500;  %color=#7e7e7e%// Maximum servo position
 %color=#cc6600%int%% pulse = 0;        %color=#7e7e7e%// Amount to pulse the servo
 
 %color=#cc6600%long%% lastPulse = 0;    %color=#7e7e7e%// the time in milliseconds of the last pulse
 %color=#cc6600%int%% refreshTime = 20; %color=#7e7e7e%// the time needed in between pulses
 
 %color=#cc6600%int%% analogValue = 0;  %color=#7e7e7e%// the value returned from the analog sensor
 %color=#cc6600%int%% analogPin = 0;    %color=#7e7e7e%// the analog pin that the sensor's on
 
 %color=#cc6600%void%% %color=#cc6600%'''setup'''%%() {
  %color=#cc6600%pinMode%%(servoPin, %color=#006699%OUTPUT%%);  %color=#7e7e7e%// Set servo pin as an output pin
  pulse = minPulse;          %color=#7e7e7e%// Set the motor position value to the minimum
  %color=#cc6600%Serial%%.%color=#cc6600%begin%%(9600);
 }
 
 %color=#cc6600%void%% %color=#cc6600%'''loop'''%%() {
  analogValue = %color=#cc6600%analogRead%%(analogPin);      %color=#7e7e7e%// read the analog input
  pulse = %color=#cc6600%map%%(analogValue,0,1023,minPulse,maxPulse);    %color=#7e7e7e%// convert the analog value
                                                        %color=#7e7e7e%// to a range between minPulse
                                                        %color=#7e7e7e%// and maxPulse.
 
  %color=#7e7e7e%// pulse the servo again if rhe refresh time (20 ms) have passed:
  %color=#cc6600%if%% (%color=#cc6600%millis%%() - lastPulse >= refreshTime) {
    %color=#cc6600%digitalWrite%%(servoPin, %color=#006699%HIGH%%);  %color=#7e7e7e%// Turn the motor on
    %color=#cc6600%delayMicroseconds%%(pulse);      %color=#7e7e7e%// Length of the pulse sets the motor position
    %color=#cc6600%digitalWrite%%(servoPin, %color=#006699%LOW%%);    %color=#7e7e7e%// Turn the motor off
    lastPulse = %color=#cc6600%millis%%();          %color=#7e7e7e%// save the time of the last pulse
  }
 }
 
 
(:divend:)

This code was written with a potentiometer in mind, so it assumes you're going to get values from 0 to 1023 from the sensor. If you don't, the servo won't move through its whole range. Determine the range of numbers the sensor is giving you and adjust the servo formula to fit. To fix this, use the map() function. You know the input range is the range of the sensor, 0 to 1023. And you know the output range is from minPulse to maxPulse.  So do this:

(:div class=code :)
 pulseWidth = %color=#cc6600%map%%(analogValue, 0, 1023, minPulse, maxPulse);
(:divend:)

!!!! Using the Arduino Servo Library


(:div class=code :)
 
 %color=#7e7e7e%/*
 %color=#7e7e7e%Servo control from an analog input using the Arduino Servo library
 
 %color=#7e7e7e%This example code uses the Arduino Servo library which comes packaged with the Arduino software.
 
 %color=#7e7e7e%In order to make this work, you must include the Servo.h library file, create an instance of the Servo object.
 %color=#7e7e7e%attach a pin to the Servo object, and then write an analog value to the Servo object to set its
 %color=#7e7e7e%position.
 
 %color=#7e7e7e%The difference between using the Servo library and the older method of pulsing a digital pin is that the library
 %color=#7e7e7e%handles a lot of the work for you. You no longer need to figure out the translation between pulse length and position.
 %color=#7e7e7e%You now can simply specify the angle you'd like your servo to be at and it will turn to that position.
 
 
 
 %color=#7e7e7e%Updated 08 Sep 2009
 %color=#7e7e7e%by Rory Nugent
 %color=#7e7e7e%Created 20 Jan 2009
 %color=#7e7e7e%by Tom Igoe
 %color=#7e7e7e%*/
 
 #include <%color=#cc6600%Servo%%.h>      %color=#7e7e7e%// include the servo library
 
 %color=#cc6600%Servo%% servoMotor;      %color=#7e7e7e%// creates an instance of the servo object to control a servo
 
 %color=#cc6600%int%% analogPin = 0;      %color=#7e7e7e%// the analog pin that the sensor is on
 %color=#cc6600%int%% analogValue = 0;    %color=#7e7e7e%// the value returned from the analog sensor
 
 %color=#cc6600%int%% servoPin = 2;      %color=#7e7e7e%// Control pin for servo motor. As of Arduino 0017, can be any pin
 
 %color=#cc6600%void%% %color=#cc6600%'''setup'''%%() {
  servoMotor.%color=#cc6600%attach%%(servoPin);  %color=#7e7e7e%// attaches the servo on pin 2 to the servo object
 }
 
 %color=#cc6600%void%% %color=#cc6600%'''loop'''%%()
 {
  analogValue = %color=#cc6600%analogRead%%(analogPin);                %color=#7e7e7e%// read the analog input (value between 0 and 1023)
  analogValue = %color=#cc6600%map%%(analogValue, 0, 1023, 0, 179);    %color=#7e7e7e%// map the analog value (0 - 1023) to the angle of the servo (0 - 179)
  servoMotor.%color=#cc6600%write%%(analogValue);                      %color=#7e7e7e%// write the new mapped analog value to set the position of the servo
  %color=#cc6600%delay%%(15);                                          %color=#7e7e7e%// waits for the servo to get there
 }
 
 
 
Changed lines 36-38 from:
Pick any analog input and connect it to Analog pin 0 as you did in the [[Labs.AnalogIn|Analog Input and Output Lab]].  Then connect an RC servomotor to digital pin 2.  The yellow wire of the servo goes to the pin, and the red and black wires go to +5V and ground, respectively.

(
:table:)
to:
Pick any analog input and connect it to Analog pin 0 as you did in the [[Labs.AnalogIn|Analog Input and Output Lab]].  Then connect an RC servomotor to digital pin 2.  The yellow wire of the servo goes to the pin, and the red and black wires go to +5V and ground, respectively. 

Not all servos have the same wiring colors.  For example, the Hextronik servos that come with Adafruit's ARDX kit use red for +5V,brown for ground, and mustrard yellow for control.

%lframe alt='Arduino connected to a servomotor' hspace=10 width=300%[[Attach
:Attach:servo_control_fsr_bb.png |Attach:Attach:servo_control_fsr_bb.png]]
[--(Diagram made with [[http://fritzing.org | Fritzing]]--]
Changed lines 43-48 from:
%alt='Arduino connected to a servomotor' width=500px%[[Attach:Attach:servo_motor_control_with_sensor_bb.png |Attach:Attach:servo_motor_control_with_sensor_bb.png]]
[--(Diagram made with [[http://fritzing.org | Fritzing]] - [[Attach:servo_motor_control_with_sensor.zip | download]])--]
(:cell:)
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[Attach:servo_analog_sensor_schem.png|Attach:servo_analog_sensor_schem.png]]
(:tableend:)

to:
%lframe alt='Schematic:Arduino connected to a servomotor' hspace=10 align=top width=300 valign=center%[[Attach:servo_control_fsr_schem.png|Attach:servo_control_fsr_schem.png]]
Changed line 153 from:
 %color=#cc6600%int%% servoPin = 2;      %color=#7e7e7e%// Control pin for servo motor, may only be pin 9 or 10
to:
 %color=#cc6600%int%% servoPin = 2;      %color=#7e7e7e%// Control pin for servo motor. As of Arduino 0017, can be any pin
Deleted lines 39-40:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[Attach:servo_analog_sensor_schem.png|Attach:servo_analog_sensor_schem.png]]
(:cell:)
Added lines 42-43:
(:cell:)
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[Attach:servo_analog_sensor_schem.png|Attach:servo_analog_sensor_schem.png]]
Changed line 42 from:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:Attach:servo_motor_control_with_sensor_bb.png |Attach:Attach:servo_motor_control_with_sensor_bb.png]]
to:
%alt='Arduino connected to a servomotor' width=500px%[[Attach:Attach:servo_motor_control_with_sensor_bb.png |Attach:Attach:servo_motor_control_with_sensor_bb.png]]
Changed line 31 from:
to:
[--(Diagram made with [[http://fritzing.org | Fritzing]] - [[Attach:arduino_and_breadboard.zip | download]])--]
Changed lines 42-43 from:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:Attach:servo_analog_sensor_bb.png |Attach:Attach:servo_analog_sensor_bb.png]]
to:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:Attach:servo_motor_control_with_sensor_bb.png |Attach:Attach:servo_motor_control_with_sensor_bb.png]]
[--(Diagram made with [[http://fritzing.org | Fritzing]] - [[Attach:servo_motor_control_with_sensor.zip | download]])--
]
Changed line 40 from:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[Attach:servo_analog_sensor_sch.png|Attach:servo_analog_sensor_sch.png]]
to:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[Attach:servo_analog_sensor_schem.png|Attach:servo_analog_sensor_schem.png]]
Changed line 42 from:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:servo_motor_control_bb.png |Attach:servo_motor_control_bb.png]]
to:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:Attach:servo_analog_sensor_bb.png |Attach:Attach:servo_analog_sensor_bb.png]]
Changed line 40 from:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[http://itp.nyu.edu/physcomp/images/labs/servo_sch.png|http://itp.nyu.edu/physcomp/images/labs/Attach:servo_motor_control_sch.png]]
to:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[Attach:servo_analog_sensor_sch.png|Attach:servo_analog_sensor_sch.png]]
Changed line 40 from:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[http://itp.nyu.edu/physcomp/images/labs/servo_sch.png|http://itp.nyu.edu/physcomp/images/labs/servo_sch.png]]
to:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[http://itp.nyu.edu/physcomp/images/labs/servo_sch.png|http://itp.nyu.edu/physcomp/images/labs/Attach:servo_motor_control_sch.png]]
Changed line 42 from:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:servo_motor_control_bb.png |Attch:servo_motor_control_bb.png]]
to:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:servo_motor_control_bb.png |Attach:servo_motor_control_bb.png]]
Changed lines 30-31 from:
%alt='Arduino connected to a breadboard' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/arduino_bboard_power.jpg
to:
%width=600 alt='Arduino connected to a breadboard' align=top valign=center%[[Attach:arduino_and_breadboard_bb.png|Attach:arduino_and_breadboard_bb.png]]
Changed line 42 from:
%alt='Arduino connected to a servomotor' width=550px%[[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg|http://itp.nyu.edu/physcomp/uploads/servo_01.jpg]]
to:
%alt='Arduino connected to a servomotor' width=600px%[[Attach:servo_motor_control_bb.png |Attch:servo_motor_control_bb.png]]
Added lines 139-140:
 %color=#7e7e7e%Updated 08 Sep 2009
 %color=#7e7e7e%by Rory Nugent
Deleted lines 141-142:
 %color=#7e7e7e%by Rory Nugent
 %color=#7e7e7e%updated 8 Sep 2009
Changed lines 129-130 from:
 %color=#7e7e7e%In order to make this work, you must include the Servo.h library file, create an instance of the Servo object,
 %color=#7e7e7e%attach a digital PWM pin to the Servo object, and then write an analog value to the Servo object to set its
to:
 %color=#7e7e7e%In order to make this work, you must include the Servo.h library file, create an instance of the Servo object.
 %color=#7e7e7e%attach a pin to the Servo object, and then write an analog value to the Servo object to set its
Deleted line 136:
 %color=#7e7e7e%Please note, unlike the older pulsing method you MUST use a digital PWM pin or it will not work.
Changed lines 121-144 from:
'''NOTE: If you've just completed the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the following code to function as expected.'''

[@

/*
Servo control from an analog input using the Arduino Servo library

This example code uses the Arduino Servo library which comes packaged with the Arduino software.

In order to make this work, you must include the Servo.h library file, create an instance of the Servo object,
attach a digital PWM pin to the Servo object, and then write an analog value to the Servo object to set its
position.

The difference between using the Servo library and the older method of pulsing a digital pin is that the library
handles a lot of the work for you. You no longer need to figure out the translation between pulse length and position.
You now can simply specify the angle you'd like your servo to be at and it will turn to that position.

Please note, unlike the older pulsing method you MUST use a digital PWM pin or it will not work.

by Rory Nugent
Created 20 Jan. 2009
*/

#include <Servo.h>      // include the servo
library
to:

(:div class=code :)
 
 %color=#7e7e7e%/*
 %color=#7e7e7e%Servo control from an analog input using the Arduino Servo
library
Changed lines 127-132 from:
Servo servoMotor;      // creates an instance of the servo object to control a servo

int analogPin = 0;      // the analog pin that the sensor is on
int analogValue = 0;    // the value returned from the analog sensor

int servoPin = 9;      // Control pin for servo motor, may only be pin 9 or 10
to:
 %color=#7e7e7e%This example code uses the Arduino Servo library which comes packaged with the Arduino software.
Changed lines 129-131 from:
void setup() {
  servoMotor.attach(servoPin);  // attaches
the servo on pin 2 to the servo object
}
to:
 %color=#7e7e7e%In order to make this work, you must include the Servo.h library file, create an instance of the Servo object,
 %color=#7e7e7e%attach a digital PWM pin to the Servo object, and then write an analog value to the Servo object to set its
 %color=#7e7e7e%position.
Changed lines 133-141 from:
void loop()
{
  analogValue = analogRead(analogPin);                // read the analog input (value between 0 and 1023)
  analogValue = map(analogValue, 0, 1023, 0, 179);    // map the analog value (0 - 1023) to the angle of the servo (0 - 179)
  servoMotor.write(analogValue);                      // write the new mapped analog value to set the position of the servo
  delay(15);                                          // waits for the servo to get there
}

@]
to:
 %color=#7e7e7e%The difference between using the Servo library and the older method of pulsing a digital pin is that the library
 %color=#7e7e7e%handles a lot of the work for you. You no longer need to figure out the translation between pulse length and position.
 %color=#7e7e7e%You now can simply specify the angle you'd like your servo to be at and it will turn to that position.
 
 %color=#7e7e7e%Please note, unlike the older pulsing method you MUST use a digital PWM pin or it will not work.
 
 
 %color=#7e7e7e%Created 20 Jan 2009
 %color=#7e7e7e%by Rory Nugent
 %color=#7e7e7e%updated 8 Sep 2009
 %color=#7e7e7e%by Tom Igoe
 %color=#7e7e7e%*/
 
 #include <%color=#cc6600%Servo%%.h>      %color=#7e7e7e%// include the servo library
 
 %color=#cc6600%Servo%% servoMotor;      %color=#7e7e7e%// creates an instance of the servo object to control a servo
 
 %color=#cc6600%int%% analogPin = 0;      %color=#7e7e7e%// the analog pin that the sensor is on
 %color=#cc6600%int%% analogValue = 0;    %color=#7e7e7e%// the value returned from the analog sensor
 
 %color=#cc6600%int%% servoPin = 2;      %color=#7e7e7e%// Control pin for servo motor, may only be pin 9 or 10
 
 %color=#cc6600%void%% %color=#cc6600%'''setup'''%%() {
  servoMotor.%color=#cc6600%attach%%(servoPin);  %color=#7e7e7e%// attaches the servo on pin 2 to the servo object
 }
 
 %color=#cc6600%void%% %color=#cc6600%'''loop'''%%()
 {
  analogValue = %color=#cc6600%analogRead%%(analogPin);                %color=#7e7e7e%// read the analog input (value between 0 and 1023)
  analogValue = %color=#cc6600%map%%(analogValue, 0, 1023, 0, 179);    %color=#7e7e7e%// map the analog value (0 - 1023) to the angle of the servo (0 - 179)
  servoMotor.%color=#cc6600%write%%(analogValue);                      %color=#7e7e7e%// write the new mapped analog value to set the position of the servo
  %color=#cc6600%delay%%(15);                                          %color=#7e7e7e%// waits for the servo to get there
 }
 
 
 
(:divend:)
Changed line 116 from:
 pulseWidth = %color=#cc6600%map%%(sensorValue, 0, 1023, minPulse, maxPulse);
to:
 pulseWidth = %color=#cc6600%map%%(analogValue, 0, 1023, minPulse, maxPulse);
Added lines 55-122:
(:div class=code :)
 
 %color=#7e7e7e%/*
 %color=#7e7e7e% Servo control from an analog input
 
 %color=#7e7e7e%The minimum (minPulse) and maxiumum (maxPulse) values
 %color=#7e7e7e%will be different depending on your specific servo motor.
 %color=#7e7e7e%Ideally, it should be between 1 and 2 milliseconds, but in practice,
 %color=#7e7e7e%0.5 - 2.5 milliseconds works well for me.
 %color=#7e7e7e%Try different values to see what numbers are best for you.
 
 %color=#7e7e7e%This program uses the millis() function to keep track of when the servo was
 %color=#7e7e7e%last pulsed.  millis() produces an overflow error (i.e. generates a number
 %color=#7e7e7e%that's too big to fit in a long variable) after about 5 days. if you're
 %color=#7e7e7e%making a program that has to run for more than 5 days, you may need to
 %color=#7e7e7e%account for this.
 
 %color=#7e7e7e%by Tom Igoe
 %color=#7e7e7e%additions by Carlyn Maw & Rob Faludi
 %color=#7e7e7e%Created 28 Jan. 2006
 %color=#7e7e7e%Updated 10 Jun. 2008
 %color=#7e7e7e%*/
 
 %color=#cc6600%int%% servoPin = 2;    %color=#7e7e7e%// Control pin for servo motor
 %color=#cc6600%int%% minPulse = 500;  %color=#7e7e7e%// Minimum servo position
 %color=#cc6600%int%% maxPulse = 2500;  %color=#7e7e7e%// Maximum servo position
 %color=#cc6600%int%% pulse = 0;        %color=#7e7e7e%// Amount to pulse the servo
 
 %color=#cc6600%long%% lastPulse = 0;    %color=#7e7e7e%// the time in milliseconds of the last pulse
 %color=#cc6600%int%% refreshTime = 20; %color=#7e7e7e%// the time needed in between pulses
 
 %color=#cc6600%int%% analogValue = 0;  %color=#7e7e7e%// the value returned from the analog sensor
 %color=#cc6600%int%% analogPin = 0;    %color=#7e7e7e%// the analog pin that the sensor's on
 
 %color=#cc6600%void%% %color=#cc6600%'''setup'''%%() {
  %color=#cc6600%pinMode%%(servoPin, %color=#006699%OUTPUT%%);  %color=#7e7e7e%// Set servo pin as an output pin
  pulse = minPulse;          %color=#7e7e7e%// Set the motor position value to the minimum
  %color=#cc6600%Serial%%.%color=#cc6600%begin%%(9600);
 }
 
 %color=#cc6600%void%% %color=#cc6600%'''loop'''%%() {
  analogValue = %color=#cc6600%analogRead%%(analogPin);      %color=#7e7e7e%// read the analog input
  pulse = %color=#cc6600%map%%(analogValue,0,1023,minPulse,maxPulse);    %color=#7e7e7e%// convert the analog value
                                                        %color=#7e7e7e%// to a range between minPulse
                                                        %color=#7e7e7e%// and maxPulse.
 
  %color=#7e7e7e%// pulse the servo again if rhe refresh time (20 ms) have passed:
  %color=#cc6600%if%% (%color=#cc6600%millis%%() - lastPulse >= refreshTime) {
    %color=#cc6600%digitalWrite%%(servoPin, %color=#006699%HIGH%%);  %color=#7e7e7e%// Turn the motor on
    %color=#cc6600%delayMicroseconds%%(pulse);      %color=#7e7e7e%// Length of the pulse sets the motor position
    %color=#cc6600%digitalWrite%%(servoPin, %color=#006699%LOW%%);    %color=#7e7e7e%// Turn the motor off
    lastPulse = %color=#cc6600%millis%%();          %color=#7e7e7e%// save the time of the last pulse
  }
 }
 
 
(:divend:)

This code was written with a potentiometer in mind, so it assumes you're going to get values from 0 to 1023 from the sensor. If you don't, the servo won't move through its whole range. Determine the range of numbers the sensor is giving you and adjust the servo formula to fit. To fix this, use the map() function. You know the input range is the range of the sensor, 0 to 1023. And you know the output range is from minPulse to maxPulse.  So do this:

(:div class=code :)
 pulseWidth = %color=#cc6600%map%%(sensorValue, 0, 1023, minPulse, maxPulse);
(:divend:)

!!!! Using the Arduino Servo Library

'''NOTE: If you've just completed the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the following code to function as expected.'''

Deleted line 124:
Changed lines 126-143 from:
 Servo control from an analog input

The minimum (minPulse) and maxiumum (maxPulse) values
will be different depending on your specific servo motor.
Ideally, it should be between 1 and 2 milliseconds, but in practice
,
0.5 - 2.5 milliseconds works well for me.
Try different values to see what numbers are best for you.

This program uses
the millis() function to keep track of when the servo was
last pulsed.  millis() produces an overflow error (i.e. generates a number
that's too big to fit in a long variable) after about 5 days. if you're
making
a program that has to run for more than 5 days, you may need to
account for this.

by Tom Igoe
additions by Carlyn Maw & Rob Faludi
Created 28 Jan. 2006
Updated 10 Jun. 2008
to:
Servo control from an analog input using the Arduino Servo library

This example code uses the Arduino Servo library which comes packaged with the Arduino software.

In order to make this work
, you must include the Servo.h library file, create an instance of the Servo object,
attach a digital PWM pin to
the Servo object, and then write an analog value to the Servo object to set its
position.

The difference between using the Servo library and the older method of pulsing a digital pin is that the library
handles
a lot of the work for you. You no longer need to figure out the translation between pulse length and position.
You now can simply specify the angle you'd like your servo to be at and it will turn to that position.

Please note, unlike the older pulsing method you MUST use a digital PWM pin or it will not work.

by Rory Nugent
Created 20 Jan. 2009
Changed lines 144-158 from:
int servoPin = 2;     // Control pin for servo motor
int minPulse = 500
// Minimum servo position
int maxPulse = 2500;  // Maximum
servo position
int pulse = 0; 
      // Amount to pulse the servo

long lastPulse = 0;    // the time in milliseconds of
the last pulse
int refreshTime = 20; // the time needed in between pulses

int analogValue = 0; 
// the value returned from the analog sensor
int analogPin = 0; 
  // the analog pin that the sensor's on

void setup() {
 pinMode(servoPin, OUTPUT);  // Set
servo pin as an output pin
 pulse = minPulse;
          // Set the motor position value to the minimum
 Serial.begin
(9600);
to:
#include <Servo.h>      // include the servo library
 
Servo servoMotor
;       // creates an instance of the servo object to control a servo

int analogPin = 0;
     // the analog pin that the sensor is on
int analogValue = 0;    //
the value returned from the analog sensor

int servoPin = 9;   
  // Control pin for servo motor, may only be pin 9 or 10

void setup() {
  servoMotor.attach(servoPin);  // attaches the servo on pin 2 to the
servo object
}
 
void loop()
{
  analogValue = analogRead(analogPin);                 // read the analog input (value between 0 and 1023)
  analogValue = map(analogValue, 0, 1023, 0, 179);     // map the analog value (0 - 1023) to the angle of the servo (0 - 179)
  servoMotor.write(analogValue);                      // write the new mapped analog value to set the position of the servo
  delay(15);                                          // waits for the servo to get there
Deleted lines 164-244:
void loop() {
 analogValue = analogRead(analogPin);      // read the analog input
 pulse = map(analogValue,0,1023,minPulse,maxPulse);    // convert the analog value
                                                      // to a range between minPulse
                                                      // and maxPulse.

 // pulse the servo again if rhe refresh time (20 ms) have passed:
 if (millis() - lastPulse >= refreshTime) {
  digitalWrite(servoPin, HIGH);  // Turn the motor on
  delayMicroseconds(pulse);      // Length of the pulse sets the motor position
  digitalWrite(servoPin, LOW);    // Turn the motor off
  lastPulse = millis();          // save the time of the last pulse
 }
}

@]

This code was written with a potentiometer in mind, so it assumes you're going to get values from 0 to 1023 from the sensor. If you don't, the servo won't move through its whole range. Determine the range of numbers the sensor is giving you and adjust the servo formula to fit.

Here's a a scaling formula that will make the adjustment:

@@ (pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) / sensorRange @@

Multiply both sides by pulseRange, and you get:

@@ (pulseWidth - minPulse) = (sensorValue - minsensorValue) * pulseRange / sensorRange @@

Add the minimum pulse to both sides and you get:

@@ pulseWidth = ((sensorValue - minSensorValue) * pulseRange / sensorRange) + minPulse @@

That's the full ranging formula.  However, because there are no floating-point variables (i.e. fractions) in the Arduino language (and in most microcontroller languages), you have to fudge the formula a bit.  For example, if you have a sensor range from 0 to 512, and a servo range from 500 to 2500 (i.e. a 2000-point range), you know that you can just multiply the servo by 4 and add 500. You'll lose a little detail, but not enough to make a difference to the end user. 

When you're making approximations like this, you have to test the approximation at the extremes of both the sensor and the output to make sure it does the job.

!!!! Using the Arduino Servo Library

'''NOTE: If you've just completed the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the following code to function as expected.'''

[@

/*
Servo control from an analog input using the Arduino Servo library

This example code uses the Arduino Servo library which comes packaged with the Arduino software.

In order to make this work, you must include the Servo.h library file, create an instance of the Servo object,
attach a digital PWM pin to the Servo object, and then write an analog value to the Servo object to set its
position.

The difference between using the Servo library and the older method of pulsing a digital pin is that the library
handles a lot of the work for you. You no longer need to figure out the translation between pulse length and position.
You now can simply specify the angle you'd like your servo to be at and it will turn to that position.

Please note, unlike the older pulsing method you MUST use a digital PWM pin or it will not work.

by Rory Nugent
Created 20 Jan. 2009
*/

#include <Servo.h>      // include the servo library
 
Servo servoMotor;      // creates an instance of the servo object to control a servo

int analogPin = 0;      // the analog pin that the sensor is on
int analogValue = 0;    // the value returned from the analog sensor

int servoPin = 9;      // Control pin for servo motor, may only be pin 9 or 10
 
void setup() {
  servoMotor.attach(servoPin);  // attaches the servo on pin 2 to the servo object
}
 
void loop()
{
  analogValue = analogRead(analogPin);                // read the analog input (value between 0 and 1023)
  analogValue = map(analogValue, 0, 1023, 0, 179);    // map the analog value (0 - 1023) to the angle of the servo (0 - 179)
  servoMotor.write(analogValue);                      // write the new mapped analog value to set the position of the servo
  delay(15);                                          // waits for the servo to get there
}

Changed lines 133-134 from:
'''NOTE: If you've just completely the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the following code to function as expected.'''
to:
'''NOTE: If you've just completed the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the following code to function as expected.'''
Changed lines 49-50 from:
The first example shows you how to control a servo motor using a method that is traditionally taught at ITP which pulsed the servo motor with a digital pin to set the position of the servo. This method is more complex and exposes the math and timing required to control a servo with a microcontroller.
to:
The first example shows you how to control a servo motor using a method that is traditionally taught at ITP which pulses the servo motor with a digital pin to set the position of the servo. This method is more complex and exposes the math and timing required to control a servo with a microcontroller.
Changed lines 117-118 from:
@@ (pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) /sensorRange @@
to:
@@ (pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) / sensorRange @@
Changed lines 121-122 from:
@@ (pulseWidth - minPulse) = (sensorValue - minsensorValue * pulseRange /sensorRange @@
to:
@@ (pulseWidth - minPulse) = (sensorValue - minsensorValue) * pulseRange / sensorRange @@
Changed line 163 from:
int servoPin = 9;      // Control pin for servo motor, must be a PWM pin
to:
int servoPin = 9;      // Control pin for servo motor, may only be pin 9 or 10
Added lines 3-4:
!!!Overview
Changed lines 1-3 from:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor. Servos are the easiest way to start making motion with a microcontroller. Even though they don't turn 360 degrees, you can use them to create all sorts of periodic or reciprocating motions.  Check out some of the [[http://flying-pig.co.uk/mechanisms/index.html |Flying Pig]] mechanisms for ideas on how to make levers, cams, and other simple machines for making motion.  

to:
(:title Servo Motor Control with an Arduino:)

In this lab, you'll control a servomotor's position using the value returned from an analog sensor. Servos are the easiest way to start making motion with a microcontroller. Even though they don't turn 360 degrees, you can use them to create all sorts of periodic or reciprocating motions.  Check out some of the
[[http://flying-pig.co.uk/mechanisms/index.html |Flying Pig]] mechanisms for ideas on how to make levers, cams, and other simple machines for making motion.

(:toc Table of Contents:)

!!! Parts

Deleted lines 24-27:
If you're using an Arduino breadboard shield, there is a row of sockets connected to 5V on the analog in side of the breadboard, and a row connected to ground on the digital in side of the board:

%alt='Arduino breadboard shield' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/breadboard_shield.jpg

Deleted lines 31-35:
(:cellnr colspan=2:)
Schematic:
%alt='Schematic:Arduino connected to a servomotor' align=top height=300 valign=center%http://itp.nyu.edu/physcomp/images/labs/servo_sch.png
(:cellnr:)
%lframe width=380px% [[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg | http://itp.nyu.edu/physcomp/uploads/servo_01.jpg"Arduino connected to a servomotor"]] | [-Breadboard version: Arduino connected to a servomotor-]
Changed lines 33-34 from:
Breadboard Shield version:
%alt='Arduino Shieldconnected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_shield_servo.JPG
to:
%alt='Schematic:Arduino connected to a servomotor' align=top width=250px valign=center%[[http://itp.nyu.edu/physcomp/images/labs/servo_sch.png|http://itp.nyu.edu/physcomp/images/labs/servo_sch.png]]
(:cell:)
%alt='Arduino connected to a servomotor' width=550px%[[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg|http://itp.nyu.edu/physcomp/uploads/servo_01.jpg]]
Changed line 40 from:
%lframe width=360px% [[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg | http://itp.nyu.edu/physcomp/uploads/servo_01.jpg"Arduino connected to a servomotor"]] | [-Breadboard version: Arduino connected to a servomotor-]
to:
%lframe width=380px% [[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg | http://itp.nyu.edu/physcomp/uploads/servo_01.jpg"Arduino connected to a servomotor"]] | [-Breadboard version: Arduino connected to a servomotor-]
Changed lines 40-41 from:

%lframe width=320px% [[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg | http://itp.nyu.edu/physcomp/uploads/servo_01.jpg"Arduino connected to a servomotor"]] | [-Breadboard version: Arduino connected to a servomotor-]
to:
%lframe width=360px% [[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg | http://itp.nyu.edu/physcomp/uploads/servo_01.jpg"Arduino connected to a servomotor"]] | [-Breadboard version: Arduino connected to a servomotor-]
Changed lines 40-41 from:
Breadboard version:
%alt
='Arduino connected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_servo.JPG
to:

%lframe width
=320px% [[http://itp.nyu.edu/physcomp/uploads/servo_01.jpg | http://itp.nyu.edu/physcomp/uploads/servo_01.jpg"Arduino connected to a servomotor"]] | [-Breadboard version: Arduino connected to a servomotor-]
Changed lines 135-136 from:
'''NOTE: If you've just completely the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the servo library to function.'''
to:
'''NOTE: If you've just completely the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the following code to function as expected.'''
Added lines 135-136:
'''NOTE: If you've just completely the exercise using the pulse method and wish to experiment with the Arduino Servo library you MUST move your servo control pin from digital pin 2 to digital PWM pin 9. A digital PWM pin is needed for the servo library to function.'''
Changed lines 55-56 from:
!!!! Using the pulse method (without the Arduino Servo library)
to:
!!!! Using the pulse method
Changed lines 55-56 from:
!!!! Using the pulse method
to:
!!!! Using the pulse method (without the Arduino Servo library)
Changed lines 158-159 from:
Servo servoMotor;      // create servo object to control a servo
to:
Servo servoMotor;      // creates an instance of the servo object to control a servo
Changed line 173 from:
  servoMotor.write(analogValue);                      // sets the servo position with the new mapped value
to:
  servoMotor.write(analogValue);                      // write the new mapped analog value to set the position of the servo
Changed lines 115-116 from:
This code was written with a potentiometer in mind, so it assumes you're going to get values from 0 to 1023 from the sensor.  If you don't, the servo won't move through its whole range.    Determine the range of numbers the sensor is giving youm and adjust the servo formula to fit.
to:
This code was written with a potentiometer in mind, so it assumes you're going to get values from 0 to 1023 from the sensor. If you don't, the servo won't move through its whole range. Determine the range of numbers the sensor is giving you and adjust the servo formula to fit.
Added lines 51-54:
The first example shows you how to control a servo motor using a method that is traditionally taught at ITP which pulsed the servo motor with a digital pin to set the position of the servo. This method is more complex and exposes the math and timing required to control a servo with a microcontroller.

The second example shows you how to control a servo motor using the Arduino Servo library. This library is very easy to use and is much easier to follow. However, it obscures all the calculations and handles the dirty work for you. This is useful once you've attempted the pulse method and understand it completely.

Changed lines 49-50 from:
The following code will move the servo as the value of the sensor changes.
to:
The following code examples will move the servo as the value of the sensor changes.

!!!! Using the pulse method

Changed line 59 from:
The minimum (minPulse) and maxiumum (maxPuluse) values
to:
The minimum (minPulse) and maxiumum (maxPulse) values
Added lines 127-171:
!!!! Using the Arduino Servo Library

[@

/*
Servo control from an analog input using the Arduino Servo library

This example code uses the Arduino Servo library which comes packaged with the Arduino software.

In order to make this work, you must include the Servo.h library file, create an instance of the Servo object,
attach a digital PWM pin to the Servo object, and then write an analog value to the Servo object to set its
position.

The difference between using the Servo library and the older method of pulsing a digital pin is that the library
handles a lot of the work for you. You no longer need to figure out the translation between pulse length and position.
You now can simply specify the angle you'd like your servo to be at and it will turn to that position.

Please note, unlike the older pulsing method you MUST use a digital PWM pin or it will not work.

by Rory Nugent
Created 20 Jan. 2009
*/

#include <Servo.h>      // include the servo library
 
Servo servoMotor;      // create servo object to control a servo

int analogPin = 0;      // the analog pin that the sensor is on
int analogValue = 0;    // the value returned from the analog sensor

int servoPin = 9;      // Control pin for servo motor, must be a PWM pin
 
void setup() {
  servoMotor.attach(servoPin);  // attaches the servo on pin 2 to the servo object
}
 
void loop()
{
  analogValue = analogRead(analogPin);                // read the analog input (value between 0 and 1023)
  analogValue = map(analogValue, 0, 1023, 0, 179);    // map the analog value (0 - 1023) to the angle of the servo (0 - 179)
  servoMotor.write(analogValue);                      // sets the servo position with the new mapped value
  delay(15);                                          // waits for the servo to get there
}

@]
Added line 53:
Changed lines 55-74 from:
  Servo control from an analog input
 
 The minimum
(minPulse) and maxiumum (maxPuluse) values
 will be different depending on your specific servo motor.
 Ideally, it should be between 1 and 2 milliseconds, but in practice,
 0.5 - 2.5 milliseconds works well for me.
 Try different values to see what numbers are best for you.
 
 This program uses the
millis() function to keep track of when the servo was
 last
pulsed.  millis() produces an overflow error (i.e. generates a number
 that's too big to fit in a long variable) after about 5 days. if you're
 making a program that has to run for more than 5 days, you may need to
 account for
this.
 
by Tom Igoe
 additions by Carlyn Maw
 Created 28
Jan. 2006
 Updated 7 Jun. 2006
 
*/
to:
 Servo control from an analog input

The minimum (minPulse) and maxiumum (maxPuluse) values
will be different depending on your specific servo motor.
Ideally, it should be between 1 and 2 milliseconds, but in practice,
0.5 - 2.5 milliseconds works well for me.
Try different values to see what numbers are best for you.

This program uses the millis() function to keep track of when the servo was
last pulsed.  millis() produces an overflow error (i.e. generates a number
that's too big to fit in a long variable) after about 5 days. if you're
making a program that has to run for more than 5 days, you may need to
account for this.

by Tom Igoe
additions
by Carlyn Maw & Rob Faludi
Created 28
Jan. 2006
Updated 10 Jun. 2008
*/
Changed lines 87-89 from:
  pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
  pulse = minPulse;          // Set the motor position value to the minimum
  Serial.begin(9600);
to:
 pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
 pulse = minPulse;          // Set the motor position value to the minimum
 Serial.begin(9600);
Changed lines 93-104 from:
  analogValue = analogRead(analogPin);      // read the analog input
  pulse = (analogValue * 19) / 10 + minPulse;    // convert the analog value
                                            // to a range between minPulse
   
                                      // and maxPulse.

  // pulse the servo again if rhe refresh time (20 ms) have passed:
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite
(servoPin, HIGH);  // Turn the motor on
 
  delayMicroseconds(pulse);       // Length of the pulse sets the motor position
    digitalWrite(servoPin, LOW);    // Turn the motor off
 
  lastPulse = millis();          // save the time of the last pulse
  }
to:
 analogValue = analogRead(analogPin);      // read the analog input
 pulse = map(analogValue,0,1023,minPulse,maxPulse);    // convert the analog value
                                                    // to a range between minPulse
                                                       // and maxPulse.

 // pulse the servo again if rhe refresh time
(20 ms) have passed:
 if (millis() - lastPulse >= refreshTime) {
   digitalWrite(servoPin, HIGH);  // Turn the motor on
  delayMicroseconds(
pulse);      // Length of the pulse sets the motor position
  digitalWrite(servoPin, LOW);
    // Turn the motor off
  lastPulse = millis();         // save the time of the last pulse
 }
Changed line 93 from:
  pulse = (analogValue / 10) * 19 + 500;    // convert the analog value
to:
  pulse = (analogValue * 19) / 10 + minPulse;    // convert the analog value
Changed line 79 from:
int lastPulse = 0;    // the time in milliseconds of the last pulse
to:
long lastPulse = 0;    // the time in milliseconds of the last pulse
Added lines 62-71:
 This program uses the millis() function to keep track of when the servo was
 last pulsed.  millis() produces an overflow error (i.e. generates a number
 that's too big to fit in a long variable) after about 5 days. if you're
 making a program that has to run for more than 5 days, you may need to
 account for this.
 
 by Tom Igoe
 additions by Carlyn Maw
 Created 28 Jan. 2006
 Updated 7 Jun. 2006
Added lines 79-81:
int lastPulse = 0;    // the time in milliseconds of the last pulse
int refreshTime = 20; // the time needed in between pulses

Changed lines 97-103 from:
  Serial.println(pulse, DEC);              // print it out for reference

  digitalWrite(servoPin, HIGH);  // Turn the motor on
  delayMicroseconds(pulse);      // Length of the pulse sets the motor position
  digitalWrite(servoPin, LOW);    // Turn the motor off
  delay(20);                     // 20 millisecond delay is needed between pulses 
                                  // to keep the servo in sync
to:
  // pulse the servo again if rhe refresh time (20 ms) have passed:
  if (millis() - lastPulse >= refreshTime) {
 
  digitalWrite(servoPin, HIGH);  // Turn the motor on
    delayMicroseconds(pulse);      // Length of the pulse sets the motor position
    digitalWrite(servoPin, LOW);    // Turn the motor off
    lastPulse = millis();          // save the time of the last pulse
  }
Changed lines 21-22 from:
Conect power and ground on the breadboard to power and ground from the microcontroller. On the Arduino module, use the 5V and any of the ground connections:
to:
Connect power and ground on the breadboard to power and ground from the microcontroller. On the Arduino module, use the 5V and any of the ground connections:
Changed lines 1-2 from:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor.
to:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor. Servos are the easiest way to start making motion with a microcontroller. Even though they don't turn 360 degrees, you can use them to create all sorts of periodic or reciprocating motions.  Check out some of the [[http://flying-pig.co.uk/mechanisms/index.html |Flying Pig]] mechanisms for ideas on how to make levers, cams, and other simple machines for making motion. 

Changed lines 109-110 from:
That's the full ranging formula.  However, because there are no floating-point variables (i.e. fractions) in the Arduino language (and in most microcontroller languages), you have to fudge the formula a bit.  For example, if you have a sensor range from 0 to 750, and a servo range from 500 to 2500 (i.e. a 2000-point range), you know that
to:
That's the full ranging formula.  However, because there are no floating-point variables (i.e. fractions) in the Arduino language (and in most microcontroller languages), you have to fudge the formula a bit.  For example, if you have a sensor range from 0 to 512, and a servo range from 500 to 2500 (i.e. a 2000-point range), you know that you can just multiply the servo by 4 and add 500. You'll lose a little detail, but not enough to make a difference to the end user. 

When you're making approximations like this, you have to test the approximation at the extremes of both the sensor and the output to make sure it does the job.

Changed lines 108-109 from:

to:
That's the full ranging formula.  However, because there are no floating-point variables (i.e. fractions) in the Arduino language (and in most microcontroller languages), you have to fudge the formula a bit.  For example, if you have a sensor range from 0 to 750, and a servo range from 500 to 2500 (i.e. a 2000-point range), you know that
Changed lines 98-99 from:
[= (pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) /sensorRange =]
to:
@@ (pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) /sensorRange @@
Changed lines 102-103 from:
[= (pulseWidth - minPulse) = (sensorValue - minsensorValue * pulseRange /sensorRange =]
to:
@@ (pulseWidth - minPulse) = (sensorValue - minsensorValue * pulseRange /sensorRange @@
Changed lines 106-109 from:
[= pulseWidth = ((sensorValue - minSensorValue) * pulseRange / sensorRange) + minPulse =]


to:
@@ pulseWidth = ((sensorValue - minSensorValue) * pulseRange / sensorRange) + minPulse @@


Changed lines 98-99 from:
[=(pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) /sensorRange =]
to:
[= (pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) /sensorRange =]
Changed lines 102-103 from:
[=(pulseWidth - minPulse) = (sensorValue - minsensorValue * pulseRange /sensorRange=]
to:
[= (pulseWidth - minPulse) = (sensorValue - minsensorValue * pulseRange /sensorRange =]
Changed lines 106-109 from:
[=pulseWidth = ((sensorValue - minSensorValue) * pulseRange / sensorRange) + minPulse=]


to:
[= pulseWidth = ((sensorValue - minSensorValue) * pulseRange / sensorRange) + minPulse =]


Added lines 96-109:
Here's a a scaling formula that will make the adjustment:

[=(pulseWidth - minPulse) / pulseRange = (sensorValue - minSensorValue) /sensorRange =]

Multiply both sides by pulseRange, and you get:

[=(pulseWidth - minPulse) = (sensorValue - minsensorValue * pulseRange /sensorRange=]

Add the minimum pulse to both sides and you get:

[=pulseWidth = ((sensorValue - minSensorValue) * pulseRange / sensorRange) + minPulse=]


Changed lines 44-45 from:
to:
(:tableend:)
Added line 50:
Added lines 45-93:
!!! Program the Microcontroller

The following code will move the servo as the value of the sensor changes.

[@
/*
  Servo control from an analog input
 
 The minimum (minPulse) and maxiumum (maxPuluse) values
 will be different depending on your specific servo motor.
 Ideally, it should be between 1 and 2 milliseconds, but in practice,
 0.5 - 2.5 milliseconds works well for me.
 Try different values to see what numbers are best for you.
 
 */

int servoPin = 2;    // Control pin for servo motor
int minPulse = 500;  // Minimum servo position
int maxPulse = 2500;  // Maximum servo position
int pulse = 0;        // Amount to pulse the servo

int analogValue = 0;  // the value returned from the analog sensor
int analogPin = 0;    // the analog pin that the sensor's on

void setup() {
  pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
  pulse = minPulse;          // Set the motor position value to the minimum
  Serial.begin(9600);
}

void loop() {
  analogValue = analogRead(analogPin);      // read the analog input
  pulse = (analogValue / 10) * 19 + 500;    // convert the analog value
                                            // to a range between minPulse
                                            // and maxPulse.

  Serial.println(pulse, DEC);              // print it out for reference

  digitalWrite(servoPin, HIGH);  // Turn the motor on
  delayMicroseconds(pulse);      // Length of the pulse sets the motor position
  digitalWrite(servoPin, LOW);    // Turn the motor off
  delay(20);                      // 20 millisecond delay is needed between pulses 
                                  // to keep the servo in sync
}

@]

This code was written with a potentiometer in mind, so it assumes you're going to get values from 0 to 1023 from the sensor.  If you don't, the servo won't move through its whole range.    Determine the range of numbers the sensor is giving youm and adjust the servo formula to fit.

Changed line 37 from:
%alt='Schematic:Arduino connected to a servomotor' align=top height=300 valign=center%http://itp.nyu.edu/physcomp/images/labs/servo_sch.PNG
to:
%alt='Schematic:Arduino connected to a servomotor' align=top height=300 valign=center%http://itp.nyu.edu/physcomp/images/labs/servo_sch.png
Changed lines 36-37 from:
schematic
to:
Schematic:
%alt='Schematic:Arduino connected to a servomotor' align=top height=300 valign=center%http://itp.nyu.edu/physcomp/images/labs/servo_sch.PNG
Changed line 39 from:
%alt='Arduino connected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_servo.jpg
to:
%alt='Arduino connected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_servo.JPG
Changed lines 42-43 from:
%alt='Arduino Shieldconnected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_shield_servo.jpg
to:
%alt='Arduino Shieldconnected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_shield_servo.JPG
Changed lines 28-43 from:
[[<<]]
to:
[[<<]]

!!! Connect an analog input sensor and a servo

Pick any analog input and connect it to Analog pin 0 as you did in the [[Labs.AnalogIn|Analog Input and Output Lab]].  Then connect an RC servomotor to digital pin 2.  The yellow wire of the servo goes to the pin, and the red and black wires go to +5V and ground, respectively.

(:table:)
(:cellnr colspan=2:)
schematic
(:cellnr:)
Breadboard version:
%alt='Arduino connected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_servo.jpg
(:cell:)
Breadboard Shield version:
%alt='Arduino Shieldconnected to a servomotor' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/bboard_shield_servo.jpg

Changed line 16 from:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/servo.jpg | http://itp.nyu.edu/physcomp/images/labs/servo.jpg"servomotor"]] | [-RC Servomotor-]
to:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/servo.JPG | http://itp.nyu.edu/physcomp/images/labs/servo.JPG"servomotor"]] | [-RC Servomotor-]
Changed line 16 from:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg | http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg"servolotor"]] | [-RC Servomotor-]
to:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/servo.jpg | http://itp.nyu.edu/physcomp/images/labs/servo.jpg"servomotor"]] | [-RC Servomotor-]
Changed lines 12-13 from:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/potentiometer.jpg | http://itp.nyu.edu/physcomp/images/labs/potentiometer.jpg"potentiometer"]] | [-10Kohm potentiometer-]
Variable resistors
to:
Changed line 14 from:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg | http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg"potentiometer"]] | [-Flex sensors\\
to:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg | http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg"flex sensor"]] | [-Flex sensors\\
Added line 17:
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg | http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg"servolotor"]] | [-RC Servomotor-]
Changed lines 1-28 from:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor.
to:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor.

For this lab you'll need:

%lframe width=100px% [[http://itp.nyu.edu/physcomp/images/labs/breadboard.jpg | http://itp.nyu.edu/physcomp/images/labs/breadboard.jpg"Solderless breadboard"]] | [-Solderless breadboard-]
%lframe width=100px% [[http://itp.nyu.edu/physcomp/images/labs/hookup_wire.jpg | http://itp.nyu.edu/physcomp/images/labs/hookup_wire.jpg"hookup wire"]] | [-22-AWG hookup wire-]
%lframe width=100px% [[http://itp.nyu.edu/physcomp/images/labs/arduino.jpg | http://itp.nyu.edu/physcomp/images/labs/arduino.jpg"Arduino module"]] | [-Arduino Microcontroller \\
module-]
[[<<]]

%lframe width=100px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/resistors.jpg | http://itp.nyu.edu/physcomp/images/labs/resistors.jpg"resistors"]] | [-10Kohm resistors-]
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/potentiometer.jpg | http://itp.nyu.edu/physcomp/images/labs/potentiometer.jpg"potentiometer"]] | [-10Kohm potentiometer-]
Variable resistors
%lframe width=90px valign=center% [[http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg | http://itp.nyu.edu/physcomp/images/labs/flex_sensors.jpg"potentiometer"]] | [-Flex sensors\\
(or a different\\
 form of variable resistor)-]
[[<<]]

!!! Prepare the breadboard
Conect power and ground on the breadboard to power and ground from the microcontroller. On the Arduino module, use the 5V and any of the ground connections:

%alt='Arduino connected to a breadboard' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/arduino_bboard_power.jpg

If you're using an Arduino breadboard shield, there is a row of sockets connected to 5V on the analog in side of the breadboard, and a row connected to ground on the digital in side of the board:

%alt='Arduino breadboard shield' align=top valign=center%http://itp.nyu.edu/physcomp/images/labs/breadboard_shield.jpg

[[<<]]
Added line 1:
In this lab, you'll control a servomotor's position using the value returned from an analog sensor.
  Edit | View | History | Print | Recent Changes | Search Page last modified on March 17, 2014, at 07:53 AM