Arduino Größe von Servo Array Objekten ist .. falsch?


7

Nachdem ich ziemlich lange über das Internet gesucht habe , habe ich keine andere Wahl, als jemanden zu fragen, ob er mir diese anscheinend seltsame Situation erklären kann.

Ich mache einige Tests mit einigen Servomotoren und versuche, sie mit millis()und ServoObjekt fast zusammen zu bewegen .

Es funktioniert natürlich entweder für einzelne Servos oder für mehrere Servos.

Der detailliertere Fall betrifft Folgendes:

  1. Bewegen Sie einen, zwei oder mehr Servomotoren zusammen.
  2. Zwingen Sie sie, FAST die gleiche Zeit zu nehmen, um eine Aktion auszuführen.
  3. Haben Sie eine dynamische Anzahl von Servos.

Über die ersten beiden Punkte hatte ich keine Probleme, sie zu lösen. Ich war leicht in der Lage, eine Funktion zu erstellen und dann eine Bibliothek zu erstellen, um einen solchen Job zu erledigen.

Da ich jedoch NICHT an C ++ gewöhnt bin und mich gefragt habe, ob es tatsächlich möglich ist, ein Array von Servo-Objekten zu erstellen, wie Sie es tatsächlich auf Arduino mit Strings tun können:

String stringArray[] = {"string1", "string2", "and so on, I love it."};

Nachdem ich mich eine Weile gefragt habe, habe ich Folgendes versucht:

Servo servObject;
Servo servObject_2;
Servo servObject_3;

Servo servos[] = {servObject, servObject_2, servObject_3};

Und weißt du was cool ist? Meine Funktion funktioniert tatsächlich korrekt, indem die Anzahl der Elemente des Servo-Arrays erzwungen wird.

Was ich damit meine ist, dass wenn ich meine Funktion zwinge zu wissen, dass sie 3 Elemente im Array haben wird, es natürlich funktionieren wird; Doch aus irgendeinem Grunde, wenn ich sizeof(servos);den Wert zurückkehrte, überraschend, ist 2.... Außerdem, wenn ich nur zwei Servo - Push - Objekte anstelle von drei in den Servo Array, deren sizeofRückkehr 6.

Durch Googeln habe ich einige Diskussionen darüber herausgefunden, dass sizeof aus bestimmten Gründen in einigen Fällen einen falschen Wert zurückgibt (wenn ich mich nicht irre, war es der richtige Wert -1), aber in meinem Fall es folgt anscheinend überhaupt keiner Logik.

Das Board, das ich benutze, ist ein Arduino Nano mit ATMEGA 328.

Irgendeine Idee, warum nicht der richtige Wert zurückgegeben wird? Bin ich eigentlich total falsch, weil ich keine Reihe von Servoobjekten erstellen sollte?

ps: Ich habe nicht den gesamten Code gepostet, weil er nutzlos gewesen wäre, da sizeof die erste Funktion ist, die in der aufgerufen wird loop()

Grüße,

briosheje


Was Sie beschreiben, ist komisch; Könnten Sie bitte den genauen Code posten, der die Größe des Arrays berechnet und anzeigt (ich nehme an, dies erfolgt über Serial)?
jfpoilpret

@jfpoilpret: arduino unterstützt das Standardkonstrukt sizeof, das für jedes Array-Objekt verfügbar ist. Daher gibt jedes Array (z. B. int elements [] = {2,3,1,3,9};) seinen korrekten Wert aus (im vorherigen Fall 5), und ich erhalte den Wert direkt vom seriellen Port. Auf jeden Fall werde ich heute Abend den gesamten Code hochladen, ich bin nicht zu Hause und kann ihn nicht wirklich aus meinem Nexus 5: P
briosheje

1
Es wäre hilfreich, wenn Sie eine Version Ihres Codes veröffentlichen, die auf das Minimum reduziert ist, das zum Nachweis der fehlerhaften Rückgabe erforderlich ist.
JRobert

@JRobert: Heute Abend werde ich den gesamten Code veröffentlichen, obwohl, wie oben erwähnt, das Array direkt vor dem Setup deklariert (und gefüllt) wird und selbst wenn ich das sizeofam Anfang meiner Schleife drucke, wird es immer noch ausgegeben Wert wie in der Funktion, in der ich es benutze. Gibt es auch eine Alternative, um zu überprüfen, ob ein Array-Element vorhanden ist? Wenn es möglich ist, könnte ich meinen eigenen sizeofPrototyp machen.
Briosheje

Mein Punkt war, dass es für jemanden einfacher ist, ein einfaches oder triviales Programm auszuprobieren, das den Fehler zeigt, dass Sie Ihr - wahrscheinlich hardwareabhängiges - vollständiges Programm ausprobieren können. Um Ihre Frage zu beantworten, verwende ich dieses Makro #define countof(a) (sizeof(a)/sizeof(a[0])), um die Anzahl der Elemente in einem Array zu ermitteln. Da dies jedoch davon abhängt, wird sizeof()es Ihnen nicht viel helfen.
JRobert

Antworten:


7

Was Sie beschreiben, scheint ein häufiges Problem zu sein, mit dem viele C- oder C ++ - Entwickler umgehen können (oder haben) sizeof.

Schauen Sie sich den folgenden Code an:

char a[3];

int size(char b[]) {
    return sizeof b;
}

void setup() {
    int size1 = sizeof a;
    int size2 = size(a);
}

In diesem Code size1wird vom Compiler ausgewertet, auf 3welche Größe die aVariable tatsächlich angewendet size2wird 2.

Warum so?

Dies liegt nur daran sizeof a, dass der Compiler sie auswertet und der Compiler weiß, dass aes sich um ein Array von 3 handelt char. Wenn aes jedoch als Argument für die Funktion übergeben wird size(), wird es in einen Zeiger (auf das erste Element des Arrays) konvertiert. Daher entspricht seine Größe der Größe eines Zeigers , der 2Bytes auf der AVR ATmega-MCU sind.

Diese Subtilität von sizeofkann seltsame Werte erklären, wie Sie beschreiben.

Wie behebe ich das Problem?

Die meisten C-Funktionen, die ein Array als Argument verwenden, erfordern ein anderes Argument, das die Größe des Arrays angibt. Das ist der Weg (der einzige, den ich denke), um mit diesem Problem umzugehen.

Hier ist ein Beispielcode:

Servo allServos[] = {...};
#define NUM_SERVOS (sizeof(allServos) / sizeof(Servo))
...
void handleServos(Servo *servos, int numServos) {
    for (int i = 0; i < numServos; i++) {
        servos[i].write(...);
        ...
    }
}

void loop() {
    handleServos(allServos, NUM_SERVOS);
}

In C ist es üblich , ein Array zu deklarieren und unmittelbar danach seine Größe wie oben zu definieren.


Oh, danke, ich wusste nicht, dass sich sizeof in diesem Fall auf den Zeiger des Arrays bezogen hätte. Gibt es also eine Möglichkeit, die wahre Größe des obigen Arrays von Servo-Objekten zu ermitteln? Soll ich jedes Element zählen und einen Zähler verwenden?
Briosheje

@briosheje siehe die neueste Bearbeitung meiner Antwort.
jfpoilpret

Vielen Dank! Es klappt! :) Ich habe die Antwort bereits als Lösung bestätigt, aber trotzdem, danke für die klare Erklärung!
Briosheje
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.