Multiple servo control

I have been playing with servos, I can get the example programs to run single servos. Now I am trying to control multiple servos (and other stuff) via a serial link with my computer. Most everything else works but I am struggling to get the servo code to behave.

What happens is that more than one servo moves when I send positional data. Perhaps I have some thing fundamentally wrong. Can I attach() on the fly? I don't have detach() yet as I simply turn off the board.

I tried time delays on the few pins I am testing.

I first send "setPin pin 2" this attaches the pin and seems to work. Then I send "turn pin degree", works for one servo but if I attach another both servos move, it seems that if I turn the highest pin servo it moves uniquely but lower pins turn both servos.

Know you wont be able to test but its probably something fundamental I have wrong, have I got things in the right place?

And yes I am a complete novice running before he can walk :slight_smile:

#include <Servo.h>

Servo servo0;  // create servo objects to control a servo
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;
Servo servo6;
Servo servo7;
Servo servo8;
Servo servo9;
Servo servo10;
Servo servo11;
Servo servo12;
Servo servo13;

// Buffer to store incoming commands from serial port
String inData;

void setup() {
  Serial.begin(9600);
  Serial.println("Serial conection started, waiting for instructions...");
}

void loop() {
  while (Serial.available() > 0)
  {
    char recieved = Serial.read();
    inData += recieved;

    // Process message when new line character is recieved
    if (recieved == '\n')
    {
      String Param0 = getValue(inData, ' ', 0);
      String Param1 = getValue(inData, ' ', 1);
      String Param2 = getValue(inData, ' ', 2);
      String Param3 = getValue(inData, ' ', 3);
      String Param4 = getValue(inData, ' ', 4);
      String Param5 = getValue(inData, ' ', 5);

      inData = "";

      int valParam0 = Param0.toInt();
      int valParam1 = Param1.toInt();
      int valParam2 = Param2.toInt();
      int valParam3 = Param3.toInt();
      int valParam4 = Param4.toInt();
      int valParam5 = Param5.toInt();


      //Serial.print(valParam0);
      //Serial.print(valParam1);
      //Serial.print(valParam2);
      //Serial.print(valParam3);
      //Serial.print(valParam4);
      //Serial.print(valParam5);


      if ( Param0 == "setPin")
      { 
        if (valParam2 == 0)
        { 
          pinMode(valParam1, INPUT);
        }
        if (valParam2 == 1)
        {
          pinMode(valParam1,OUTPUT);
        }
        if (valParam2 == 2)
        {
 
          switch (valParam1) {
 
          case 0:
 
          servo0.attach(0);
          
          case 1:
 
          servo1.attach(1);
 
          case 2:
 
          servo2.attach(2);
 
          case 3:
 
          servo3.attach(3);
 
          case 4:
 
          servo4.attach(4);
 
          case 5:
 
          servo5.attach(5);
 
          case 6:
 
          servo6.attach(6);
 
          case 7:
 
          servo7.attach(7);

          case 8:
 
          servo8.attach(8);
  
          case 9:
 
          servo9.attach(9);
 
          case 10:
 
          servo10.attach(10);
 
          case 11:
 
          servo11.attach(11);
 
          case 12:
 
          servo12.attach(12);
 
          case 13:
 
          servo13.attach(13);
          }
        }
      }
      
      if ( Param0 == "get")
      {
        Serial.println(digitalRead(valParam1));
      }

      if ( Param0 == "set")
      {
        digitalWrite(valParam1, valParam2);
      }


      if ( Param0 == "pwm")
      {
        analogWrite(valParam1, valParam2);
      }


      if ( Param0 == "getA")
      {
        Serial.println(analogRead(valParam1));
      }


      if ( Param0 == "turn")
      {
 
          switch (valParam1) {
 
          case 0:
 
          servo0.write(valParam2);
          
          case 1:
 
          servo1.write(valParam2);
 
          case 2:
 
          servo2.write(valParam2);
 
          case 3:
 
          servo3.write(valParam2);
 
          case 4:
 
          servo4.write(valParam2);
 
          case 5:
 
          servo5.write(valParam2);
 
          case 6:
 
          servo6.write(valParam2);
 
          case 7:
 
          servo7.write(valParam2);

          case 8:
 
          servo8.write(valParam2);
  
          case 9:
 
          servo9.write(valParam2);
          delay(15);
 
          case 10:
 
          servo10.write(valParam2);
          delay(15);
 
          case 11:
 
          servo11.write(valParam2);
 
          case 12:
 
          servo12.write(valParam2);
          delay(15);
 
          case 13:
 
          servo13.write(valParam2);
          }
        }

    }
  }
}




