Probleme mit meinem Code für Servo Ansteuerung

Ich hab momentan Probleme mit meinem Code welchen ich vor einiger Zeit entwickelt habe da er seine Funktion mehrere Servo Motoren an eine Position zu bringen mit einer Funktion ähnlich wie das Sweep Beispiel und alle in der selben Zeit nicht mehr erfüllt und ich bin mir relativ sicher das er nachdem ich ihn entwickelt hatte funktioniert hat. Ich weiß der Code ist relativ lang und etwas schwer zu lesen aber ich hoffe jemand hier kann mir helfen.

#include <Servo.h>

int NumberOfMotors = 6;
Servo SM[6];
int SPin[6];
int Number;
int Break; // um eine Pause zwischen zwei Bewegungen anzugeben

boolean ToF[6]; // gibt an ob drehgeschwindigkeit oder zeitraum der drehung angegeben ist
int Unit[6];  // gibt einheit der zeit an sekunden minuten usw
int Period[6];  // gibt zeit an in der sich eine Bewegung vollziehen soll
int MSpeed[6]; // gibt direkt geschwindigkeit einer Bewegung an
int PAlt[6]; // Gibt alte Position an
int PNeu[6]; // Gibt geplante Position an


void StartAllocation(int Number2, boolean a, int b, int c, int d, int e, int f) {
  ToF[Number2] = a;
  Unit[Number2] = b;
  Period[Number2] = c;
  MSpeed[Number2] = d;
  PAlt[Number2] = e;
  PNeu[Number2] = f;
}

void Allocation(int Number2, boolean a, int b, int c, int d, int f) {
  ToF[Number2] = a;
  Unit[Number2] = b;
  Period[Number2] = c;
  MSpeed[Number2] = d;
  PNeu[Number2] = f;
}

int MovingTime() {
  int output = 0;
  if (PNeu[Number] == PAlt[Number]) {
    output = 0;
  }
  else {
    if (ToF[Number] == true) {
      output = MSpeed[Number] * Unit[Number];
    }
    if (ToF[Number] == false) {
      if (PAlt[Number] < PNeu[Number]) {
        output = ((Period[Number] * Unit[Number]) / (PNeu[Number] - PAlt[Number]));
      }
      if (PAlt[Number] > PNeu[Number]) {
        output = ((Period[Number] / (PAlt[Number] - PNeu[Number])) * Unit[Number]);
      }
    }
  }
  return output;
}

void Moving() {
  if (PAlt[Number] < PNeu[Number]) {
    PAlt[Number]++;
  }
  if (PAlt[Number] > PNeu[Number]) {
    PAlt[Number]--;
  }
  SM[Number].write(PAlt[Number]);
}

void Action() {
  int TimeOld[6];
  int WaitingTime[6];
  int controle = 0;
  Number = 0;
  for (int i = 0; i < NumberOfMotors; i++) {
    TimeOld[Number] = millis();
    WaitingTime[Number] = MovingTime();
    Number++;
  }
  Number = 0;
  while (controle < NumberOfMotors) {
    Number = 0;
    for (int i = 0; i < NumberOfMotors; i++) {
      if (TimeOld[Number] + WaitingTime[Number] < millis()) {
        Moving();
        TimeOld[Number] = millis();
      }
      Number++;
    }
    controle = 0;
    Number = 0;
    for (int i = 0; i < NumberOfMotors; i++) {
      if (PAlt[Number] == PNeu[Number]) {
        controle++;
      }
      Number++;
    }
  }

  delay(Break);
}




