Go Down

Topic: Verhalten des AccelStepper (Read 643 times) previous topic - next topic

Demokrit

Hallo zusammen,

ich arbeite an einer schrittmotorgesteuerten Linearachse mit 2 Endschaltern (Home: Limit_M, Limit: Limit_B). Ich nutze AccelStepper, und bin dabei auf etwas verwirrendes gestoßen. Anbei ein Sketchauszug zum Homing und Limiting (Achtung: Nicht nachmachen, hier knallts am Ende):

Code: [Select]
void setup() {
...
...
  stepper.enableOutputs();
  stepper.setMaxSpeed(MAXSPEED); 
  stepper.setAcceleration(ACCELERATION);
  stepper.setSpeed(INIT_SPEED);  // positive
  lcd.setCursor (0, 1); lcd.print(F("*** Initializing ***"));
  homeStepper();
}

void homeStepper() {
  stepper.moveTo(-VERY_BIG);
  initRun = true;
  homing = true;
  lcd.setCursor (0, 2); lcd.print(F("      Homing        "));
}

void limitStepper() {
  stepper.moveTo(VERY_BIG);
  limiting = true;
  lcd.setCursor (0, 2); lcd.print(F("     Limiting       "));
}

void goHome() {
  stepper.moveTo(0.0);
  goingHome = true;
  lcd.setCursor (0, 2); lcd.print(F("    Going home      "));
}

void loop() {
  if (initRun) {
    if (homing && digitalRead(LIMIT_M)) {
      // home position reached, add a little offset to unload the switch
      stepper.setCurrentPosition(-LIMIT_OFFSET);
      homing = false;
      limitStepper();
    }
    if (limiting && digitalRead(LIMIT_B)) {
      // Limit position reached, back up a little to unload the switch
      limitBPos = stepper.currentPosition() - LIMIT_OFFSET;     
      delay(1000); // just to see what happens
      limiting = false;
      initRun = false;
      // Go home
      goHome();
    }
  }

  if (goingHome && (stepper.distanceToGo() == 0)) {
    lcd.clear();
    lcd.setCursor (0, 2); lcd.print(F("       READY        "));
    stepper.setSpeed(0.0f);
    stepper.disableOutputs();
    goingHome = false;
  }

  stepper.run();

}



Limit_M und Limit_B werden erfolgreich gesetzt, dann eine (überflüssige) Gedenksekunde, und bei der Heimfahrt zu Home (0) rattert er in positiver Richtung gegen den Anschlag.

Ändere ich hingegen die goHome() Funktion wie folgt, so klappt alles wie gewünscht:

Code: [Select]
void goHome() {
  stepper.setSpeed(-MAXSPEED);
  stepper.moveTo(0.0);
  goingHome = true;
  lcd.setCursor (0, 2); lcd.print(F("    Going home      "));
}


Was ich nicht verstehe:
Vor dem Homing habe ich eine positive Geschwindigkeit und ein großes, negatives Ziel gesetzt. Ergebnis: Schlitten fährt rückwärts. Alles ist gut.

Beim Limiting habe ich die Geschwindigkeit nicht geändert, und ein großes, positives Ziel gesetzt. Ergebnis: Schlitten fährt vorwärts. Alles ist gut.

Für den Nach-Hause-Weg (Startposition > 150.000) gebe ich als Ziel „0" an, und ohne Definition einer negativen Geschwindigkeit knallt der Schlitten gegen den Anschlag. AccelStepper scheint nicht zu erkennen, dass 0 in rückwärtiger Richtung von 150.000 aus gesehen liegt, und steppt mit voller Kraft voraus. Gleiches geschieht auch, wenn ich statt „moveTo" mit „stepper.move(-stepper.currentPosition())" agiere. Ohne negative Geschwindigkeit krachts.

Kann jemand dieses Verhalten erklären? Beim Homing und Limiting erkennt er aus dem Ziel die Drehrichtung, bei der Heimfahrt zu „0" hingegen nicht. Ein Luxusproblem, denn es läuft ja, aber ich verstehe nicht, wofür die negative Geschwindigkeitsangabe erforderlich ist.

herbk

Hi,
bei den Fahrten zu den Limits hast Du einmal ein "-VERY_BIG" und nur ein "VERY_BIG" , - sieht für mich auch wie eine Richtungsangabe aus.

Demokrit

