Arduino Forum

International => Deutsch => Topic started by: themanfrommoon on Aug 04, 2019, 12:25 am

Title: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 12:25 am
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
Title: Re: 8x verschachteltes if...then...else
Post by: postmaster-ino on Aug 04, 2019, 12:35 am
'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
Title: Re: 8x verschachteltes if...then...else
Post by: wapjoe on Aug 04, 2019, 12:37 am
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.
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 12:38 am
….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());
Title: Re: 8x verschachteltes if...then...else
Post by: Mahimus on Aug 04, 2019, 12:43 am
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++
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 12:54 am
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?!
Title: Re: 8x verschachteltes if...then...else
Post by: wapjoe on Aug 04, 2019, 01:04 am
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.
Title: Re: 8x verschachteltes if...then...else
Post by: postmaster-ino on Aug 04, 2019, 01:06 am
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
Title: Re: 8x verschachteltes if...then...else
Post by: uwefed on Aug 04, 2019, 01:07 am
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
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 01:52 am
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() {
}
Title: Re: 8x verschachteltes if...then...else
Post by: uwefed on Aug 04, 2019, 02:01 am
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
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 02:13 am
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?!
Title: Re: 8x verschachteltes if...then...else
Post by: uwefed on Aug 04, 2019, 02:47 am
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 
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 02:57 am
Da hast du natürlich auch Recht.
Wie baut man das denn geschickt auf?
Title: Re: 8x verschachteltes if...then...else
Post by: uwefed on Aug 04, 2019, 04:06 am
siehe #8
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 10:12 am
#8 hab ich leoder nicht so ganz verstanden, bzw. kann das spontan nicht umsetzen
Title: Re: 8x verschachteltes if...then...else
Post by: noiasca on Aug 04, 2019, 10:30 am
du sollst Code-Duplikate vermeiden und das was du über Iterationen schaffen kannst z.B. in eine For-Schleife packen:

das ersetzt 4 mal