void setup() {
  Serial.begin(9600);
  SPin[0] = 3;
  SPin[1] = 5;
  SPin[2] = 6;
  SPin[3] = 9;
  SPin[4] = 10;
  SPin[5] = 11;

  Number = 0;
  for (int i = 0; i < 6; i++) {
    SM[Number].attach(SPin[Number]);
    Number++;

    SM[0].write(90);
    SM[1].write(80);
    SM[2].write(80);
    SM[3].write(0);
    SM[4].write(90);



    PAlt[0] = 90;
    PAlt[1] = 80;
    PAlt[2] = 80;
    PAlt[3] = 0;
    PAlt[4] = 90;

    delay(5000);
    Serial.print("Start");
    Allocation(0, false, 1, 10000, 1, 85);
    Allocation(1, false, 1, 10000, 1, 72);
    Allocation(2, false, 1, 10000, 1, 149);
    Allocation(3, false, 1, 10000, 1, 0);
    Allocation(4, false, 1, 10000, 1, 138);



    Action();
  }



  /*
    Allocation(0, Boolean ToF, Unit, Period, MovingSpeed, Neue Position, Break in Millisekunden)

     Folgendes verwenden um neu Bewegung in Void Setup hinzuzufügen:

     Allocation(0, , , , , );
     Allocation(1, , , , , );
     Allocation(2, , , , , );
     Allocation(3, , , , , );
     Allocation(4, , , , , );
     Action();
  */

}


void loop() {}

Hi

Du definierst 6 Servos, wovon in Setup nur noch 5 (0...4) bespaßt werden.

Bis auf Deine etwas eigene Art

  • Schleife von 0 bis 5 hochzählen
  • separate Variable vor der Schleife auf 0 initiieren und am Ende der Schleife hochzählen
    (man könnte die Schleifen-Variable hier nutzen)
  • und der dauernden Nutzung von INT (warum eigentlich?)

Sehe ich direkt nicht, wo der Sketch hakt.

Verteile massig Serial.print im Sketch um abzuschätzen, wo Dieser 'falsch abbiegt'.
Wenn Dir bewusst ist, wo der Fehler auftritt, kannst Du den Bereich davor genauer unter die Lupe nehmen und so den Fehler eingrenzen.

MfG

PS: Ggf. sind die MoBaTools was für Dich - langsam laufende Servos lassen sich damit nämlich realisieren.

delay(Break);

Da Break dauerhaft Null ist, sich nie ändert, dürfte das Delay recht sinnfrei sein.

E:\Programme\arduino\portable\sketchbook\sketch_dec29a\sketch_dec29a.ino: In function 'void Action()':

