Auswahl mehrerer Instanzen einer Klasse via Index möglich ?

Hallo,
als immernochAnfänger weiß ich nicht ob meine Begriffswahl korrekt ist, daher hilft mir Google nix:

Ich habe mehrere Servos, die ich über die Standard Arduino Bibliothek anspreche.
Dazu habe ich aktuell mehrere Objekte (nennt man das Instanzen der Servoklasse ?) erstellt:

Servo myservo0; 
Servo myservo1;  
Servo myservo2;

Damit läuft auch mein Sketch, z.B:

myservo0.writeMicroseconds(1200);
myservo1.writeMicroseconds(1200);
myservo2.writeMicroseconds(1200);

Ich würde meinen Code gerne aufräumen und verschlanken, und diese Servos gerne via Index ansprechen.
Also gerne etwa sowas kreieren:

byte i=2;
Servo myservo[i]; // drei Servoobjekte erstellen, die via i ausgewählt werden können

Um dann in der loop z.B. sowas

for (i=0;i<3;i++)
 {myservo[i].writeMicroseconds(1200);}

laufen lassen zu können.
Geht das ?

Gruß,
Tütenflieger

Schon mal was von Arrays gehört? Das geht auch mit Objekten :slight_smile:

Servo servos[3];

Was du oben geschrieben hast, erstellt nur 2 Objekte!

Oh, soo einfach ?
Das hab ich echt nicht geahnt, drum nicht ausprobiert.
Sonst erwiesen sich Punkte eher komplexer als erwartet...
Sorry,

Tütenflieger

Danke !

Du hattest es ja eigentlich:

byte i=2;
Servo myservo[i]; // drei Servoobjekte erstellen, die via i ausgewählt werden können

Der Fehler ist das wie gesagt, dass das nur 2 Objekte mit den Indizes 0 und 1 erstellt

Der Fehler ist das wie gesagt, dass das nur 2 Objekte mit den Indizes 0 und 1 erstellt

... und dass es so gar nicht gehen sollte...
Tip: mit const gehts

const byte AnzahlServos=3;
Servo myservo[AnzahlServos]; // drei Servoobjekte erstellen, die via Index ausgewählt werden können

void loop () {
for (byte i = 0; i <  AnzahlServos; i++)
   machWasMit(myservo[i]);
}

void machWasMit(Servo& s) 
{
  // s ist eine Referenz auf eines der Servo Objekte
  s.writeMicroseconds(1200);
}

OK, das mit der Definition als Konstante geht klar.
Mein

const byte ANZSERVOS = 3:
Servo myservo[ANZSERVOS];

kompiliert auch. Es hakt aber nun bei anderen Objekten, bei deren Erstellung Parameter übergeben werden müssen.
Da komme ich nicht weiter, hier konkret bei der PID Lib, die laut PID_v1.h folgende Parametern erwartet:
PID::PID(double*, double*, double*, double, double, double, int) .

Folgendes kompiliert nicht:

#include <PID_v1.h>  // Standard PID-Lib aus dem Playground
const byte PIDs = 2; // 2 PID Regelungen

//--------- PID -----------
double PID_Input[PIDs], double PID_Output[PIDs], double PID_Setpoint[PIDs];  

PID myPID[2](&PID_Input[2], &PID_Output[2], &PID_Setpoint[2], 100, 50, 0, DIRECT);

Fehlermeldung: // Obkekt_indizier_TEST:30: error: bad array initializer

