Forum: Mikrocontroller und Digitale Elektronik Problem AccelStepper Arduino


von Jan V. (ka6cr)


Lesenswert?

Moin moin,
in den letzten paar Wochen habe ich mich ein wenig in die uC-Welt 
eingearbeitet und habe auch schon Erik Bartmann (Die elektronische Welr 
mit Arduino entdecken  [Sehr empfehlenswert!!!]) durch. Nun habe ich 
schon einige kleinere Projekte realisiert und bin nun an einer 
schrittmotorgesteuerten Linearführung dran (siehe CNC Fräse, Drucker, 
Scanner), welche nacheinader versch. Positionen anfahren soll (BSP.: 0mm 
115mm, 560mm, 340mm, 0mm). Dazu habe ich mir den L297/L298 Treiber 
gelötet. So weit so gut, funktioniert alles einwandfrei (z.B. mit dem 
abgewandelten Blink-Programm).

Doch zu meinem Problem: Da die später bewegten Massen bei 0,5kg liegen 
können benötige ich eine Beschleunigungsfunktion im Programm, womit ich 
zur <AccelStepper.h> Libarary komme.

Accel.ino funktioniert super.
Acceltest.ino (Blocking.pde von 
http://www.open.com.au/mikem/arduino/AccelStepper/Blocking_8pde-example.html 
)

funktioniert gar nicht

Lasse ich bei Acceltest.ino die letzte Zeile weg 
(stepper.runToNewPosition(5000);    ), funktioiert es wieder.

Es muss also ein Programmfehler sein, aber ich raff es nicht.

Ich habe versuch mich in die Beschreibung von AccelStepper einzulesen, 
aber ich blicke nicht wirklich durch. Gegoogelt und die Foren durchsucht 
habe ich auch schon, um genau zu sein die letzten 2 Tage.

Es wäre schön wenn mir jemand helfen oder ansatzweiße die AccelStepper 
Lib erklären könnte.


mfg, Jan

Board: Arduino Uno




Accel.ino:
1
#include <AccelStepper.h>
2
3
AccelStepper stepper(1, 12, 10);
4
5
void setup()
6
{ 
7
  stepper.setMaxSpeed(1000);
8
  stepper.setAcceleration(600);
9
}
10
11
void loop()
12
{
13
  if (stepper.distanceToGo() == 0)
14
  {
15
    delay(500);
16
    pos = -pos;
17
    stepper.moveTo(pos);
18
  }
19
  stepper.run();
20
}




Acceltest.ino:
1
#include <AccelStepper.h>
2
3
AccelStepper stepper(1, 12, 10);
4
5
void setup()
6
{ 
7
    stepper.setMaxSpeed(200);
8
    stepper.setAcceleration(100);
9
}
10
void loop()
11
{   
12
    stepper.runToNewPosition(500);
13
    stepper.runToNewPosition(5000);   
14
}

von Jürgen S. (jurs)


Lesenswert?

Jan V. schrieb:
> Es wäre schön wenn mir jemand helfen oder ansatzweiße die AccelStepper
> Lib erklären könnte.

http://www.open.com.au/mikem/arduino/AccelStepper/classAccelStepper.html

Und wenn das nicht hilft, dann eben den Quellcode der Library lesen.

von Jan V. (ka6cr)


Lesenswert?

Hi,
das mit dem Library Quellcode ist so eine Sache. Ich bin recht neu in 
der Materie und das ist für mich schon sehr kompliziert. Den genannten 
Link habe ich schon durch. Ich frage mich nur warum das Example 
Blocking.pde (bzw. .ino ) nicht im Original funktioniert, sondern nur 
wenn ich

void loop()
{
    stepper.runToNewPosition(500);
    stepper.runToNewPosition(5000);
}

zu

void loop()
{
    stepper.runToNewPosition(500);
}

ändere.

mfg, Jan

von Karl H. (kbuchegg)


Lesenswert?

Jan V. schrieb:
> Hi,
> das mit dem Library Quellcode ist so eine Sache. Ich bin recht neu in
> der Materie und das ist für mich schon sehr kompliziert. Den genannten
> Link habe ich schon durch. Ich frage mich nur warum das Example
> Blocking.pde (bzw. .ino ) nicht im Original funktioniert, sondern nur
> wenn ich
>
such dir den Quelltext und sieh nach, wie dir Funktion arbeitet, bzw. wo 
der UNterschied zu der distanceToGo Lösung liegt. Ich würde mal 
erwarten, dass das ganze ähnlich funktioniert.


