Using Multiple Servos with Arduino

jmichael26:
hi! how to program it if i'll be needing more than 2 servo motors? thanks

Zoomcat's code in reply #6 shows 4 servos already, on pins 6, 7, 8 and 9.

ahh but what if i'll be using 14 servos ?

Well you'll need an Arduino with 14 spare digital pins. Uno has 20 pins if you count the analogs, but lose 2 for Tx Rx leaves you a theoretical 18. Mega has dozens more .

I'm not sure if there's an absolute maximum that the servo library can handle though, sorry.

my friend told me that i need to use sevo drivers to accomodate those servos. but i'm just worried about its program . please help me

JimboZA:
Well you'll need an Arduino with 14 spare digital pins. Uno has 20 pins if you count the analogs, but lose 2 for Tx Rx leaves you a theoretical 18. Mega has dozens more .

I'm not sure if there's an absolute maximum that the servo library can handle though, sorry.

but how is the program if i'll be using 14 servos? just copy paste your #6 program? thanks

zoomkat:
Several servo control code.

//zoomkat 11-22-12 simple delimited ',' string parse 

//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added

String readString;
#include <Servo.h>
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo

void setup() {
  Serial.begin(9600);

//myservoa.writeMicroseconds(1500); //set initial servo position if desired

myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

//expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

int n = readString.toInt();  //convert readString into a number

// auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        { 
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
        readString=""; //clears variable for new input
      }
    } 
    else {   
      readString += c; //makes the string readString
    }
  }
}

Sorry, i have an question for this code.
How these servo run, what is control it ? I found pins 6,7,8,9 in arduino connect to servo but I didn't find pin that receive order control servo from other part like varistor...
Thanks !

How these servo run, what is control it ? I found pins 6,7,8,9 in arduino connect to servo but I didn't find pin that receive order control servo from other part like varistor...

You send data to the Arduino, from the Serial Monitor application, to control the servos:

          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);

like varistor..

Can you explain just what the "varistor" is?

Hello to everyone.I have 6 servos and Arduino Uno.The connection that i make is 3,5,6,9,10,11(all the PWM of Arduino).It will be a problem?Thanks in advance.

jack1992:
Hello to everyone.I have 6 servos and Arduino Uno.The connection that i make is 3,5,6,9,10,11(all the PWM of Arduino).It will be a problem?Thanks in advance.

Servos are NOT driven using PWM (the way Arduino does it), so there is no need to use just PWM pins.

PaulS:
Servos are NOT driven using PWM (the way Arduino does it), so there is no need to use just PWM pins.

ok thank you sir

I am trying to use 2 servos but it is not working. When I connect only one servo, it works properly. When I connect the second servo, both servos get very erratic and after a few movements they drive to a limit and stay there. If I disconnect one servo control wire, the remaining servo acts normally again.

I initially tried this on a Diecemilia and thought maybe it was caused by an old board. I swapped out for an Uno but get the same result.

Servos are powered by an external 5V power supply; ground of power supply connected to Uno and servos.

The code is as simple as I could get, just trying to get the system to work.

#include <Servo.h>

Servo sideservo, forwardservo;  // create servo object to control a servo

void setup() {
  sideservo.attach(9);
  forwardservo.attach(10);  
}

void loop() { // minimal movement to avoid damage to system
  sideservo.write(60);
  delay(1000);
  forwardservo.write(80);
  delay(1000);
  sideservo.write(90);
  delay(1000);
  forwardservo.write(100);
  delay(1000);
}

Any idea what is going on here?

Any idea what is going on here?

Without knowing how you powered the servos? No. I'd guess, though, that you are expecting the Arduino to power and control the servos. That is not going to happen. It can CONTROL the servos. It can NOT power the servos.

Hi all, new to the forum here, 1st post and all that....

Being a noobie and all that, I was just messing with this last week.

redbird:
Servos are powered by an external 5V power supply; ground of power supply connected to Uno and servos.

The code is as simple as I could get, just trying to get the system to work.

Any idea what is going on here?

Try disconnecting the ground of your power supply from the Uno. It really shouldn't matter, but I've had the same problems you're having.

My servos are connected to a power supply that's not connected to the arduino, the only connection with the arduino from the servos is the PWM wire. In my case, I'm using 4xAA batteries to power the servos, and a 9v battery to power the arduino.