Code: [Select]

  for (byte echtSoSchwer = 0; echtSoSchwer < 4; echtSoSchwer++)
  {
    if (Pos[echtSoSchwer] - encoder.getPosition() == 0) {
      Serial.println(F("Steht bereits auf Startposition"));
    }
    else if (Pos[echtSoSchwer] - encoder.getPosition() > 0) {
      Serial.print(F("Pos"));
      Serial.print(echtSoSchwer);
      Serial.print(F(" ist am naechsten: "));
      Serial.println(Pos[echtSoSchwer]);
      Serial.print(F("fahre weiter steps: "));
      Serial.println(Pos[echtSoSchwer] - encoder.getPosition());
      stepper.runToNewPosition(map(Pos[echtSoSchwer] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
    }
  }
Title: Re: 8x verschachteltes if...then...else
Post by: agmue on Aug 04, 2019, 10:37 am
Gibt es vielleicht eine elegantere Lösung?
Ich denke ja, es ist eine Frage der Formulierung.

... 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.
Der Motor soll sich bewegen, wenn die Ist-Position nicht mit einer der vier absoluten Positionen übereinstimmt. Die boolsche Algebra hilft.

Übrigens ist encoder.getPosition() immer ein zeitaufwändiger Zugriff mittels I2C, das muß nicht sein. Mal ein Versuch:

Code: [Select]
int aktPos = encoder.getPosition();
if( (Pos[0] != aktPos) && (Pos[1] != aktPos) && (Pos[2] != aktPos) && (Pos[3] != aktPos) )
{
  stepper.move(...);
}

Sieht eleganter aus, wenn es dann noch funktioniert ...
Title: Re: 8x verschachteltes if...then...else
Post by: postmaster-ino on Aug 04, 2019, 11:10 am
Hi

Du berechnest zu jeder der Positionen die Entfernung.
Von den ganzen Entfernungen suchst Du Dir die Kleinste aus (und merkst Dir dieses Ziel).
Wenn diese Entfernung kleiner als Deine halbe tolerierbare Abweichung ist: fertig.
(Halbe Abweichung, da Du ja links wie rechts davon stehen kannst und das Ziel in der Mitte liegen soll)
Sonst: Fahrt zum eben gemerkten Ziel, dem Endpunkt, Der der aktuellen Position am Nahesten liegt - nur in die richtige Richtung starten.

MfG
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 11:42 am
@noiasca:
tja, so hab ich am Anfang auch gedacht. So funktioniert es aber leider nicht.
In meinem verschachtelten if..then..else Konstrukt kommt immer nur EINE Aktion zum tragen. Nur ein Ausgang der Schleifen wird TRUE und somit wird nur eine Bewegung gemacht.
In deiner Variante werden je nach aktueller Position bis zu 3 (oder4?!) Positionen neu angefahren.
Die anderen werden nicht verriegelt.

Es soll aber bei jedem Start nur einmal bis zur nächsten der jeweils 4 möglichen Startpositionen gedreht werden.

Man könnte das als switch case bauen, aber dann ist der Aufwand doch noch größer als mit dem if..then..else?!
Oder in deiner Schleife ne flag setzen. Aber dann sind es ja noch mehr if's die durchlaufen werden müssen?!


@agmue:
Das stimmt, daran hatte ich auch schon gedacht, es war etwas quick&dirty die Position mehrfach abzufragen. Da es nur im Setup war hatte ich mal darüber hinweggesehen. Falls das Signal verrauscht sein sollte (war es bis jetzt nicht), könnten da möglicherweise komische Effekte zustande kommen.
Ich baue das also schnell um und frage den Wert wie von dir vorgeschlagen zum Start nur noch 1x ab.

-> muss ich noch machen

@postmaster-ino:
Die Richtung muss prinzipbedingt immer die gleiche sein, ich darf nicht rückwärts drehen, sonst verklemmt etwas oder ist nicht da wo es sein soll.
Bis auf die tolerierbare Abweichung mache ich das ja momentan schon (funktioniert ja auch).
Ein reboot vom ESP scheint leider einen Schritt auszulösen (Messwert steigt um 5 an), daher dreht er bei jedem reboot etwas weiter, ansonsten müsste er ja beim nächsten reboot stehenbleiben, wenn er einmal eine der 4 möglichen Starpositionen erreicht hat und danach nicht weitergedreht hat.

Tatsächlich habe ich momentan den Fall, dass bei Position 0 der Messwert und der Sollwert übereinstimmt und die Meldung "Steh bereits auf Startposition" kommt. Und zwar reproduzierbar bei jeder Umdrehung. ....warte ich mal ein wenig bis der Motor warm wird und der Messwert möglicherweise um 1/4096stel Umdrehung (0,0879°) driftet....
Title: Re: 8x verschachteltes if...then...else
Post by: noiasca on Aug 04, 2019, 11:58 am
@noiasca:
tja, so hab ich am Anfang auch gedacht. So funktioniert es aber leider nicht.
In meinem verschachtelten if..then..else Konstrukt kommt immer nur EINE Aktion zum tragen. Nur ein Ausgang der Schleifen wird TRUE und somit wird nur eine Bewegung gemacht.
In deiner Variante werden je nach aktueller Position bis zu 3 (oder4?!) Positionen neu angefahren.
Die anderen werden nicht verriegelt.

Es soll aber bei jedem Start nur einmal bis zur nächsten der jeweils 4 möglichen Startpositionen gedreht werden.



du kannst gern am ende der zwei IF-Bedingugen mit einem Break aus dem For ausbrechen (und somit "beenden")


Code: [Select]


  for (byte echtSoSchwer = 0; echtSoSchwer < 4; echtSoSchwer++)
  {
    if (Pos[echtSoSchwer] - encoder.getPosition() == 0) {
      Serial.println(F("Steht bereits auf Startposition"));
      break;
    }
    else if (Pos[echtSoSchwer] - encoder.getPosition() > 0) {
      Serial.print(F("Pos"));
      Serial.print(echtSoSchwer);
      Serial.print(F(" ist am naechsten: "));
      Serial.println(Pos[echtSoSchwer]);
      Serial.print(F("fahre weiter steps: "));
      Serial.println(Pos[echtSoSchwer] - encoder.getPosition());
      stepper.runToNewPosition(map(Pos[echtSoSchwer] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
      break;
    }
  }
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 12:13 pm
nope, nu läufts gar nicht mehr
….Debugging...

Er bleibt in der 4. Position hängen, weil die sich anders berechnet

1,2 und 3 funktionieren

0-3 geht so:
Code: [Select]
stepper.runToNewPosition(map(Pos[0] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
stepper.runToNewPosition(map(Pos[1] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
stepper.runToNewPosition(map(Pos[2] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
stepper.runToNewPosition(map(Pos[3] - encoder.getPosition(), 0, 4095, 0, StepsPerRevolution));
4 geht so:
Code: [Select]
stepper.runToNewPosition(map(4095 - encoder.getPosition() + Pos[0], 0, 4095, 0, StepsPerRevolution));
Title: Re: 8x verschachteltes if...then...else
Post by: themanfrommoon on Aug 04, 2019, 12:47 pm
Ich habs jetzt so:
Code: [Select]
  int StartupPos = encoder.getPosition();
  if ( (Pos[0] != StartupPos) && (Pos[1] != StartupPos) && (Pos[2] != StartupPos) && (Pos[3] != StartupPos) ) {
    if (Pos[0] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[0] - StartupPos, 0, 4095, 0, StepsPerRevolution));
    }
    else if (Pos[1] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[1] - StartupPos, 0, 4095, 0, StepsPerRevolution));
    }
    else if (Pos[2] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[2] - StartupPos, 0, 4095, 0, StepsPerRevolution));
    }
    else if (Pos[3] - StartupPos > 0) {
      stepper.runToNewPosition(map(Pos[3] - StartupPos, 0, 4095, 0, StepsPerRevolution));
    }
    else {
      stepper.runToNewPosition(map(4095 - StartupPos + Pos[0], 0, 4095, 0, StepsPerRevolution));
    }
  }


Das hat nun zwar die Hysterese noch nicht drinnen, aber es funktioniert so wie ich es brauche, und ich denke es ist ausreichend kurz und ausreichend übersichtlich.
Title: Re: 8x verschachteltes if...then...else
Post by: agmue on Aug 04, 2019, 12:57 pm
@noiasca:
In deiner Variante werden je nach aktueller Position bis zu 3 (oder4?!) Positionen neu angefahren.
Die anderen werden nicht verriegelt.
Mit break; sieht es gut aus. Ich habe gerade auch etwas Zeit gebraucht, um die Priorisierung in (Pos[echtSoSchwer] - aktPos > 0) zu verstehen. Das ist clever :)

Das hat nun zwar die Hysterese noch nicht drinnen, ...
Mit dem Vorschlag von noiasca geht auch die Hysterese einfach (Testprogramm zur Veranschaulichung ohne Sensor):

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] = {0, 1024, 2048, 3072}; // 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
#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
  Pos[0] = (map(Pos[0], 0, 4095, 0, StepsPerRevolution));
  Pos[1] = (map(Pos[1], 0, 4095, 0, StepsPerRevolution));
  Pos[2] = (map(Pos[2], 0, 4095, 0, StepsPerRevolution));
  Pos[3] = (map(Pos[3], 0, 4095, 0, StepsPerRevolution));
 
  test(400);
  Serial.println(F("-------------"));
  test(603);
  Serial.println(F("-------------"));
  test(597);
  Serial.println(F("-------------"));
  test(222);
  Serial.println(F("-------------"));
}
void test(int aktPos)
{
  const int toleranz = 4;
  for (byte echtSoSchwer = 0; echtSoSchwer < 4; echtSoSchwer++)
  {
    if (abs(Pos[echtSoSchwer] - aktPos) < toleranz) {
      Serial.println(F("Steht bereits auf Startposition"));
      break;
    }
    else if (Pos[echtSoSchwer] - aktPos > 0) {
      Serial.print(F("Pos"));
      Serial.print(echtSoSchwer);
      Serial.print(F(" ist am naechsten: "));
      Serial.println(Pos[echtSoSchwer]);
      Serial.print(F("fahre weiter steps: "));
      Serial.println(Pos[echtSoSchwer] - aktPos);
      stepper.runToNewPosition(map(Pos[echtSoSchwer] - aktPos, 0, 4095, 0, StepsPerRevolution));
      break;
    }
  }
}
void loop() {
}
Title: Re: 8x verschachteltes if...then...else
Post by: uwefed on Aug 04, 2019, 11:03 pm
#8 hab ich leoder nicht so ganz verstanden, bzw. kann das spontan nicht umsetzen
Du mußt kontrollieren ob die Werte des Encoder in einem bestimmten Bereich liegen.
also zB wenn der Wert 1000 sein soll dann kontrollierst Du ob der Istwert größer 1000-10 und kleiner als 1000+10 ist, also zwischen 990 und 1010 liegt.
Grüße Uwe