Arduino Servo bewegt sich bei Verwendung von Klassen nicht

7

Ich versuche, eine Klasse mit Arduino zum Laufen zu bringen, aber es scheint nicht richtig auszulösen. Der Code wird perfekt kompiliert und soll das Bein eines Hexapods steuern . Auch der Beispiel-Sweep funktioniert mit diesem Servo, also hier kein Problem. Das Servo bewegt sich jedoch nicht wirklich. Ich denke, es hat etwas mit der Reihenfolge der Deklaration der Variablen zu tun:

#include <Servo.h>

// Abstract each leg, so only those functions can be accessed
class Leg {
  // Actions that can be triggered from outside
  public:
    Leg(int hipPin, int kneePin);
    void up();

  // These should be only available for the leg
  private:
    Servo hip;
    Servo knee;
  };

Leg::Leg(int hipPin, int kneePin) {
  hip.attach(hipPin);
  knee.attach(kneePin);
  }

// Testing the leg: move it up
void Leg::up() {
  for(int pos = 0; pos < 180; pos += 1) {
    hip.write(pos);
    delay(15);
    }
  }


// Initialize the leg
Leg topLeft(9, 10);

void setup() {
  }

// Test the function up()
void loop() {
  topLeft.up();
  }

Ich teste nur den Pin 9 (lasse die 10 leer). Es scheint Schmerzen zu haben , was bedeutet, dass Sie sehen können, wie das Servo zittert, sich aber bei 0 Grad nicht wirklich bewegt.

Francisco Presencia
quelle
Hinweis: Ähnliche Frage wie diese , aber da die Lösung bei mir nicht funktioniert hat, gehe ich davon aus, dass es nicht dasselbe Problem ist. Jede Hilfe beim Debuggen ist ebenfalls willkommen (:
Francisco Presencia
Funktioniert das gleiche Setup mit dem gleichen Pin, wenn Sie nur den Hip-Servo-Code außerhalb des Unterrichts testen? Tritt das Problem nur auf, wenn sich der Code in der Leg-Klasse befindet?
Omer
Ihr Problem kann dieser Frage ähnlich sein: arduino.stackexchange.com/questions/830/…
jfpoilpret

Antworten:

5

Es sieht so aus, als ob dieses Problem auf eine schlechte Reihenfolge der Initialisierungsaufrufe für globale Variablen zurückzuführen ist.

In C ++ ist die Reihenfolge der globalen Variableninitialisierung für verschiedene Kompilierungseinheiten (dh C ++ - Quelldateien, keine Headerdateien) nicht vorhersehbar. Die Initialisierungsreihenfolge wird nur innerhalb einer Kompilierungseinheit eingehalten .

In Ihrem Programm gibt es mehrere globale Variablen, die, wenn sie in der falschen Reihenfolge initialisiert werden, Ihr Programm zum Scheitern bringen:

  • Leg topLeft; Dies ist Ihre Klasseninstanz
  • servo_t servos[MAX_SERVOS];, int8_t Channel[_Nbr_16timers ];Und uint8_t ServoCount = 0;alle definiert inServo.cpp

Für den Aufruf Servo.attach()müssen die drei oben genannten Variablen bereits initialisiert worden sein, was Sie nicht sicher sein können.

Wie können Sie das beheben?

Indem Sie den attach()in- LegKonstruktor nicht ausführen, sondern an eine init()Methode delegieren, von der aus Sie Folgendes aufrufen können setup():

class Leg {
    // Actions that can be triggered from outside
    public:
    void init(int hipPin, int kneePin);
    void up();

    // These should be only available for the leg
    private:
    Servo hip;
    Servo knee;
};

Leg::init(int hipPin, int kneePin) {
    hip.attach(hipPin);
    knee.attach(kneePin);
}

// Testing the leg: move it up
void Leg::up() {
    for(int pos = 0; pos < 180; pos += 1) {
        hip.write(pos);
        delay(15);
    }
}

// Declare the leg
Leg topLeft;

void setup() {
    // Initialize the leg
    topLeft.init(9, 10);
}

// Test the function up()
void loop() {
    topLeft.up();
}
jfpoilpret
quelle
Nur zur Verdeutlichung wird die Initialisierungsreihenfolge globaler Variablen nicht nur zwischen verschiedenen Übersetzungseinheiten definiert. In derselben Übersetzungseinheit ist dies die Reihenfolge ihrer Definitionen.
Omer
+1 das ist Gold, die Erklärung hat gerade 100% der ungelösten Probleme gelöst, die ich jemals mit Arduino und C ++ hatte. Danke, ich werde es testen, wenn ich nach Hause komme.
Francisco Presencia
@Omer danke für die Klarstellung, die ich vergessen hatte aufzunehmen. Ich habe gerade meine Antwort bearbeitet.
jfpoilpret