NB: Die Hinweise in der Doku, das man gewisse Restriktionen einhalten 
muss, hast du gelesen? Zugegeben, die sind ein wenig verstreut, aber 
alles in allem ergibt sich da schon das Bild, dass diese Funktion nicht 
unbedingt die zuverlässigste in der Verwendung in loop() ist.

von Jan V. (ka6cr)


Lesenswert?

Ja,

das mit dem "Dont use this in event loops, since it blocks. " habe ich 
gelesen. Im Example Programm (Blocking.pde) jedoch wird dies nicht 
beachtet und dennoch existieren im I-Net Videos, in welchen der Sketch 
läuft.
Den Library Quelltext kann ich leider nicht interpretieren.

mfg, Jan Verse

von Jürgen S. (jurs)


Lesenswert?

Jan V. schrieb:
> Den Library Quelltext kann ich leider nicht interpretieren.

Das ist schlecht.
Eigentlich sogar schon sehr schlecht, wenn nicht mal die Beispiele zur 
Library fehlerfrei funktionieren.

Aber wie wär's denn damit, dass Du Dir genau anschaust, was zwischen dem 
funktionierenden und dem nicht funktionierenden Beispielprogramm an 
Unterschieden vorhanden ist, und dann tastest Du Dich ran per 
try-and-error?

Was genau heißt denn "funktioniert nicht" eigentlich?
Programm kann vom Compiler nicht compiliert werden?
Programm kann nicht in das Arduino-Board hochgeladen werden?
Motor dreht überhaupt nicht?
Nur die erste Bewegung wird ausgeführt, danach nichts mehr?

Oder was genau?

Was mir z.B. auffällt, ist dass im zweiten Programm gar keine 
Delay-Zeiten drin sind wie im ersten.

Was passiert denn, wenn Du Delays einbaust, z.B.

void loop()
{
  delay(500);
  stepper.runToNewPosition(500);
  delay(500);
  stepper.runToNewPosition(5000);
}


???

von Karl H. (kbuchegg)


Lesenswert?

Jürgen S. schrieb:
> Jan V. schrieb:
>> Den Library Quelltext kann ich leider nicht interpretieren.
>
> Das ist schlecht.
> Eigentlich sogar schon sehr schlecht, wenn nicht mal die Beispiele zur
> Library fehlerfrei funktionieren.


Ausgesprochen schlecht.

Ich lass mal meinen Gedanken freien Lauf (und ich gebe zu, dass einiges 
davon Spekulation ist)

Punkt 1
*******
Wenn ich mir den Funktionsumfang dieser Klasse so ansehe und welche 
Funktionalität da durch anderen Funktionen so bereit gestellt wird, dann 
ist nicht zu erwarten, dass die Funktion runToNewPosition sonderlich 
kompliziert sein wird. Ich erwarte eigentlich, dass die irgendwie so 
aussieht
1
void AccelStepper::runToNewPosition( long pos )
2
{
3
  moveTo( pos );
4
5
  while (stepper.distanceToGo() != 0)
6
    stepper.run();
7
}

irgendwas in dieser Richtung. Vielleicht noch mit dem einen oder anderen 
kleinen Einschub, aber im wesentlichen wirds das sein. WEnn er das nicht 
'interpretieren' kann, dann ... kratze ich mich am Kopf und wundere 
mich.

Punkt 2
*******
Nehme ich die restlichen Hinweise in der Lib ernst, die unter anderem 
auch sagen, dass die Standard-Arduino-loop Funktion nicht zu lange 
blockieren darf, weil sonst die ganze Zeitsteuerung durcheinander kommt, 
dann ziehe ich daraus den Schluss, dass diese Funktion runToNewPosition 
eigentlich gar nicht verwendet werden soll. Anscheinend (zumindest sieht 
das für mich so aus), gibt es da ausserhalb der loop so was wie eine 
Zeitsteuerung, die einen Systemtick auf Software-Ebene bereitstellt, aus 
dem sich dann wiederrum die AccelStepper::run() bedient, um daraus die 
ev. notwendigen Beschleunigungen etc. zu berechnen. Kehrt loop() zu 
lange nicht zurück, dann geschieht da nichts mehr und run kann nicht 
mehr korrekt arbeiten.

