Go Down

Topic: 8x verschachteltes if...then...else (Read 437 times) previous topic - next topic

themanfrommoon

Aug 04, 2019, 12:25 am Last Edit: Aug 04, 2019, 12:27 am by themanfrommoon
Hallo,

ich habe hier ein kleines Problem.

Folgendes möchte ich erreichen:

Wenn (Pos[0] - encoder.getPosition() == 0) dann tue nix
 ansonsten
  Wenn (Pos[0] - encoder.getPosition() > 0) {stepper.move(Pos[0] - encoder.getPosition());};
   ansonsten
    Wenn (Pos[1] - encoder.getPosition() == 0) dann tue nix
     ansonsten
      Wenn (Pos[1] - encoder.getPosition() > 0) {stepper.move(Pos[1] - encoder.getPosition());};
       ansonsten
        Wenn (Pos[2] - encoder.getPosition() == 0) dann tue nix
         ansonsten
          Wenn (Pos[2] - encoder.getPosition() > 0) {stepper.move(Pos[2] - encoder.getPosition());};
           ansonsten
            Wenn (Pos[3] - encoder.getPosition() == 0) dann tue nix
             ansonsten
              Wenn (Pos[3] - encoder.getPosition() > 0) {stepper.move(Pos[3] - encoder.getPosition());};
               ansonsten stepper.move(4095 - encoder.getPosition());

Code: [Select]
  if (Pos[0] - encoder.getPosition() == 0) {}
   else
    if (Pos[0] - encoder.getPosition() > 0) {stepper.move(Pos[0] - encoder.getPosition());};
     else
      if (Pos[1] - encoder.getPosition() == 0) {}
       else
        if (Pos[1] - encoder.getPosition() > 0) {stepper.move(Pos[1] - encoder.getPosition());};
         else
          if (Pos[2] - encoder.getPosition() == 0) {}
           else
            if (Pos[2] - encoder.getPosition() > 0) {stepper.move(Pos[2] - encoder.getPosition());};
             else
              if (Pos[3] - encoder.getPosition() == 0) {}
               else
                if (Pos[3] - encoder.getPosition() > 0) {stepper.move(Pos[3] - encoder.getPosition());};
                 else stepper.move(4095 - encoder.getPosition());


leider kompiliert das so nicht.

Gibt es vielleicht eine elegantere Lösung?

Es darf nur ein Bewegung geben, und nicht zwei.
Eine der Bedingungen wird immer zutreffen.

Lieben Gruß,
Chris

postmaster-ino

'kompiliert nicht' ist echt viel sagend ... soll heißen?

Ok, anders formuliert: Fehlermeldung?

Irgendwie habe ich nämlich das Gefühl, daß der Kram bei mir ebenfalls NICHT kompiliert.

MfG
Dein Problem, Dein Sketch, Deine Bilder.
Ob ich ohne Diese an Deinem Problem arbeiten will, entscheide aber immer noch ich.
Große Buchstaben? Immer wieder, neben Punkt und Komma, gerne gesehen.

wapjoe

#2
Aug 04, 2019, 12:37 am Last Edit: Aug 04, 2019, 12:38 am by wapjoe
Moin,

lösche mal die Semikolon ; hinter den geschweiften Klammern und setze die letzte else-Abfrage in geschweiften Klammern (hier weiß ich nicht ob es nötig ist, aber sieht einheitlicher aus).

Achte auch auf richtige Einrückung des Sketches, auch bei deinem Codefragment. Fehlermeldung zu posten wäre für Helfer sehr hilfreich.

themanfrommoon

….habs nun doch gefunden. Vor dem else muss das ";" weg  ::)

nu geht's:

