Servo motor control in Arduino

This example controls a servomotor. It moves a servomotor based on the value of an analog input. Thanks to Casey Reas for cleaning up the code. Thanks to Henryk Marstrander for the formula.


/*
  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
 */

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 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);
}

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. 

  // 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
  }
}

Here’s a version that controls two servos. Note that you have to reduce the refresh time to compensate for the pulse times of the servos as you add more servos. Thanks to Carlyn Maw for the update.

/*
  Two-servo control from an analog input

  Moves two servos based on the value of one analog sensor, 
  in  opposite directions.

  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.

  by Tom Igoe
  Created 28 Jan. 2006
  Repurposed for Dual Servos by Carlyn Maw
  24 Mar. 2006
*/

int servoPinL = 2;     // Control pin for servo motor - L
int servoPinR = 3;     // Control pin for servo motor - R
int minPulse = 500;   // Minimum servo position
int maxPulse = 2500;  // Maximum servo position
long adjustedAV = 0;  // Analog value adjusted for determining pulse values
int pulseL = 0;        // Amount to pulse the servoL
int pulseR = 0;        // Amount to pulse the servoR
int delayValueMax = 20000;  // the 20 microsecond maxiumum pulse range for the servo
int delayValue = 20000;    // the actual value the code should wait, determined later

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

void setup() {
  pinMode(servoPinL, OUTPUT);  // Set servo pins as an output pins
  pinMode(servoPinR, OUTPUT);
  pulseL = minPulse;           // Set the motor position values to the minimum
  pulseR = maxPulse;
}

void loop() {
  analogValue = analogRead(analogPin);      // read the analog input (0-1024)
  adjustedAV = (analogValue / 10) * 19;     // convert the analog value to a number
                                            // between 0-2000 (difference between min and max)

  pulseL = adjustedAV + minPulse;           // set value for left motor
  pulseR = maxPulse - adjustedAV;           // and the inverse for the right

  digitalWrite(servoPinL, HIGH);     // Turn the L motor on
  delayMicroseconds(pulseL);         // Length of the pulse sets the motor position
  digitalWrite(servoPinL, LOW);      // Turn the L motor off

  digitalWrite(servoPinR, HIGH);     // Turn the R motor on
  delayMicroseconds(pulseR);         // Length of the pulse sets the motor position
  digitalWrite(servoPinR, LOW);      // Turn the R motor off

  delayValue = (delayValueMax - pulseL) - pulseR; // determine how much time you have before the 20 ms is over...
  delayMicroseconds(delayValue);                  // 20 millisecond delay is needed between pulses
                                                  // to keep the servos in sync
}