Mein Schluss: die Funktion runToNewPosition ist eigentlich eine 
Funktion, die ich gar nicht verwenden will. Wozu auch? distanceToGo 
verrät mir ohnehin alles was ich wissen will, nämlich ob es Zeit ist, 
die nächste anzufahrende Position in den AccelStepper zu laden. Und 
gerade bei einer CNC Steuerung, bei der naturgemäss mehrere Motoren 
gleichzeitig an der Arbeit sind, WILL ich doch gar nicht haben, dass mir 
eine einzige Motorfahrt alle anderen blockiert.

d.h. das Abarbeiten mehrerer Positionen würde sowieso in etwa so 
aussehen
1
unsigned int Positions[5] = { 100, 500, 300, 800, 400 };
2
unsigned int actPos = 0;
3
unsigned char startFirst = TRUE;
4
5
void loop()
6
{
7
  if( startFirst ) {
8
    actPos = 0;
9
    stepper.moveTo( Positions[actPos] );
10
    startFirst = FALSE;
11
  }
12
13
  else {
14
    if( stepper.distanceToGo() == 0 ) {
15
      actPos++;
16
      if( actPos < 5 ) {
17
        stepper.moveTo( Positions[actPos] );
18
      }
19
    }
20
  }
21
22
  stepper.run();
23
}

Wenn mehrere Motoren im Spiel sind, dann wirds trickreicher, weil man 
dann unter Umständen 'zusammenwarten muss', bis alle Motoren ihre 
angestrebte Endposition erreicht haben. D.h. spätestens da ist dann 
diese Funktion runToNewPosition sowieso nicht mehr zu gebrauchen.

Schlussfolgerung: Es ist zwar schade, wenn diese Funktion nicht 
funktioniert. Aber so ein Beinbruch ist das dann auch wieder nicht, weil 
sie sowieso zu nichts zu gebrauchen ist. Und das dürfte auch der Grund 
sein, warum das bisher noch niemandem aufgefallen ist.

von Jürgen S. (jurs)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Schlussfolgerung: Es ist zwar schade, wenn diese Funktion nicht
> funktioniert. Aber so ein Beinbruch ist das dann auch wieder nicht, weil
> sie sowieso zu nichts zu gebrauchen ist.

Na ja, wenn man mit einem Einzeiler im Programm eine schwere Masse per 
Sanftanlauf sanft beschleunigen kann, bis auf maximale 
Stepgeschwindigkeit, die Masse mit Maximalgeschwindigkeit verfährt und 
am Ende eine sanfte Zielbremsung auf den Punkt hinlegt, das hätte wohl 
schon was. Wenn es funktioniert.

Und das mit dem Sanftanlauf und der Sanft-Abbremsung auf Zielpunkt wird 
wohl auch der Grund sein, dass er es mit dieser Library probiert und 
nicht mit der einfachen "offiziellen" Stepper-Library, die nur das 
Verfahren mit konstanter Geschwindigkeit vorsieht (ohne Beschleunigung, 
ohne Verzögerung bei den Verfahrgeschwindigkeiten).

von Jan V. (ka6cr)


Lesenswert?

Hallo,

vielen Dank für eure Antworten.

Jürgen S. schrieb:
> Nur die erste Bewegung wird ausgeführt, danach nichts mehr?

Korrekt.
Das gleiche Problem auch mit dem von Dir vorgeschlagenen Code (delay()).

@ Karl Heinz Buchegger:

Ich muss nur einen Motor bewegen. Ist dir den ein Code bekannt, der den 
Motor mit Beschleunigung/Abbremsung auf bestimmte Positionen bewegt und 
dabei die "normale" Stepper Library einbezieht (ähnl. dem aus deinem 
Punkt 2)
??. Das wäre natürlich super.