Code: [Select]
 if (Pos[0] - encoder.getPosition() == 0) {}
   else
    if (Pos[0] - encoder.getPosition() > 0) {stepper.move(Pos[0] - encoder.getPosition());}
     else
      if (Pos[1] - encoder.getPosition() == 0) {}
       else
        if (Pos[1] - encoder.getPosition() > 0) {stepper.move(Pos[1] - encoder.getPosition());}
         else
          if (Pos[2] - encoder.getPosition() == 0) {}
           else
            if (Pos[2] - encoder.getPosition() > 0) {stepper.move(Pos[2] - encoder.getPosition());}
             else
              if (Pos[3] - encoder.getPosition() == 0) {}
               else
                if (Pos[3] - encoder.getPosition() > 0) {stepper.move(Pos[3] - encoder.getPosition());}
                 else stepper.move(4095 - encoder.getPosition());

Mahimus

#4
Aug 04, 2019, 12:43 am Last Edit: Aug 04, 2019, 12:44 am by Mahimus
Auch das else braucht geschweifte Klammern.
Auch glaube ich dass es eine elegantere Lösung gibt. Abfragen ob er auf position ist, wenn nicht eins weiter fahren, eine Variable hochzählen und beim nächsten loop durchlauf dann ggf. die hochgezähle position anfahren. Hoffe es ist verständlich. Du hast da ja 0,1,2,3 stehen und machst sonst das gleiche. Dann mach doch:


move pos(i)
i++

themanfrommoon

#5
Aug 04, 2019, 12:54 am Last Edit: Aug 04, 2019, 12:56 am by themanfrommoon
mal gucken, ob es mir gelingt zu erklären was ich möchte....

Also wenn der Strom eingeschaltet wird, bootet mein nodeMCU ESP8266 und fragt von einem Magnetencoder eine Position ab.
Durch die verschachtelte if...then...else Schleifen versuche ich im Setup() herauszufinden, ob die zufällige Startposition mit einer der vier absoluten Positionen übereinstimmt. Wenn ja, soll nichts passieren.
Wenn nein, dann soll die Distanz zur nächsten Position berechnet werden und der Stepper dort hin fahren. Dann ist die Startposition erreicht, und die Loop() kann beginnen.



Code: [Select]
#define Microstepping 4                    // Stepperdriver is set to 1/n microsteps (here 1/4)
#define StepperStepsPerRevolution 200           //one revolution of the stepper is 200 steps
int StepsPerRevolution = (StepperStepsPerRevolution * Microstepping);       // results in 800 steps per one revolution of the stepper

#include <AccelStepper.h>
#include <AS5600.h>
int n;
//int Pos[4] = {176, 1202, 2222, 3250}; // Der Winkelsensor hat Werte für 0-360° Sensorradposition von 0-4095. Diese vier Werte in dem Array markieren im Wertebereich 0-4095 die Positionen der vier Mulden im Sensorrad
int Pos[4] = {0, 1024, 2048, 3072}; // Testdaten Absolutpositionen
int RelativeStep[4];
#define STEPpin  14
#define DIRpin   12
unsigned long previousMillis = 0;
unsigned long stepperMillis = 0;
const long interval = 10;
AS5600 encoder;
int output;
AccelStepper stepper(AccelStepper::DRIVER, STEPpin, DIRpin);
void setup()
{
  Wire.setClock(400000L); //setzt die I²C Taktfrequenz auf 400kHz
  Serial.begin(9600);
  stepper.setMaxSpeed(10000); // 10000 ist wunderbar
  stepper.setAcceleration(100000); // 100000 ist schön schnell, 200 ist schön langsam

  RelativeStep[0] = (map(Pos[1], 0, 4095, 0, StepsPerRevolution)) - (map(Pos[0], 0, 4095, 0, StepsPerRevolution));
  RelativeStep[1] = (map(Pos[2], 0, 4095, 0, StepsPerRevolution)) - (map(Pos[1], 0, 4095, 0, StepsPerRevolution));
  RelativeStep[2] = (map(Pos[3], 0, 4095, 0, StepsPerRevolution)) - (map(Pos[2], 0, 4095, 0, StepsPerRevolution));
  RelativeStep[3] = StepsPerRevolution - (map(Pos[3], 0, 4095, 0, StepsPerRevolution));


  if (Pos[0] - encoder.getPosition() == 0) {}
  else if (Pos[0] - encoder.getPosition() > 0) {
    stepper.runToNewPosition(Pos[0] - encoder.getPosition());
  }
  else if (Pos[1] - encoder.getPosition() == 0) {}
  else if (Pos[1] - encoder.getPosition() > 0) {
    stepper.runToNewPosition(Pos[1] - encoder.getPosition());
  }
  else if (Pos[2] - encoder.getPosition() == 0) {}
  else if (Pos[2] - encoder.getPosition() > 0) {
    stepper.runToNewPosition(Pos[2] - encoder.getPosition());
  }
  else if (Pos[3] - encoder.getPosition() == 0) {}
  else if (Pos[3] - encoder.getPosition() > 0) {
    stepper.runToNewPosition(Pos[3] - encoder.getPosition());
  }
  else stepper.runToNewPosition(4095 - encoder.getPosition());
}

