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:
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
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.
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
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);
}
???
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
voidAccelStepper::runToNewPosition(longpos)
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
unsignedintPositions[5]={100,500,300,800,400};
2
unsignedintactPos=0;
3
unsignedcharstartFirst=TRUE;
4
5
voidloop()
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.
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).
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
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.)
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.