How do I use obects in functions and numerate them?

Hi folks,
as I’m not so familiar with object coding I’d like to ask questions.

I’d like to use an array to control several servos but want to “automate” the
setup.

And I want to control several servos using an rotary encoder depending on a selection
using momentary switches. As the routine is always the same for each servo, I’d like
to write a function.

So here some pseudo code to show what I think of:

#include <Servo.h>
#include <RotaryEncoder.h>

// servodata contains 1. servoobject number, 2. pin where connected, 3. angle to drive to
int servodata={
1,10,45,
2,11,30,
3,12,61
};

// using a counter to set the servos. Here number should be used to name the object
void setup() {

	for (number=1; number < 3; number+=3){

            servo-number.attach(number+1);  //read as servo1.attach(10);
           servo-number.write(servodata[number+2]; // read as servo1.write(45);
	}
  Serial.println("Setup complete");
  delay(500);
}

// here the number of the momentary switch should be used to select the object
void loop() {

	momentary=read switch;

	switch(momentary){
// here a function should be called where other operation are done (for each servo the same)
		case 1 : controlServo( servo-momentary ); break; // read as controlServo(servo1)
		case 2 : controlServo( servo-momentary ); break;
		default;
        }
}

int controlServo( ChosenServo ){
... read rotary...
... ChosenServo.write...
return(1);
}

Some advice on how to combine the name of the servo object with a number and how to
consign a (numbered)object would be appreciated.

So, multiple servo’s and multiple pins to move them?

For the servo part:

const byte ServoPins[] = {10, 11, 12};
const byte NrServos = sizeof(SevoPins);
byte servoAngles[NrServos] = {45, 30, 61};
Servo myServos[NrServos];

Now you can just iterate over them as you like.

You could also make a struct but I think this is also fine.

And you can extend that to the buttons:

const byte ButtonPins[NrServos] = {3, 4, 5};

And if you want to press a button to “select” a servo you need to store which button was pressed last. For example

#include <Bounce2.h> // like to use Bounce2 litbrary for buttons
const byte ButtonPins[NrServos] = {3, 4, 5};

Bounce buttons[NrServos];
byte servoSelected = 0;

void setup(){
  for(byte i = 0; i < NrServos; i++){
    buttons[i].attach(ButtonPins[i], INPUT_PULLUP);
  }
}

void loop(){
  for(byte i = 0; i < NrServos; i++){
    buttons[i].update();
    if(buttons[i].fell()){
      servoSelected = i;
    }
  }
}

A struct implementation might look like this:

#include <Servo.h>

//servo information structure definition
//typedef allows us to create a variable of this type

#define NUM_SERVOS      3
Servo   servoOne;
Servo   servoTwo;
Servo   servoThree;

typedef struct
{
    Servo           servoObject;
    byte            pinServo;
    int             servoAngle;

}struct_ServoInfo;

struct_ServoInfo ServoInfo[NUM_SERVOS] = 
{
    {
        //servo object one
        .servoObject = servoOne,
        .pinServo = 10,
        .servoAngle = 45    
    },
    {
        //servo object two
        .servoObject = servoTwo,
        .pinServo = 11,
        .servoAngle = 30    
    },
    {
        //servo object three
        .servoObject = servoThree,
        .pinServo = 12,
        .servoAngle = 61    
    }
    
};

void setup() 
{
    Serial.begin(9600);
    for( int i=0; i<NUM_SERVOS; i++ )
    {
        ServoInfo[i].servoObject.attach( ServoInfo[i].pinServo );
        ServoInfo[i].servoObject.write( ServoInfo[i].servoAngle ); 
        
    }//for
    
}//setup

void loop( void )
{
    //...
    
}//loop

Blackfin:
A struct implementation might look like this:

Why create 6 Servo objects when you only need 3?

gfvalvo:
Why create 6 Servo objects when you only need 3?

A fair question. Perhaps the struct member could be a pointer to the already-created object:

#include <Servo.h>

//servo information structure definition
//typedef allows us to create a variable of this type

#define NUM_SERVOS      3
Servo   servoOne;
Servo   servoTwo;
Servo   servoThree;

typedef struct
{
    Servo           *servoObject;
    byte            pinServo;
    int             servoAngle;

}struct_ServoInfo;

struct_ServoInfo ServoInfo[NUM_SERVOS] = 
{
    {
        //servo object one
        .servoObject = (Servo *)&servoOne,
        .pinServo = 10,
        .servoAngle = 45    
    },
    {
        //servo object two
        .servoObject = (Servo *)&servoTwo,
        .pinServo = 11,
        .servoAngle = 30    
    },
    {
        //servo object three
        .servoObject = (Servo *)&servoThree,
        .pinServo = 12,
        .servoAngle = 61    
    }
    
};

void setup() 
{
    Serial.begin(9600);
    for( int i=0; i<NUM_SERVOS; i++ )
    {
        ServoInfo[i].servoObject->attach( ServoInfo[i].pinServo );
        ServoInfo[i].servoObject->write( ServoInfo[i].servoAngle ); 
        
    }//for
    
}//setup

void loop( void )
{
    //...
    
}//loop

Some advice on how to combine the name of the servo object with a number and how to
consign a (numbered)object would be appreciated.

That can NOT be done. At run time, variables have addresses, not names.

Blackfin:
A fair question. Perhaps the struct member could be a pointer to the already-created object:

You can (no need for cast!), or just don't create a servo object outside the struct :wink:

Thanks for your suggestions !

septillion:
So, multiple servo’s and multiple pins to move them?

For the servo part:

const byte ServoPins[] = {10, 11, 12};

const byte NrServos = sizeof(SevoPins);
byte servoAngles[NrServos] = {45, 30, 61};
Servo myServos[NrServos];



Now you can just iterate over them as you like.

This looked fine on the first view. But when I try to numerate my objects it seems that they are not global (or how it’s called correct?)

my testcode:

#include <Servo.h>

const byte ServoPins[] = {10, 11, 12};
const byte NrServos = sizeof(ServoPins);
byte servoAngles[NrServos] = {45, 30, 61};
int i=0;
int j=0;

void setup(){
	for (i=1; i<3; i++){
		Servo myServos[i];
		myServos[i].attach(ServoPins[i]);
	}

}

void loop(){
	for (i=0; i<3; i++){
		myServos[i].write(servoAngles[i]);
	}

}

The compiler is not amused → "error: ‘myServos’ was not declared in this scope.(in the loop)

Maybe I should mention that the usage of the array …

int servodata={
1,10,45,
2,11,30,
3,12,61
};

… is important as the final data for the servos are calculated by a spreadsheet and have to be changed easy. It’s easier to replace the array than editing N objects and compile new.


gfvalvo:
Why create 6 Servo objects when you only need 3?

That’s only for explanation, at the end there are 13 servos working. If the code works for three it should also work for thirteen. (or 23 if this code works on a teensy)


Structures
I understand that I have to define structure-members for every servo. Isn’t it possible to read the data from my “beloved” array?
Even that I like septillion’s proposal if it would work.

In your test code, you dropped a critical line from the snippet that Sepillion gave you:

Servo myServos[NrServos];

Put it back.

Then you compounded the problem with this:

Servo myServos[i];

You can just delete that line.

That’s simply because you somehow moved the declaration of myServo into setup(). :wink: That’s not what I did :slight_smile:

And somehow you do think you need ‘i’ and ‘j’ globally…
Try:

#include <Servo.h>

const byte ServoPins[] = {10, 11, 12};
const byte NrServos = sizeof(ServoPins);
byte servoAngles[NrServos] = {45, 30, 61};
Servo myServos[NrServos]; //declare it here

//NO need for them global
//int i=0;
//int j=0;

void setup(){
  //spaces are free ;)
  //but more importantly, computer start counting at 0 (zero)
  //And we made a nice definition of the number of servo's, take advantage of that! ;)
  for (byte i = 0; i < NrServos; i++){
    //Servo myServos[i]; NOT HERE
    myServos[i].attach(ServoPins[i]);
  }
}

void loop(){
  for (bye i = 0; i < NrServos; i++){
    myServos[i].write(servoAngles[i]);
  }
}

Olfried:
Maybe I should mention that the usage of the array …

int servodata={

1,10,45,
2,11,30,
3,12,61
};



... is important as the final data for the servos are calculated by a spreadsheet and have to be changed easy. It's easier to replace the array than editing N objects and compile new.

Absolutely!

But :slight_smile:

  • It has no reason to be int => byte will do
  • if it doesn’t change on runtime => const
  • first numbers are pretty meaningless => leave them out, saves memory.
  • and jamming everything in a single array is possible, it doesn’t make very clear code. I would opt for two arrays. Barely more work pasting two from Excel. And are the pins really changing? Or just the angles?

Talking about the angles, they don’t change during runtime?