PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schrittmotor im Sinus laufen lassen



julius12345
20.06.2011, 02:40
Hallo ihr lieben
Mein Schrittmotor verliert haufenweise schritte und zwar schon im µC Programm.

Ich will einen Schrittmotor im Sinus hin und her drehen lassen. Das ziel ist es mit zwei Schrittmotoren so eine Kreisbewegung zu erzeugen, wobei sich dann die beiden Sinus-Bewegungen zu einem Kreis überlagern.

aber erst mal geht es nur um die X-Achse.
Bei meinem Projekt ist es wichtig, dass die Zeit exakt eingehalten wird. (die Frequenz des Sinus)
Deshalb kann ich nicht wie üblich die Schrittmotoren so ansteuern, dass sie einfach ihre Steps abfahren, bis der Job erledigt ist. (das dauert nämlich nicht immer gleich lange.
Deshalb habe ich Folgendes Programm geschrieben. Es läuft auf einem Arduino bestückt mit einem ATMEGA 320 Was da für ein Schrittmotor Treiber dran hängt ist erst mal egal, da meine Probleme schon im Programm liegen.
Das Programm generiert eine Sinuskurve, die die anzufahrende Position zu einer bestimmten Zeit darstellt. alle 0.1 Sekunden wird diese Position mit der vorherigen abgeglichen und der Motor mit der entsprechenden Geschwindigkeit weiterbewegt, um die nächste Position in der richtigen zeit zu erreichen.
Das ganze funktioniert auch auf den ersten Blick, aber leider gehen viele Schritte verloren.

So ist eine exakte Ansteuerung nicht möglich.

ich gehe mal davon aus, dass das an der Programmlaufzeit liegt, die den Motor Takt durcheinander bringt.

aber wie kann ich das besser programmieren? ich würde mich über Hilfe sehr freuen.
das kann ja nicht so schwer sein ein Schrittmotor exakt im Sinus laufen zu lassen.

hier der code:





int stepperXPin = 13;
int stepperXDirPin = 4;


float i = 0.0000001;
int amplitude = 2000;

int motor_statusX = 0; // motor pin HIGH oder LOW
float stepsX = 0; // Anzahl an Schritten die der Motor im naechsten Intervall fahren soll
int stepCountX = 0; // Anzahl der noch zu fahrenden schritte
float positionOldX = 0;
float positionX = 0;
long previousMillis = 0; // Timer fuer Interval
long zeitaltX = 0; // Timer fuer Motor-Takt


void setup() {
pinMode(stepperXPin, OUTPUT);
pinMode(stepperXDirPin, OUTPUT);
}


void loop()
{

//-----------------Sinus Signal Erzeugung-------------------------//


long interval = 100000; //0.1 sekunden // Aufloesung in der die Sinuskurve in Geraden unterteilt wird.
if (micros() - previousMillis > interval) { // takt für das ubergeben des nechsten sinus werts.
previousMillis = micros();

positionX = ((sin(i)*amplitude)); // erzeugen des sinus signals multipliziert mit der Amplitude (Anzal der Schritte)
stepsX = positionOldX - positionX; // zu gehende schitt anzahl wird ermittet.
stepCountX = abs(stepsX);
positionOldX = positionX;

if(stepsX < 0){ //setting the motor direction
digitalWrite(stepperXDirPin, HIGH);
}
else {
digitalWrite(stepperXDirPin, LOW);
}

i = i+0.1; // der zaehler für die Sinuskurve wird um 0.1 erhoeht. das ergibt bei der Sinus laenge von 2 pi eine Aufloesung von 63 pro Sinus durchlauf
}


//-----------------Motor Steuerung-------------------------//


if(stepCountX > 0){ // solange es noch schritte zu gehen gibt
if (micros() - zeitaltX >= (interval/abs(stepsX*2)) ) { // wird der motor im entsprechenden takt gepulst. (zeit geteilt durch schritte)(schitte mal zwei, da pro Schritt eimal HIGH und LOW geschaktet werden muss

zeitaltX= micros();
if (motor_statusX == 1){
digitalWrite(stepperXPin, LOW);
stepCountX--;
motor_statusX = 0;

}
else
{
digitalWrite(stepperXPin, HIGH);
motor_statusX = 1;
}
}
}

}

021aet04
20.06.2011, 10:12
Welche Last hängt am Schrittmotor? Hast du ein Oszi?

Es gibt verschiedene Möglichkeiten. Das erste wäre ein Fehler im Programm bzw µC. Die 2te Möglichkeit wäre, dass der Motor Schritte verliert, weil er eine zu hohe Last anliegt.

Verwendest du als Takt einen Interrupt? Ich kann keinen erkennen. Um einen exakten Takt zu erzeugen ist es sinvoll einen Interrupt zu verwenden. Je nach Quarz und Presacaler hast du verschiedene Zeiten, die du nutzen kannst.

MfG Hannes

julius12345
20.06.2011, 18:13
der Fehler liegt im Programm.

ja, interrupt wäre sicherlich gut, aber ich habe noch nie damit gearbeitet. wie geht das?
ich kenne das nur, das eine interrupt ausgefürt wird, wenn ein bestimmter imput kommt, also ein imput-pin wird von aussen HIGH oder LOW geschaltet.
bei mir brauche ich es ja genau anders herumm.
Wie geht das?
geht das mit arduino?

hier die Dokumentation von arduinos interrupt Funktion:
http://www.arduino.cc/en/Reference/AttachInterrupt

gibt es irgendwo Beispiel Coder für Schrittmotor Steuerung mit Interrupts?

vielen dank!

Geistesblitz
21.06.2011, 01:23
Also ich würde versuchen, das ganze etwas anders zu lösen. Hab mir jetzt den Code nicht wirklich angeguckt, aber hatte mir darüber schonmal ein wenig Gedanken gemacht. Bei einer Sinusfunktion geht das sogar relativ einfach über die Umkehrfunktion. Um die exakten Schrittzeitpunkte berechnen zu können braucht man eine Funktion der Zeit in Abhängigkeit vom Weg (also anders herum, als gewohnt). Wenn jetzt also meinetwegen x(t)=R*sin(a*t) und y(t)=R*cos(a*t) sind, dann ließe sich t1(x)=asin(x/R)/a und t2(y)=acos(x/R)/a berechnen. t1 und t2 sind die Zeitfunktionen der jeweiligen Achsen, nun könnte man für die x- und y-Werte die aktuelle Schrittzahl*Schrittweite nehmen und wenn man davon die Differenz mit dem nächsten Schritt, also Schrittweite*(aktuelle Schrittzahl+1), nimmt, erhält man immer die nötige Zeitdifferenz zum nächsten Schritt. Was höchstens Probleme machen könnte ist der Rechenaufwand zwischen den einzelnen Schritten, sowie beide Achsen simultan laufen zu lassen. Da fiele mir jetzt aber auch nichts zu ein.

WL
21.06.2011, 13:22
Vielleicht hilft Dir das weiter:
http://www-i1.informatik.rwth-aachen.de/~algorithmus/Algorithmen/algo32/algo32.pdf

Habe ich vor vielen Jahren mal erfolgreich in einer CNC Fräse angewendet.
Bei Kreisformen ist der Frequenzverlauf ziemlich "glatt", so weit ich mich erinnern kann.

Geistesblitz
21.06.2011, 15:17
Das PDF ist sehr interessant, wie hast du das denn in ein Programm für die Schrittmotoren umgesetzt? Erst alle Punkte berechnen lassen oder während der Fahrt "frisch" berechnen?

WL
21.06.2011, 20:59
Der Vorteil dieses Algoritmus ist die einfache (Integer) und damit schnelle Berechnung.
Eine Schleife läuft z.B. für die X-Koordinate und in dieser wird dann die Y-Koordinate berechnet (während der Fahrt).

Das Ganze geht natürlich auch mit Geraden. Dabei ergeben sich aber u.U. (bei entsprechenden Deltawerten) unsaubere Frequenzen die dann unangenehm auf die Motoren wirken (Geräuschentwicklung / Schrittverlust).

Habe das früher mit einem 6502 gemacht. Den Code habe ich leider nicht mehr. :(

Geistesblitz
21.06.2011, 22:32
Interessant^^
Das hieße, dass eine Achse in einer konstanten Geschwindigkeit fährt und die andere sich dann nach der Funktion ausrichtet? Konstante Geschwindigkeit am Endpunkt ist so wohl eher nicht möglich.

Mich interessiert im Grunde, wie man (fast) beliebige Funktionen für die Zeitverläufe recht genau für Schrittmotoren übersetzt. Am interessantesten wäre es wohl, wissenschaftliche Arbeiten dazu zu lesen, irgendwer wird sich doch wohl schon damit beschäftigt haben, allerdings weiß ich nicht, wo ich suchen muss. Glaub nicht, dass sich an unserer Uni schonmal jemand damit beschäftigt hat. Aber es gibt ja schon genügend CNC-Maschinen, die auch komplizierte Kurvenmuster (zB. geschwungene Schrift) sehr genau realisieren, jedoch wird es da wohl eher über nen PC laufen. Ich hör allerdings irgendwie dauernd, dass PCs für Echtzeitverfahren ungeeignet sind...hmmmm

julius12345
22.06.2011, 01:53
hallo,

danke für die antworten!
habe das Problem jetzt gelöst. allerdigs nur für Sinus kurven und andere mathematische funktionen.
Der tip kam vom MaWin aus dem Mikrocontroller.net

hier das Programm:



int stepperXPin = 13;
int stepperXDirPin = 4;

float pi = 3.14159265;

float i = 0.0000001;
int amplitude = 2000;
float frequenz = 3.97;

int motor_statusX = 0; // motor pin HIGH oder LOW
int positionOldX = 0;
int positionX = 0;
long t = 0; // Timer fuer Interval
long zeitaltX = 0; // Timer fuer Motor-Takt


void setup() {
Serial.begin(115200);
pinMode(stepperXPin, OUTPUT);
pinMode(stepperXDirPin, OUTPUT);
}



void loop()


{



t=micros(); // immer nur 1 Aufruf des Zeitgebers in der Schleife!
positionX=sin(t/(100000.0*pi*(frequenz/2)))*amplitude; // sonst unterschiedliche



if(positionX>positionOldX) // Zeiten möglich
digitalWrite(stepperXDirPin, HIGH); // (ich verwende sie eh nur 1x)
else
digitalWrite(stepperXDirPin, LOW);


if(positionX!=positionOldX)
{
if(abs(positionX-positionOldX)>1)
{
Serial.println("cpu zu langsam");
}



digitalWrite(stepperXPin, motor_statusX=!motor_statusX); // Zuweisung!
positionOldX=positionX;
}
}



es läuft die ganze zeit so schnell es geht, und sobald die zu fahrende funktion einen weiteren vollen schritt ergibt wird Dieser sofort ausgeführt.
Leider funktioniert das nur bei mathematischen Funktionen in Abhängigkeit der zeit.
bei x y Koordinaten, die z.b. Wegpunkte sind auf denen zwischendurch interpoliert werden muss geht das nicht.

auch die Berechnungen die man in dem Programm machen kann sind sehr begrenzt, da sonst das zeitlich nicht mehr hin haut. (mehr als ein schritt pro Programm Durchlauf).

WL
22.06.2011, 02:10
Interessant^^
Das hieße, dass eine Achse in einer konstanten Geschwindigkeit fährt und die andere sich dann nach der Funktion ausrichtet?

Richtig !


Konstante Geschwindigkeit am Endpunkt ist so wohl eher nicht möglich.
????
Start- und Endpunkt sollten von einer Rampe eingehüllt sein. ;)

Geistesblitz
22.06.2011, 16:18
Ok, Missverständnis, ich meine nicht den Endpunkt, sondern eher den TCP. Der würde in irgendeiner Geschwindigkeit fahren, da der Geschwindigkitsvektor einen konstanten und einen veränderlichen Anteil enthält. Interessant ist es ja, eine gleichmäßige Geschwindigkeit zu erhalten, wie man es zB. bei Werkzeugmaschinen braucht.

Ostermann
23.06.2011, 16:26
Hallo Willi!


Vielleicht hilft Dir das weiter:
http://www-i1.informatik.rwth-aachen.de/~algorithmus/Algorithmen/algo32/algo32.pdf (http://www-i1.informatik.rwth-aachen.de/%7Ealgorithmus/Algorithmen/algo32/algo32.pdf)


Das ist der Bresenham-Algorithmus. Das ist ein Standard in der Informatik. Dazu sollte sich im Web eine ganze Menge Literatur finden lassen.

Natürlich sind die Frequenzen ziemlich glatt. Die Ableitung des Weges nach der Zeit ist die Geschwindigkeit. Das schöne an sin und cos ist, dass die Ableitungen wieder Winkelfunktionen sind, nämlich cos und -sin...

Mit freundlichen Grüßen
Thorsten Ostermann