void loop() {
  // put your main code here, to run repeatedly:

}




Die Berechnung funktioniert soweit, es fehlt mir nur noch der Befehl, um den Stepper blockierend in die Startposition zu fahren.
Welcher ist das?
runToNewPosition scheint nicht zu funktionieren?!

wapjoe

Mit der Stepper-Funktion kann ich dir nicht helfen, aber wenn ich das richtig sehe kannst du die Hälfte der if-Abfragen einsparen.

Code: [Select]
if (Pos[0] - encoder.getPosition() == 0) {}
usw., wenn Position == 0 dann mache nichts, verstehe ich das richtig, oder soll da noch was passieren? Sonst lass die gleich weg und frag nur > 0 ab.

postmaster-ino

Hi

.runspeedto() oder so müsste Die heißen - kA, ob Da Rampen drin sind - sonst: StateMaschine ginge auch in setup() in einer While ...

Oder: Du machst EINEN Step, prüfst die Entfernung und bei NICHT NULL macht Du EINEN Step, .... wieder While in setup();

MfG
Dein Problem, Dein Sketch, Deine Bilder.
Ob ich ohne Diese an Deinem Problem arbeiten will, entscheide aber immer noch ich.
Große Buchstaben? Immer wieder, neben Punkt und Komma, gerne gesehen.

uwefed

#8
Aug 04, 2019, 01:07 am Last Edit: Aug 04, 2019, 01:17 am by uwefed
Zuerst mal ist ein == bei solchen Sachen sehr gefährlich da da immer eine gewisse Ungenauigkeit drin ist wegen dem ungeraden Verhältnis zu Schritten und Winkelauflösung bzw der geringeren Schrittauflösung gegenüber der Positionsauflösung. Du mußt eine gewisse "Unschärfe" zulassen.
sagst daß ein Winkelfehler von 2-3 Grad annehmbar ist.
Dann weißt Du doch an wechen Zielwert der Motor sich nähert. wenn er von der Position 1 zu 2 bewegt dann brauchst Du Position 0,1 und 3 nicht kontrollieren.

Am Anfang kannst Du das auch einfach in einer Forschleife machen:
for (byte i = 0; i<4; i++)
{
Wenn Istwert ca Pos ist, dann ist die istposition = i.
}

Das ca kann man programmieren indem man kontrolliert ob der Istwert > sollwert - Abweichung && Istwert < sollwert + Abweichung kontrolliert.

Ein Winkel von 2-3 entspricht einem Wert von 23 bis 34 bei einem Encoder von 12 Bit pro Umdrehung.

Grüße Uwe

themanfrommoon

Quote
usw., wenn Position == 0 dann mache nichts, verstehe ich das richtig, oder soll da noch was passieren? Sonst lass die gleich weg und frag nur > 0 ab.
Ist das nicht nur halb durchdacht?
Wenn ich die Situation == 0 nicht abfrage und bei TRUE nicht aus der Abfrage aussteige, so wird dann auch aus == 0 zur nächsten Position gefahren, was ja eigentlich unnötig ist.