Ja schon, aber von der Position 176016 nach 0 geht's auch nur rückwärts.
Zudem habe ich als zweiten Test ein relatives, negatives Ziel versucht:

Code: [Select]
stepper.move(-stepper.currentPosition())

Ergebnis: Ebenfalls ein Crash. Auch hier interessiert ihn das Vorzeichen nicht, welches er beim Homing und Limiting akzeptiert.

postmaster-ino

Hi

Ich denke, daß Er hier ABSOLUTE Angaben haben möchte.
Bei einer negativen Zahl ist das oberste Bit gesetzt (und ein paar andere hohen Bits auch) - das ergibt eine sehr sehr große Zahl - zumindest, wenn man Diese VORZEICHENLOS (aka unsigned) interpretiert.
Genau Das wird bei Dir passieren.
Sobald Du eine negative Zahl eingibst, sieht die Lib ein Ziel in weit positiver Richtung, da Sie keine negativen Zahlen kennt.
Das untere Ende wird 0 sein, das obere Ende -1 (also alle Bits gesetzt) - bei 16 Bit wäre Das Position 65535 (0xFFFF).

Lasse Deinen Stepper Mal
Code: [Select]

for (byte t=0;t<10;t++){
   stepper.mov(100);
   stepper.mov(200);
}

Denke, jetzt wird 10x nach Posituin 100 und dann nach Position 200 gefahren.
Beim ersten Mal von 'egal wo', ab dem 2.ten Mal eben von Position 200, da wir Da eben gerade sind.

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.

Demokrit

Es scheint auf jeden Fall so zu sein, dass er bei relativer Positionierung mit negativer Position keine Richtungsumkehr vornimmt, bei absoluter hingegen schon. Letzteres jedoch nur bei negativen Positionen, und nicht bei 0.

Das ist irgendwie inkonsistent, und kann leicht zu heftigem Fehlverhalten führen. Gerade die Fahrt nach 0 (goHome) wird fast jede(r) brauchen.

Ich werde das mal in der Google Gruppe von AccelStepper ansprechen.

Danke für euren Input!

agmue

Code: [Select]
stepper.moveTo(0.0);
Welchen Sinn soll ein float haben?

void moveTo(long absolute);

Da Du uns nicht das komplette Programm zeigst, könnte auch stepper.moveTo(-VERY_BIG); Unsinn sein.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Demokrit

Code: [Select]
stepper.moveTo(0.0);
Welchen Sinn soll ein float haben?

void moveTo(long absolute);

Da Du uns nicht das komplette Programm zeigst, könnte auch stepper.moveTo(-VERY_BIG); Unsinn sein.

0.0 war ein Tippfehler, entstanden aus dem Anliegen, den Code für den Post auf das Wesentliche zu beschränken. "VERY_BIG" ist ein "long int" (größer als die maximale Stepzahl bis zum Limit Schalter). Diesen habe ich statt "__LONG_MAX__"  verwendet, da letzterer nicht funktioniert hat.

Und ja, Unsinn ist nicht auszuschließen. Ich beherrsche PHP, JavaScript und Python, aber C ist für mich noch zu beackerndes Neuland.

agmue

Du hast nicht geschrieben, auf welchem Arduino das Programm laufen soll. Mich überraschen die 8-Bitter immer wieder, gerade bei großen Zahlen, weil standardmäßig mit int gerechnet wird, was int16_t entspricht. Bei long können aus positiven Zahlen leicht mal negative werden, wenn man nicht ganz genau auf die verwendeten Typen achtet. Bei meinem Teensy 3.2 entspricht ein int dann int32_t, da funktionieren manche Programme schonmal mal anders.

Bei einem auf das Problem reduzierten, vollständigen Programm könnten geübte Augen mal nach sowas Ausschau halten. Der Unterschied könnte beispielsweise in 150000 und 150000L liegen.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Demokrit

Aktuell nutze ich einen Uno. Den Code hatte ich schnell zusammengeklöppelt, um auf mein eigentliches Problem (die ausbleibende Richtungsumkehr bei Fahrt nach "0") hinzuweisen. Im tatsächlichen Code nutze ich auch plattformübergreifende Variablendefinitionen.

Ich habe mittlerweile alles komplett neu gemacht. Homing und Limiting gehört eher in den Setup. Dies erspart sämtliche Prozessvariablen, und der Loop bleibt für die eigentliche Anwendung.

Go Up