Servo write - variable

According to the official Arduino site:

Syntax
servo.write(angle)

Parameters

servo: a variable of type Servo

Is it possible to use a variable for the name of the servo, such that you can change servos by changing the content of the variable "servo" as used above?

If so, what sort of variable would it have to be?

What am I trying to do?

I would like to create several servos:

Servo myservo1; // create servo object to control a servo
Servo myservo2; // create servo object to control a servo
Servo myservo3; // create servo object to control a servo
Servo myservo4; // create servo object to control a servo

and use a variable in the statement

variable.write(angle)

such that I can switch servos by changing the content of the variable from myservo1 to myservo2, etc.

Is this possible?

You could do it with a pointer-to-Servo.

You could create an array of servos

Please, tell us if it worked

As mentioned, an array of servos.

Some completely untested code that illustrates the process

#include <Servo.h>
const int NumServos = 4;
Servo ServoArray[NumServos];
int ServoPins[NumServos] = {7, 8, 9, 10};

void setup() {
  // put your setup code here, to run once:
  for (int i = 0; i < NumServos; i++)
    ServoArray[i].attach(ServoPins[i]);
}

void loop() {
  // put your main code here, to run repeatedly:
  for (int i = 0; i < NumServos; i++)
  {
    for (int j = 0; j < 180; j++)
    {
      ServoArray[i].write(j);
      delay(20);
    }
  }
}

I am trying this, but it does nothing? Not even an error.

I edited it to take a 5 number string, and parse it to 2 and 3 length. That part works correctly. Then I try to use the write command to make the servo move to the number of degrees of n2, being the 3 digit parse.

No movement. :o

// zoomkat 12-13-11 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 1.0
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550
// use serial monitor to test

#include <Servo.h> 
String readString, servoname, servo2;

Servo mys[8]; //Now we have 8 servos


void setup() {
  Serial.begin(9600);
  for(int i=0; i<8; i++)
{
   mys[i].attach(i+2);
}
 
  Serial.println("two-servo-test-1.0"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(3);  //delay to allow buffer to fill 
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
      Serial.println(readString); //see what was received
      
      // expect a string like 07002100 containing the two servo positions      
      servoname = readString.substring(0, 2); //get the first two characters name
      servo2 = readString.substring(2, 5); //get the next three characters 
      
      Serial.println(servoname);  //print to serial monitor to see parsed results
      Serial.println(servo2);

      int n1 = servoname.toInt();
      int n2 = servo2.toInt();

      Serial.println("the numbers are :");
      Serial.println(n1);  //print to serial monitor to see number results
      Serial.println(n2);
            
      mys[n1].write(n2); //set servo position 

    readString="";
  } 
}

What does it print?

It correctly prints out

8
180

if I enter 08180

That should write 180 position to servo pin 8. Or so it should if I do it correctly.

That should write 180 position to servo pin 8.

Pin 10, I think.

Edit: you don't have a servo 8, only 0 to 7, on pins 2 to 9

:slight_smile:
Yes, thank you very much for figuring that out.

Here's another version, with the servo numbers lining up with the pin numbers

// zoomkat 12-13-11 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 1.0
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550
// use serial monitor to test

#include <Servo.h> 
String readString, servoname, servo2;

Servo mys[18]; //Now we have 18 servos


void setup() {
  Serial.begin(9600);
  for(int i=2; i<18; i++)
{
   mys[i].attach(i); // was i+2
}
 
  Serial.println("two-servo-test-1.0"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(3);  //delay to allow buffer to fill 
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
      Serial.println(readString); //see what was received
      
      // expect a string like 07180 containing the servo position and degrees      
      servoname = readString.substring(0, 2); //get the first two characters name
      servo2 = readString.substring(2, 5); //get the next three characters 
      
      Serial.println(servoname);  //print to serial monitor to see parsed results
      Serial.println(servo2);

      int n1 = servoname.toInt();
      int n2 = servo2.toInt();

      Serial.println("the numbers are :");
      Serial.println(n1);  //print to serial monitor to see number results
      Serial.println(n2);
            
      mys[n1].write(n2); //set servo position 

    readString="";
  } 
}

  for(int i=2; i<18; i++)How many servos?

You get servos at pins 2-17 with that number entered. I've been playing around with it and it seems positions 00 and 01 don't work properly. They are assigned to TX and RX on the mega and that might be why. Also pins 20 and 21 are assigned to SDA and SCL and don't work either. So that currently leaves me with 17 working servos. Should be good.

I plan to feed the serial data to the board using a usb cable to a Rasp Pi and node red's dashboard to feed the serial inputs.

I am currently running my robot project using firmata on the mega to communicate with the Pi, but I'm not entirely satisfied with that, as when you run firmat a , you can't run any other code on the Arduino. That's limiting. I have found that ping sensors work fantastic on the Arduino, very accurate and reliable, but no so good on the Rasp Pi. So, now I can run code on the Arduino again.

You get servos at pins 2-17 with that number entered.

How many simultaneous servos does the Servo library support ?

This method may be superior.

[code]

// Example 5 - Receive with start- and end-markers combined with parsing

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
int firstIntegerFromPC = 0;
int secondIntegerFromPC = 0;
// int floatFromPC = 0.0;

boolean newData = false;

// my servo addition

#include <Servo.h> 
Servo mys[20]; //Now we have 20 servos but only use 2-19 (ie 18 servos)

//

//============

void setup() {
    Serial.begin(9600);
    Serial.println("This demo expects 2 pieces of data - two integers");
    Serial.println("Enter data in this style <1, 180>  ");
    Serial.println();
    // my addition
      for(int i=2; i<20; i++)
{
   mys[i].attach(i); // was i+2
}
 // end my addition
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        servoMove();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    // tim comments out strcpy(firstIntegerFromPC, strtokIndx); // copy it to firstIntegerFromPC
    firstIntegerFromPC = atoi(strtokIndx); // my addition convert first part to an integer
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    secondIntegerFromPC = atoi(strtokIndx);     // convert this part to an integer

   // Tim comments out strtokIndx = strtok(NULL, ",");
  //  Tim comments out floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
    Serial.print("Servo Number ");
    Serial.println(firstIntegerFromPC);
    Serial.print("Degrees movement ");
    Serial.println(secondIntegerFromPC);
    // Serial.print("Float ");
   // Serial.println(floatFromPC);

}
void servoMove() {
   // start my addition
  mys[firstIntegerFromPC].write(secondIntegerFromPC); //write servo position 
   // end my addition
   }

[/code]

Servo mys[20]; //Now we have 20 servos but only use 2-19 (ie 18 servos)
...
 for(int i=2; i<20; i++)

How many servos?

I can make 18 work on the mega. Maybe more is possible.

So why confuse things and define 20 servos, but only attach 18?

How does it number the servos when I define them by

servo mys[20]

Does it start at zero so that its defining a servo named mys0-my19?

I wasn't sure how that works. Pin 0 and 1 don't seem to work, not that the pin number has to coincide with the servo number, but I would prefer it did. Can I start mys[20] somehow on #2 so I don't define a 0 and 1 and can still have pin # and servo # coincide?

Thanks for all your help. What you have to endure to help some of us!

The servo array knows nothing about the pins you're going to attach its elements to.
Arrays always index from zero, so if you want to attach servo element zero to pin two, you can either loop from zero, and add two to the index to give the pin, or iterate from two and subtract two to give the servo element.

Personally, for flexibility, I would always have an array of pin numbers to match the number of elements in the servo array.