Quote
Zuerst mal ist ein == bei solchen Sachen sehr gefährlich da da immer eine gewisse Ungenauigkeit drin ist wegen dem ungeraden Verhältnis zu Schritten und Winkelauflösung bzw der geringeren Schrittauflösung gegenüber der Positionsauflösung. Du mußt eine gewisse "Unschärfe" zulassen.
Warum ist das == sehr gefährlich?

In dem extrem unwahrscheinlichen Fall, dass der Sollwert und der Istwert genau == sind, soll nix passieren. Das ist doch nicht falsch oder gefährlich?! Und genauso funktioniert es.

Bei allen anderen Werten wird die Differenz zur nächsten möglichen Position berechnet und dann dort hingefahren. Und genauso funktioniert es.

Ich hatte noch zwei kleine Rechenfehler drin, aber nun geht's mit der etwas umständlichen if..then..else Verschachtelung.

Hier der funktionierende Sketch, der noch mit einer Menge Debug Ausgaben versehen ist, aber das macht es leichter zu verstehen:
Code: [Select]
#define Microstepping 4                    // Stepperdriver is set to 1/n microsteps (here 1/4)
#define StepperStepsPerRevolution 200           //one revolution of the stepper is 200 steps
int StepsPerRevolution = (StepperStepsPerRevolution * Microstepping);       // results in 800 steps per one revolution of the stepper