E:\Programme\arduino\portable\sketchbook\sketch_dec29a\sketch_dec29a.ino:80:49: warning: comparison of integer expressions of different signedness: 'int' and 'long unsigned int' [-Wsign-compare]
  80 |      if (TimeOld[Number] + WaitingTime[Number] < millis()) {
      |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~

Die Warnung ist nicht nur berechtigt, sondern der Code wird spätestens nach ziemlich genau 49,x Tagen auf die Nase fallen.

Ansonsten, hast du irgendwie vergessen zu sagen, was der Code tun soll, und was er nicht tut.
Oder du hast es so gut verschlüsselt, dass ich es nicht kapiere,

vielen dank für die Hilfe ich werde mal weiter ausprobieren woran es jetzt lag ich hoffe einfach das es nicht an der Hardware liegt
-ich habe 6 Motoren definiert da ich den sechsten jetzt noch nicht nutze aber später einbinden möchte.
-das selbe bei der Break Variable
-intager nutze ich irgendwie aus Gewohnheit wenn das Funktioniert muss ich mich noch darum kümmern

nochmal vielen Dank

Sollte die for-Schleife nicht nur das attach() der Servos machen? Sie endet aber erst am Ende von setup() nach dem Action(). Ich kann mit nicht vorstellen, dass das so gedacht ist.

Ausserdem sind Kommentare ein hervorrangendes Mittel um das eigene Programm auch nach einiger Zeit noch zu verstehen. Und um eventuellen Helfern zu helfen.

Man kann Arrays bei der Definition initiieren.

  SPin[0] = 3;
  SPin[1] = 5;
  SPin[2] = 6;
  SPin[3] = 9;
  SPin[4] = 10;
  SPin[5] = 11;

Eine Notiz am Rande:

Die Servo.h Bibliothek kann auf dem UNO 12 Servo ansteuern und diese können auf beliebigen Pins sitzen und nicht nur auf den PWM pins. Da die Bibliothek einen Timer verwenden sind beim UNO 2 PWM Ausgänge nicht mehr benutzbar (Pin 9 und 10). Andere Arduino Versionen haben andere Einschränkungen bzw gar keine. siehe Servo - Arduino Reference

Grüße Uwe

Hallo,

du musst deine definierten Konstanten im Code auch nutzen. Sonst endet das zwangsweise im Kaos, wie man sieht.
Wenn du derzeit nur 5 Servos statt 6 hast, dann brauchst du nur eine einzige Konstante ändern. Desweiteren muss dann noch i nutzen um Haufenweise Codedopplungen zu vermeiden.

const byte NumberOfMotors = 5;

void setup(void) {

  for (byte i = 0; i < NumberOfMotors; i++)
  {
    SM[i].attach(SPin[i]);
    SM[i].write(90);
    PAlt[i] = 90;
    
    delay(5000);
    Serial.print("Start");
    /*
    Allocation(0, false, 1, 10000, 1, 85);
    Allocation(1, false, 1, 10000, 1, 72);
    Allocation(2, false, 1, 10000, 1, 149);
    Allocation(3, false, 1, 10000, 1, 0);
    Allocation(4, false, 1, 10000, 1, 138);
    */
    Action();
  }
}

dann kannste auch weitere Arrays so definieren.

int Unit[NumberOfMotors];

Desweiteren schreit mich förmlich ein struct für die Servoeigenschaften an.
Dann bekommste auch das Allocation in den Griff.

Wichtig ist Struktur reinbringen - im wahrsten Sinne.

MicroBahner das was du gesagt hast habe ich auch gerade bemerkt und es war auch der Ursprung des eigentlichen Fehlers

uwefed verstehe ich dich richtig es ist egal welche pins ich für die Servo Ansteuerung nutze da dies mit allen funktioniert denn das hatte ich eigentlich anders gelernt

Doc_Arduino sorry aber was meinst du mit "struct"?

combie meinst du der code funktioniert dann nicht mehr weil millis dann bei seinem Maximalwert angelangt ist und wieder von neu anfängt?

combie meinst du der code funktioniert dann nicht mehr weil millis dann bei seinem Maximalwert angelangt ist und wieder von neu anfängt?

Jain!
Ich sage, dass dein Verfahren den Überlauf nicht kompensiert.

Doc_Arduino sorry aber was meinst du mit "struct"?

Das kann ich dir auch beantworten.
Ihm meint das C++ Schlüsselwort struct

Ja, die Servo-Lib funktioniert an allen digitalen Pins ( meine MobaTools übrigens auch :wink: ).

'struct' ist zusammengesetzter Datentyp, und erlaubt zusammengehörige Daten auch Im Programm als zusammengehörige Einheit zu behandeln. Siehe z.B. hier. (Edit: ist doch glatt der gleiche Link wie bei combie - aber nicht abgeschrieben :wink: )
Aber wenn ich mir dein Programm so anschaue ...
Da glaube ich ehrlicherweise dass zuerst noch andere Wissensdefizite beseitigt werden müssten.

Damit beim Überlauf von millis() keine Fehler auftreten, muss man in der Tat die Zeitabfrage entsprechend gestalten. Da kann man sonst leicht auf die Nase fallen.

Hallo,

ich habe dir ein Bsp. gemacht. Ist nun statt einem struct eine class gewurden, spielt aber erstmal keine große Rolle.
Alle Servoeigenschaften sind deine Member in der Klasse.
Die Methoden sind deine "Funktionen" die du außerhalb der Klasse aufrufst.
Kannste mit Überlegung erweitern - was du eben so benötigst für deine Servos.
Die Namen der Funktionen und Methoden sind sicherlich noch nicht perfekt. Der Sinn sollte aber daraus hervorgehen.

Du kannst das alles auch ohne struct und class machen, wenn du jederzeit konsistente Arrays und gültige for Schleifen für alles verwendest.
Am Ende möchte man jedoch eine Klasse und kann davon soviele Objekte erstellen wie man benötigt.
Mag aktuell vielleicht noch etwas viel sein, aber der Weg dahin sollte dein Ziel sein.
Vermeidet viele Probleme.

Kompiliert, aber nicht praktisch getestet

// https://forum.arduino.cc/index.php?topic=656054.0

/*
  Doc_Arduino - german Arduino Forum
  IDE 1.8.10
  avr-gcc 9.2.0 mit -std=gnu++17
  Arduino Mega2560
  29.12.2019
*/

#include <Servo.h>

const byte NumberOfServos = 2;

// *******************************************************************************

class Steuerung
{
    Servo myservo;

  private:
    // Member
    const byte pin;
    byte winkel;


  public:
    // Konstruktor
    Steuerung(byte p, byte w) :
      // Initialisierungsliste
      pin{p},
      winkel{w}
    {}

    // Methoden
    void init ()
    {
      myservo.attach(pin);
      myservo.write(winkel);
    }

    void setPosition(unsigned int var)
    {
      winkel = var;
    }

    void goPosition(void)
    {
      myservo.write(winkel);
    }
};

// *******************************************************************************

Steuerung steuerung[NumberOfServos] = {
  {8, 60},   // Parameter laut Initialisierungsliste
  {9, 90},   // Pin, Winkel (Startposition)
};


void setup(void) {
  setupServos();  // alle Servos initialisieren
}


void loop(void) {

  refreshPosition();     // mus ständig in loop aufgerufen werden

  // Bsp.
  newPosition(0, 120);  // Position vom ersten Servo ändern
}


// ****** Funktionen ******
void setupServos(void)
{
  for (Steuerung &k : steuerung)
  {
    k.init();
  }
}


void refreshPosition(void)
{
  for (Steuerung &k : steuerung) {
    k.goPosition();
  }
}


void newPosition(const byte index, const byte winkel)
{
  if (index < NumberOfServos)
  {
    steuerung[index].setPosition(winkel);  // Position vom Servo n ändern
  }
}

oder schaust dir die MobaTools an ... :slight_smile:

Siehe z.B. hier. (Edit: ist doch glatt der gleiche Link wie bei combie - aber nicht abgeschrieben :wink: )

Ich betrachte das als eine Abstimmung über die Frage:
Wo ist die richtige, lesenswerte, Sprachdokumentation?

vielen dank für all die Antworten

Doc_Arduino ich muss sagen ich verstehe nicht einmal die hälfte deines Codes dies liegt aber daran das ich dafür nicht tief genug in der Materie bin und nicht viel Erfahrung habe aber definitiv vielen dank das du dir soviel mühe gemacht hast den kompletten code quasi neu zu schreiben

ich geh mal davon aus das hier die meisten Informatik studiert oder in einer Ausbildung viel davon gelernt haben hättet ihr vielleicht tips wie man das auch anders lernen kann?

struct schaue ich mir gerade an

und zu meinem Sketch es funktioniert momentan mehr oder weniger der eine Motor dreht sich manchmal seltsamerweise in die falsche Richtung und generell bin ich mir nicht so sicher das meine Hardware noch vollkommen in Ordnung ist da ich zB bei meinem Arduino Uno bei fast jedem zweiten Hochladen "Arduino: 1.8.9 (Windows 10), Board: "Arduino/Genuino Uno"

Der Sketch verwendet 4234 Bytes (13%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 326 Bytes (15%) des dynamischen Speichers, 1722 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
avrdude: ser_open(): can't open device "\.\COM3": Zugriff verweigert

Problem beim Hochladen auf das Board. Hilfestellung dazu unter http://www.arduino.cc/en/Guide/Troubleshooting#upload.

Dieser Bericht wäre detaillierter, wenn die Option
"Ausführliche Ausgabe während der Kompilierung"
in Datei -> Voreinstellungen aktiviert wäre.
"

von einem Sketch eine Fehlermeldung bekomme und die Motoren können keine Position direkt zu beginn anfahren da sie sich erstmal nur kleinschrittig bewegen und dann plötzlich springen

ich geh mal davon aus das hier die meisten Informatik studiert oder in einer Ausbildung viel davon gelernt haben

Zumindest für meinen seiner, darf ich dich enttäuschen.

hättet ihr vielleicht tips wie man das auch anders lernen kann?

Dokus lesen und üben.
Gibts überhaupt andere Wege?

Hi

Selber auch kein Informatiker, nur ein mit Elektronik zu begeisternder Hobbyist.

Da steht eine Kleinigkeit sogar in Deutsch:

Dieser Bericht wäre detaillierter, wenn die Option
"Ausführliche Ausgabe während der Kompilierung"
in Datei -> Voreinstellungen aktiviert wäre.

Das solltest Du machen - mehr Informationen schaden bestimmt nicht, wenngleich Das nicht Dein Problem löst, daß der Arduino schlicht 'nicht da' ist.

Das ist aber eine Sache zwischen Arduino und Windows - Das bekommt man normal nicht kaputt.

MfG

Hallo,

ich geh mal davon aus das hier die meisten Informatik studiert oder in einer Ausbildung viel davon gelernt haben

Trifft für mich auch nicht zu. Bin elektronisch vorbelastet und irgendwann kam programmieren als ein Hobby dazu.

Die Initialzündung Klassen zu programmieren kam übrigens von combie. Er hatte das einmal auf die Beine gestellt.

Es stimmt auch nicht das Informatiker zwangsweise perfekt programmieren können. Das wäre optimalerweise ihr Hobby parallel zum Studium. Ein Informatikstudium ist auch viel Mathematik. Ihr Vorteil ist dann das sie sich mathematische Lösungen/Formeln selbst herleiten bzw. aufstellen können. So wie ein Elektroniker sich gewisse Formeln selbst aufstellen kann wenn er die Grundlagen drauf hat. Nur das es bei Informatiker/Mathematiker in weit aus höheren Ebenen passiert bzw. möglich sein sollte. :slight_smile:

Und wenn ich euch erzähle das viele Leute die das Rückrat zur avr C/C++ Programmierung hegen und pflegen, sodass wir überhaupt unsere µC programmieren können, auch keine Informatiker/Mathematiker sind, dann heißt das, dass sich diese Leute mit sehr viel Herzblut in ein Thema eingearbeitet haben und ein Wissensstand besitzen der Wahnsinn ist.

Ich stelle auch die These auf, dass viele Hardcore Informatiker in ihrem Leben nie einen µC zu Gesicht bekommem haben und werden. Die arbeiten wohl eher bei Banken, Versicherungen u.ä. und erarbeiten Statistiken, Wahrscheinlichkeitsberechnungen usw. :grin:

Hallo,

apropo Informatiker, was sie so machen :slight_smile:

Bekannt wohl eher durch seine legendären Xerox Scans. :grin:

Hi nochmal danke für eure Hilfe ich kann mich leider erst jetzt wieder melden da ich die letzten tage kein Wlan hatte. Also grundsätzlich funktioniert jetzt wie bereits gesagt fast alles was nur jetzt mein Problem ist, ist das die Motoren nach dem Anfahren von 2-4 Punkten aufhören sich zu bewegen hattet ihr da vielleicht schon was gesehen woran das noch liegen könnte?

Hallo,

du hast sicherlich dafür den Sketch geändert. Wir bräuchten jetzt den aktuellen Sketch zur weiteren Beurteilung.
Wenn möglich mit genauerer Problembeschreibung. Was funktioniert wie lange/wie oft und wann genau bleibt was stehen. Wo sind 2-4 Punkte? Immer daran denken wir können nur das lesen was geschrieben steht. Wir sehen deinen Aufbau nicht und auch nicht deine gedanklichen Vorstellungen was im Ablauf passieren soll.

ups sorry punkte anfahren da sie in einem Roboter ähnlichen arm verbaut sind momentan hab ich leider aufgrund von Klausuren keine Zeit mich darum zu kümmern. Eine nähere Problem Beschreibung gebe ich euch sobald ich den Arm weiter Testen kann
Auch nochmal vielen dank für eure Hilfsbereitschaft und Geduld mit einem blutigen Anfänger wie mir