When I powered one servo from an arduino, it worked fine. When I tried two, it became erratic. The main green LED on the arduino would dim, then the arduino would reboot.

Now that I have 2 power supplies, not connected in any way, it works.

Randy

When you set servos to go directly to certain positions the shaft is moving very quickly and so there can be a lot of skip ups (I know this because I've been messing with this myself recently). A better way of doing it without putting a lot of wear and tear on the servos is using a for loop to gradually get the servo to the position you want. In this way you don't get sudden jerks but a smooth transition to the angle you want.

*I posted this before I realized the code on page one already existed. this is a much less elegant solution.this program would be simpler if i used commas in the command protocol.
however, this program 'steps' to the commanded value. so the servo sweeps into position with +1 or -1 steps. this may smooth out the servo movement.

here is a program i have to control 4 servos simultaneously from the serial console. feel free to improve the code as you see fit.
Here is a video of it in action: Control multiple servos simultaneously in Arduino - YouTube
This is for use with the serial console or you can change values from an input device, sensor, etc

//This will control 4 servos using a single command. 
//The command structure is a string of 12 characters Received on the serial port. DO NOT use line feed or carriage return (NL CR)
//if you send 000000000000 the motors will Detach and be free moving.

//3 Digits per servo * 4 Servos = 12 digits
//S1    S2   S3   S4
//000 000 000 000

//for example: 180180180180 would send EACH moter to move to 180. also, 001001001001 would send EACH motor to to 1.
//If you dont want a servo to change position send it a 000. so to move ServoB ONLY to 125 you would send 000125000000
// just change the PosX value to change position without serial command i.e. posA = 90 or posD = 1.
 
#include <Servo.h>
#define debug 1 //set debug to 0 if you dont want feedback. (Saves code space, increases program speed)
#define servoApin 2 //Hardware Configuration Servo Control Pin.
#define servoBpin 4
#define servoCpin 5
#define servoDpin 3

#define  posAstart 150 //estimated servo location on powerup
#define  posAmin 100 //minimum allowed 'angle' (must be at least 1)
#define  posAmax 180 //maximum allowed 'angle' (must be 180 max)

#define  posBstart 90 
#define  posBmin 30 
#define  posBmax 150 

#define  posCstart 90
#define  posCmin 1 
#define  posCmax 180

#define  posDstart 90
#define  posDmin 1 
#define  posDmax 180

int servoACompleted = 1;
int servoBCompleted = 1;
int servoCCompleted = 1;
int servoDCompleted = 1;

String SreadString="";
String posAString, posBString, posCString, posDString;

int posA = posAstart;
int posB = posBstart;
int posC = posCstart;
int posD = posDstart;

int storedPosA = posAstart; //guestimate of rest 
int storedPosB = posBstart; //guestimate of rest
int storedPosC = posCstart; //guestimate of rest 
int storedPosD = posDstart; //guestimate of rest

Servo servoA;  // forward and backwards on pin 2
Servo servoB; //side to side on pin 4
Servo servoC; //blank on pin 5
Servo servoD;  //mouth on pin 3

void setup() {
Serial.begin(9600);
}

void loop() {
ReadSerialPort();                //read the entire serial port buffer
CheckIfStopCommand();   //check if "000000000000" string was sent to DETACH ALL Servos
SerialdataToVariables();    //this has no error checking control so make sure you send the proper data
UpdateServos();                 //This function must be called as fast as possible.
Feedback();                       //this function can be removed if you dont need feedback. or changed for custom feedback

} //end loop



void ReadSerialPort(){  
while (Serial.available()) { //builds up read string from serial buffer/ at this point its expects 12 digits
char c = Serial.read();  //gets one byte from serial buffer
SreadString += c; //makes the string SreadString
delay(2);  //slow looping to allow buffer to fill with next character
}
}


void CheckIfStopCommand(){
if(SreadString == "000000000000"){ // all servos DETACH
 if(debug ==1){
 Serial.println(SreadString); // DEBUGGING
 Serial.println("ALL Servos Detached"); // DEBUGGING
  }
servoA.detach();  // 
servoB.detach();  // 
servoC.detach();  //
servoD.detach();  // 
SreadString =""; //this clears the string
}
}


void SerialdataToVariables(){
if (SreadString.length() > 0) { //this is messy but it is a way to strip the ascii string from serial port to 4 seperate 3 digit values and remove any leading zeros
//protocol order is posA - posB - posC -posD
 posAString = SreadString;  //store the RXed string into 4 seperate strings
 posBString = SreadString;
 posCString = SreadString;
 posDString = SreadString;
 posAString.remove(3,9); //parse the desired 3 digits from each string
 posBString.remove(0,3); 
 posBString.remove(3,6);
 posCString.remove(0,6); 
 posCString.remove(3,3);
 posDString.remove(0,9);   
 posA = posAString.toInt(); //convert to ints that have leading zeros ( 000 to 999 )
 posB = posBString.toInt();
 posC = posCString.toInt();
 posD = posDString.toInt();
 if(posA<100) posAString.remove(0,1); //remove the leading zeros
 if(posA<010) posAString.remove(0,1);
 if(posB<100) posBString.remove(0,1);
 if(posB<010) posBString.remove(0,1);
 if(posC<100) posCString.remove(0,1);
 if(posC<010) posCString.remove(0,1);
 if(posD<100) posDString.remove(0,1);
 if(posD<010) posDString.remove(0,1);
 posA = posAString.toInt(); //posX are now your integer command values (0 to 999)
 posB = posBString.toInt();
 posC = posCString.toInt();
 posD = posDString.toInt();
 if(debug == 1){ //debug option
Serial.print("Data received: ");
Serial.println(SreadString); // DEBUGGING
Serial.print("Int posA: ");
Serial.println(posA); // DEBUGGING
Serial.print("Int posB: ");
Serial.println(posB); // DEBUGGING
Serial.print("Int posC: ");
Serial.println(posC); // DEBUGGING
Serial.print("Int posD: ");
Serial.println(posD); // DEBUGGING
}
SreadString=""; //empty for next input
}
}

void UpdateServos(){
 if(posA>posAmin-1 && posA<posAmax+1){ // if within min and max 
 if(storedPosA>posA){ //if stored position is greater than commanded position
 servoACompleted = 0;
 storedPosA--;
 servoA.attach(servoApin);
 servoA.write(storedPosA); 
 delay(1);
 }
 if(storedPosA<posA){ //if stored position is less than commanded position
 servoACompleted = 0;
 storedPosA++;
 servoA.attach(servoApin);
 servoA.write(storedPosA); 
 delay(1);
 }  
 }


if(posB>posBmin-1 && posB<posBmax+1){
if(storedPosB>posB){ //if stored position is greater than commanded position
servoBCompleted = 0;
storedPosB--;
servoB.attach(servoBpin);
servoB.write(storedPosB);
delay(1);
}
if(storedPosB<posB){ //if stored position is less than commanded position
servoBCompleted = 0;
storedPosB++;
servoB.attach(servoBpin);
servoB.write(storedPosB);
delay(1);
}  
}

if(posC>posCmin-1 && posC<posCmax+1){
if(storedPosC>posC){ //if stored position is less than commanded position
servoCCompleted = 0;
storedPosC--;
servoC.attach(servoCpin);
servoC.write(storedPosC);
delay(1);
}
if(storedPosC<posC){ //if stored position is greater then commanded position
servoCCompleted = 0;
storedPosC++;
servoC.attach(servoCpin);
servoC.write(storedPosC);
delay(1);
}  
}

 if(posD>posDmin-1 && posD<posDmax+1){ // if within min and max 
 if(storedPosD>posD){ //if stored position is greater than commanded position
 servoDCompleted = 0;
 storedPosD--;
 servoD.attach(servoDpin);
 servoD.write(storedPosD); 
 delay(1);
 }
 if(storedPosD<posD){ //if stored position is less than commanded position
 servoDCompleted = 0;
 storedPosD++;
 servoD.attach(servoDpin);
 servoD.write(storedPosD); 
 delay(1);
 }  
 }

}

void Feedback(){
if(debug == 1){
 if(storedPosA==posA && servoACompleted == 0){
 Serial.println("ServoA Done"); // DEBUGGING
 servoACompleted = 1;
 }
 if(storedPosB==posB && servoBCompleted == 0){
   Serial.println("ServoB Done"); // DEBUGGING
   servoBCompleted = 1;
 }
 if(storedPosC==posC && servoCCompleted == 0){
  Serial.println("ServoC Done"); // DEBUGGING
  servoCCompleted = 1;
 }
 if(storedPosD==posD && servoDCompleted == 0){
  Serial.println("ServoD Done"); // DEBUGGING
  servoDCompleted = 1;
}  
}
}

im using flysky th9x reciver... i cant use 2 servo same time ...this srvo is for pen tilt camer ..only 1 servo working properly...

void Servo_Control1(){
int Pos1;
inputPina = pulseIn(42, HIGH, 25000); // /Servo 2
Pos1 = map(inputPina, 1000, 2000, 0, 180); //center over zero
Pos1 = constrain(Pos1, 0, 170);

totala = totala - readingsa[readIndexa];
readingsa[readIndexa] = Pos1;
totala = totala + readingsa[readIndexa];
readIndexa = readIndexa + 1;
if (readIndexa >= numReadingsa) {
// ...wrap around to the beginning:
readIndexa = 0;
}

averagea = totala/ numReadingsa;
Serial.println(averagea);
myservo1.write(averagea);
delay(1);
}

void Servo_Control2(){
int Pos2;

inputPinb = pulseIn(44, HIGH, 25000); // /Servo 2
Pos2 = map(inputPinb, 1000, 2000, 0, 180); //center over zero
Pos2 = constrain(Pos2, 0, 170);

totalb = totalb - readingsb[readIndexb];
readingsb[readIndexb] = Pos2;
totalb = totalb + readingsb[readIndexb];
readIndexb = readIndexb + 1;
if (readIndexb >= numReadingsb) {
// ...wrap around to the beginning:
readIndexb = 0;
}

averageb = totalb / numReadingsb;
Serial.println(averageb);
myservo2.write(averageb);
delay(1);
}

i cant use 2 servo same time

I do. Why can't you?

The snippet of code you posted does something, in addition to wasting code space. You only need ONE function. That function can take arguments, like which pin number to read from, which index into a 2D array (for the readings) and which Servo instance to write to.

You need to explain EXACTLY what the code does, EXACTLY how the servos are connected and powered, etc.

I used the code from post 6 on this thread. My issue is I want to write an app in visual studio using a trackbar/scrollbar to control each servo.

here is my code on the trackbar:

private void val_trackBar_Scroll(object sender, EventArgs e)
{
try
{
myport.Write(val_trackBar.Value.ToString() + 'a');

Degree_label.Text = "Degree = " + val_trackBar.Value.ToString();
}

catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}

In the previously posted code as far as I can understand, I must use the letter 'a' within my C# writeLine so the Arduino can pick up on which servo I am addressing and move it as requested....

It does not work :frowning: I can get a single servo to work fine using a different sketch on the Arduino but I need to be able to use more than one.

any help would be much appreciated.

Here is the full c# code:

namespace Arduino_test
{
public partial class frm_Robot : Form
{

private SerialPort myport;

public frm_Robot()
{
InitializeComponent();
}

private void start_btn_Click(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = port_name_tb.Text;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;

try
{
myport.Open();
MessageBox.Show("Connected to Servo");
}

catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}

private void val_trackBar_Scroll(object sender, EventArgs e)
{
if (myport.IsOpen)
{
myport.WriteLine(val_trackBar.Value.ToString() + 'a');
Degree_label.Text = "Degree = " + val_trackBar.Value.ToString();
}
}

private void trackBar1_Scroll(object sender, EventArgs e)
{
if (myport.IsOpen)
{
myport.WriteLine(val_trackBar.Value.ToString() + 'b');
Degree_label1.Text = "Degree = " + val_trackBar.Value.ToString();
}
}

private void trackBar2_Scroll(object sender, EventArgs e)
{
if (myport.IsOpen)
{
myport.WriteLine(val_trackBar.Value.ToString() + 'c');
Degree_label2.Text = "Degree = " + val_trackBar.Value.ToString();
}
}

private void btn_stop_Click(object sender, EventArgs e)
{
try
{
myport.Close();
MessageBox.Show("Disconnected From Servo");
this.Close();
}

catch (Exception ex2)
{
MessageBox.Show(ex2.Message, "Error");
}
}

private void port_name_tb_TextChanged(object sender, EventArgs e)
{

}

private void frm_Robot_Load(object sender, EventArgs e)
{
MessageBox.Show("Enter a port number (eg: COM1), click connect, dont forget to Click disconnect before closing the window.");
}
}
}

The Arduino code in reply 6 does nothing until a comma is encountered. Where do you send a comma to the serial port?