String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {
    0, -1
  };
  int maxIndex = data.length() - 1;
  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++;
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

Once attached, do you ever detach the servo ?

Do I detach() the servo? Not yet, I am just at the stage of attaching() the first then the second and trying to turn them, detach will come later. Right now I believe I should be able to attach() pins as and when needed and send them write() commands. I know that the servo library will disable PWM on other pins until all have been detached but I'm not there yet.

I have two servos linked on pins nine and ten. I am using the linker shield and a short piece of their four link wire that feeds ground +ve and separate signals to the servos. I have the board powered by a 5v supply and my power link set to external.

When you find yourself with fourteen variable differing only by a numeric suffix, it's time to look at using arrays.

Your switch/case commands need a break; after each case to avoid the program falling through to the next case.

See switch/case

it's time to look at using arrays

If I only I knew how, but its day 2 and I'm sure I'll get there.

avoid the program falling through to the next case.

Thanks, knew it would be something fundamental, off to read your link.

Solved, thank you very much, completely independent servo movement, next stop arrays()

Test code for multiple servos.

//zoomkat 11-22-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 
// Powering a servo from the arduino usually *DOES NOT WORK*.

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

Thanks zoomkat. I am trying to set pins on the fly to either input, output or servo. So I think I need to understand how to replace the myservoa. servo variable with an array alternative. Like myservo[n].attach(n)

Wow, I wrote the solution and didn't know it, arrays are easier than I thought, this with the help of some friends.

#include <Servo.h>
// set up 14 servo objects in an array
Servo myservos[14] ;


// Buffer to store incoming commands from serial port
String inData;

void setup() {
  Serial.begin(9600);
  Serial.println("Serial conection started, waiting for instructions...");
} 

void loop() {
  while (Serial.available() > 0)
  {
    char recieved = Serial.read();
    inData += recieved;

    // Process message when new line character is recieved
    if (recieved == '\n')
    {
      String Param0 = getValue(inData, ' ', 0);
      String Param1 = getValue(inData, ' ', 1);
      String Param2 = getValue(inData, ' ', 2);
      String Param3 = getValue(inData, ' ', 3);
      String Param4 = getValue(inData, ' ', 4);
      String Param5 = getValue(inData, ' ', 5);

      inData = "";

      int valParam0 = Param0.toInt();
      int valParam1 = Param1.toInt();
      int valParam2 = Param2.toInt();
      int valParam3 = Param3.toInt();
      int valParam4 = Param4.toInt();
      int valParam5 = Param5.toInt();

      if ( Param0 == "setPin")
      { 
        if (valParam2 == 0)
        { 
          pinMode(valParam1, INPUT);
        }
        if (valParam2 == 1)
        {
          pinMode(valParam1,OUTPUT);
        }
        if (valParam2 == 2)
        {
           myservos[valParam1].attach(valParam1);
        }
      }
      
      if ( Param0 == "get")
      {
        Serial.println(digitalRead(valParam1));
      }

      if ( Param0 == "set")
      {
        digitalWrite(valParam1, valParam2);
      }


      if ( Param0 == "pwm")
      {
        analogWrite(valParam1, valParam2);
      }


      if ( Param0 == "getA")
      {
        Serial.println(analogRead(valParam1));
      }


      if ( Param0 == "turn")
      {
      myservos[valParam1].write(valParam2) ;
        }

    }
  }
}




String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {
    0, -1
  };
  int maxIndex = data.length() - 1;
  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++;
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

Detach[] and possibly pwm timing input next.