Auch folgende Versionen gehen NICHT (Compiler-Fehlermeldungen als Kommentar hintenangestellt

2. Versuch: PID myPID[PIDs]; Fehlermeldung : Obkekt_indizier_TEST:29: error: no matching function for call to 'PID::PID()' 
note: candidates are: PID::PID(double*, double*, double*, double, double, double, int)

3. Versuch: PID myPID[2](&PID_Input[], &PID_Output[], &PID_Setpoint[], 100, 50, 0, DIRECT);  // Obkekt_indizier_TEST:31: error: expected primary-expression before ']' token Obkekt_indizier_TEST:31: error: bad array initializer
4. Versuch: PID myPID[2](&PID_Input, &PID_Output, &PID_Setpoint, 100, 50, 0, DIRECT); // Obkekt_indizier_TEST:32: error: bad array initializer

Meine Originalversion ohne Indices, weder bei den Objekten noch bei den Übergabeparametern macht mit PID myPID_QR(&PID_QR_Input, &PID_QR_Output, &PID_QR_Setpoint, P_Param_QR, I_Param_QR, D_Param_QR, DIRECT);

keine Probleme.

Ich habe dann versucht, die PID myPID[index] innerhalb einer for-Schleife zu erstellen, aber vor der Setupfunktion mag C das nicht, und innerhalb von Setup() streikt der Compiler, da myPID noch nicht initialisiert ist (was ja auch stimmt).

Wie können also indexierte Objekte aus einer Library erstellt werden, bei der ebenfalls indexierte Parameter übergeben werden sollen ? Ich will ja pro Objekt entsprechend unterschiedliche Parameter setzen können-

Damit zusammenhängende Folgefrage, bezieht sich auf die Funktion "machWasMit" aus dem Beispiel von michael_x (reply #4):
Ist es zwingend, daß dort das Servoobjekt über eine Referenz aufgerufen wird, also s.writeMicroseconds(1200); ?
Würde also der direkte Weg, z.B. die Wertezuordnung mit myservo[1].writeMicroseconds(1200); gar nicht gehen ?

Danke ,
Tütenflieger

(Arduino-IDE 1.06 unter Win 8.1)

Du musst genauso wie bei Arrays aus elementaren Datentypen mit geschweiften Klammern arbeiten!! Wie man halt ein Array normal initialisiert. Das ist nicht grundlegend anders. Bei Objekten kommt dann lediglich hinzu dass man den Konstruktor explizit aufruft.

Google spuckt da auch mit "Array aus Objekten initialisieren" Antworten aus:

Als Ergänzung noch die einfache Antwort:

Würde also der direkte Weg, z.B. die Wertezuordnung mit

   myservo [ 1 ] . writeMicroseconds(1200);

gar nicht gehen ?

**Doch, klar. **

Falls es dich nicht verwirrt:
Nur die Übergabe an andere Funktionen könnte evtl. problematisch werden. Da sollte man die Parameter als Zeiger oder Referenz auf die Original-Objekte mitgeben.

Hallo ,

ich habe versucht die von Serenifly verlinkten Seiten zu verstehen, und auf meine Fragestellung hin anzuwenden.
Also bei der beispielshaften Objektgenerierung von 2 Stk. myPID Objekten diese für die Initialisierung einzeln in geschweifte Klammern zu setzen. Verschiedene Versuche mit den Klammern, und Angabe der Indice oder auch nicht:

#include <PID_v1.h>
double PID_Input, PID_Output, PID_Setpoint;
PID myPID[]{PID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 100, 0, DIRECT), 
            PID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 50, 0, DIRECT)}; 

// Alternativ hatte ich folgendes Probiert:
PID myPID[]{myPID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 100, 0, DIRECT), 
            myPID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 50, 0, DIRECT)};
// und:
PID myPID[2]{myPID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 100, 0, DIRECT), 
             myPID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 50, 0, DIRECT)}; 
// und:
 PID myPID[]{{myPID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 100, 0, DIRECT)}, 
             {myPID(&PID_Input, &PID_Output, &PID_Setpoint, 100, 50, 0, DIRECT)}}; 
// und:
 PID myPID[]{myPID[0](&PID_Input, &PID_Output, &PID_Setpoint, 100, 100, 0, DIRECT), 
             myPID[1](&PID_Input, &PID_Output, &PID_Setpoint, 100, 50, 0, DIRECT)};

Alles kompiliert nicht, immer mit dem error: function definition does not declare parameters.

Ich stehe da gerade wie der Ochs vor Berg....

ratloser Tütenflieger

= vergessen. Normale Arrays schreibst du doch auch so:

int test [5] = { 16, 2, 77, 40, 12071 }

Und zwei Objekten mit den gleichen Variablen arbeiten zu lassen mag kompilieren, ist aber praktisch nicht gut.

Übersetzt für mein Objekt mit mehreren übergebenen Variablen heißt das dann doch, daß ich jeweils einen Parametersatz in fürein Objekt geschweifte Klammern setze:

PID myPID[2] = {{(&PID_Input, &PID_Output, &PID_Setpoint, 100, 100, 0, DIRECT)}, 
             {(&PID_Input, &PID_Output, &PID_Setpoint, 100, 50, 0, DIRECT)}};

und es kompiliert nicht mit
Obkekt_indizier_TEST.ino:23: warning: left-hand operand of comma has no effect
Obkekt_indizier_TEST.ino:24: warning: right-hand operand of comma has no effect
Obkekt_indizier_TEST:24: error: braces around scalar initializer for type 'PID'

???

Die Anmerkung mit den gleichen Variablen bei der Initialisierung war ja korrekt, aber hier nur ein Beispiel.

Tütenflieger

seufz
Den einen Fehler behoben und dann den ersten Hinweis wieder ignoriert :slight_smile:

Erstens hast du viel zu viele unsinnige Klammern.

Zweitens geht das nur wenn lediglich ein Default Konstruktor vorhanden ist. Wenn andere Konstruktoren da sind, musst du den Konstruktor explizit aufrufen. An der Stelle ist die Syntax von C++ leider nicht mit den Standard C Initialisierungslisten kompatibel.

const int instances = 2;
double PID_Input[instances], PID_Output[instances], PID_Setpoint[instances];

PID myPIDs[instances] = { PID(&PID_Input[0], &PID_Output[0], &PID_Output[0], 100, 100, 0, DIRECT),
	                  PID(&PID_Input[1], &PID_Output[1], &PID_Output[1], 100, 100, 0, DIRECT),
	                };

Hallo Serenifly,
jetzt kompilierts.

Vielen Dank für die Geduld!

Tütenflieger