#include <AccelStepper.h>
#include <AS5600.h>
int n;
int Pos[4] = {115, 1110, 2172, 3236}; // Der Winkelsensor hat Werte für 0-360° Sensorradposition von 0-4095. Diese vier Werte in dem Array markieren im Wertebereich 0-4095 die Positionen der vier Mulden im Sensorrad
//int Pos[4] = {0, 1024, 2048, 3072}; // Testdaten Absolutpositionen
int RelativeStep[4];
#define STEPpin  14
#define DIRpin   12
unsigned long previousMillis = 0;
unsigned long stepperMillis = 0;
const long interval = 10;
AS5600 encoder;
int output;
AccelStepper stepper(AccelStepper::DRIVER, STEPpin, DIRpin);
void setup()
{
  Wire.setClock(400000L); //setzt die I²C Taktfrequenz auf 400kHz
  Serial.begin(9600);
  stepper.setMaxSpeed(500); // 10000 ist wunderbar
  stepper.setAcceleration(100000); // 100000 ist schön schnell, 200 ist schön langsam

  RelativeStep[0] = (map(Pos[1], 0, 4095, 0, StepsPerRevolution)) - (map(Pos[0], 0, 4095, 0, StepsPerRevolution));
  RelativeStep[1] = (map(Pos[2], 0, 4095, 0, StepsPerRevolution)) - (map(Pos[1], 0, 4095, 0, StepsPerRevolution));
  RelativeStep[2] = (map(Pos[3], 0, 4095, 0, StepsPerRevolution)) - (map(Pos[2], 0, 4095, 0, StepsPerRevolution));
  RelativeStep[3] = StepsPerRevolution - (map(Pos[3], 0, 4095, 0, StepsPerRevolution));

  delay(100);
  Serial.println("");
  Serial.println("Start");
  Serial.print("Ist-Position: ");
  Serial.println(encoder.getPosition());
  if (Pos[0] - encoder.getPosition() == 0) {
    Serial.println("Steht bereits auf Startposition");
  }
  else if (Pos[0] - encoder.getPosition() > 0) {
    Serial.print("Pos0 ist am naechsten: ");
    Serial.println(Pos[0]);
    Serial.print("fahre weiter steps: ");
    Serial.println(Pos[0] - encoder.getPosition());
    stepper.runToNewPosition(map(Pos[0] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
  }
  else if (Pos[1] - encoder.getPosition() == 0) {
    Serial.println("Steht bereits auf Startposition");
  }
  else if (Pos[1] - encoder.getPosition() > 0) {
    Serial.print("Pos1 ist am naechsten: ");
    Serial.println(Pos[1]);
    Serial.print("fahre weiter steps: ");
    Serial.println(Pos[1] - encoder.getPosition());
    stepper.runToNewPosition(map(Pos[1] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
  }
  else if (Pos[2] - encoder.getPosition() == 0) {
    Serial.println("Steht bereits auf Startposition");
  }
  else if (Pos[2] - encoder.getPosition() > 0) {
    Serial.print("Pos2 ist am naechsten: ");
    Serial.println(Pos[2]);
    Serial.print("fahre weiter steps: ");
    Serial.println(Pos[2] - encoder.getPosition());
    stepper.runToNewPosition(map(Pos[2] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
  }
  else if (Pos[3] - encoder.getPosition() == 0) {
    Serial.println("Steht bereits auf Startposition");
  }
  else if (Pos[3] - encoder.getPosition() > 0) {
    Serial.print("Pos3 ist am naechsten: ");
    Serial.println(Pos[3]);
    Serial.print("fahre weiter steps: ");
    Serial.println(Pos[3] - encoder.getPosition());
    stepper.runToNewPosition(map(Pos[3] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
  }
  else {
    Serial.print("Pos0 ist am naechsten: ");
    Serial.println(Pos[0]);
    Serial.print("fahre weiter steps: ");
    Serial.println(4095 - encoder.getPosition() + Pos[0]);
    stepper.runToNewPosition(map(4095 - encoder.getPosition() + Pos[0], 0, 4095, 0, StepsPerRevolution));
  }
  Serial.print("Ist-Position: ");
  Serial.println(encoder.getPosition());
}

void loop() {
}

uwefed

Quote
In dem extrem unwahrscheinlichen Fall, dass der Sollwert und der Istwert genau == sind, soll nix passieren. Das ist doch nicht falsch oder gefährlich?! Und genauso funktioniert es.
Daß Istwert gleich Sollwert ist kann auch nie passieren.

Aus der anderen Diskussion entnehme ich:
Motor Winkelauflösung: 200 Schritte pro umdrehung und 1/4 Microschritte das sind 800 Schritte pro Umdrehung.
Das entspricht einem Winkel von 0,45° pro Schritt.

Die Auflösung des Encoders ist 4096 Schritte pro Umdrehung.

Das heißt daß pro Motorschritt der Encoder 5,12 Schritte hat. Da ist ein zusammentreffen der gelesenen Werte  mit dem Sollwerten für die Position ein Zufall.

Grüße Uwe

themanfrommoon

Quote
Da ist ein zusammentreffen der gelesenen Werte  mit dem Sollwerten für die Position ein Zufall.
Ja das stimmt.
Aber wenn es mal so sein sollte (was natürlich extrem unwahrscheinlich ist) dann soll eben nix passieren.

Also ist das doch nicht falsch?!
Nur eben extrem unwahrscheinlich.

Wenn ich die Zeile weglasse und zufällig Istwert = Sollwert sein sollte, dann würde der Stepper die nächste Position anfahren, obwohl dies nicht nötig wäre.

Oder hab ich da irgendwo noch einen Denkfehler drin?!

uwefed

Quote
Aber wenn es mal so sein sollte (was natürlich extrem unwahrscheinlich ist) dann soll eben nix passieren.
Aber wenn zB der Wert 1 drüber oder drunter ist dann hat es keinen Sinn daß der Motor sich dreht weil dadurch wieder viel drunter oder drüber (in diesem Fall 4 Encoderschritte) posizioniert. Das weil jeder Motorschritt 5 Encoderschritte entspricht.

Grüße Uwe 

themanfrommoon

Da hast du natürlich auch Recht.
Wie baut man das denn geschickt auf?

uwefed


Go Up