Aber scheinbar scheint die Funktion "runToNewPosition" doch irgendwie zu 
funktionieren, da der Stepepr im Video mit dem Sketch Blocking.pde 
läuft.
(   https://www.youtube.com/watch?v=BOwq_bC1Pmk  )

mit freundlichen Grüßen, Jan

von Karl H. (kbuchegg)


Lesenswert?

Jürgen S. schrieb:
> Karl Heinz Buchegger schrieb:
>> Schlussfolgerung: Es ist zwar schade, wenn diese Funktion nicht
>> funktioniert. Aber so ein Beinbruch ist das dann auch wieder nicht, weil
>> sie sowieso zu nichts zu gebrauchen ist.
>
> Na ja, wenn man mit einem Einzeiler im Programm eine schwere Masse per
> Sanftanlauf sanft beschleunigen kann, bis auf maximale
> Stepgeschwindigkeit, die Masse mit Maximalgeschwindigkeit verfährt und
> am Ende eine sanfte Zielbremsung auf den Punkt hinlegt, das hätte wohl
> schon was. Wenn es funktioniert.

langsam
Das macht die Klasse auch so!

Der einzige UNterschied von moveTo und runToNewPosition besteht darin, 
dass moveTo sofort zurückkommt und die eigentliche Bewegung durch 
laufende Aufrufe von run() gemacht wird, während der Aufruf von 
runToNewPosition (laut Doku) erst dann zurück  kommt, wenn die 
Endposition erreicht ist.

Das hat nichts mit Rampensteuerung oder dergeleichen zu tun. Das 
passiert da wie dort.
(Alle Angaben basierend auf der Doku, die ich im Header File der Klasse 
gefunden habe, bzw. den Webseiten, die die Funktionen erklären.)

von Karl H. (kbuchegg)


Lesenswert?

Jan V. schrieb:

> Ich muss nur einen Motor bewegen. Ist dir den ein Code bekannt, der den
> Motor mit Beschleunigung/Abbremsung auf bestimmte Positionen bewegt und
> dabei die "normale" Stepper Library einbezieht (ähnl. dem aus deinem
> Punkt 2)
> ??. Das wäre natürlich super.

Was hindert dich eigentlich daran, die Doku der Lib ZU LESEN?


http://www.open.com.au/mikem/arduino/AccelStepper/classAccelStepper.html

die ist doch nun wirklich nicht schwer zu benutzen.

mit einem Aufruf von moveTo sagst du der Klasse, wo du hinwillst und 
dann wird so oft run() aufgerufen, bis die Position erreicht ist. 
Freundlicherweise teilt dir run das mit dem Return-Wert sogar mit, ob es 
die Position erreicht hat oder nicht.(*)


Nur weil du fertige Klassen benutzen kannst, heißt das nicht, dass du 
nicht mehr mnitdenken musst.



(*) was ich weiter oben beim Codebeispiel mit den 5 POsitionen noch 
nicht wusste. Denn dann wird das ganze sogar noch trivialer.

von Jan V. (ka6cr)


Lesenswert?

Die Lib- Erklärung habe ich gelesen. Bin nur nicht ganz dahinter 
gestiegen.

Ich habe das Programm noch leicht geändert und siehe da, es 
funktioniert.

#include <AccelStepper.h>
AccelStepper stepper(1, 12, 10);
unsigned int Positions[6] = { 1000, 5000, 3000, 5000, 4000, 0 };
unsigned int actPos = 0;
unsigned char startFirst = true;
void setup()
{
  stepper.setMaxSpeed(600);
  stepper.setAcceleration(1500);
}
void loop()
{
  if( startFirst ) {
    actPos = 0;
    stepper.moveTo( Positions[actPos] );
    startFirst = false;
  }

  else {
    if( stepper.distanceToGo() == 0 ) {
      actPos++;
      if( actPos < 6 ) {
        stepper.moveTo( Positions[actPos] );
      }
    }
  }
  stepper.run();
}

mfg, Jan Verse

von Clemens (Gast)


Lesenswert?

Hallo Jan, welche Version der AccelStepper library hast du denn 
verwendet? In den Versionen ab 1.23 gab es einen Bug, s. Changelog auf 
http://www.open.com.au/mikem/arduino/AccelStepper/ der unter gewissen 
Voraussetzungen auch die runToNewPosition()-Funktion betraf, s. 
https://groups.google.com/forum/?fromgroups=#!topic/accelstepper/duqMhFft9OE 
sollte nun, mit der neuen Version 1.26 gefixed sein.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.