Forum: Mikrocontroller und Digitale Elektronik Schrittmotor "Live" steurn


von andrea (Gast)


Lesenswert?

Liebe Kompetenzhorde,

Ich will eine Schrittmotor in Echtzeit die Bewegung eines Objekts 
nachvollziehen lassen.

Das Objekt wird über einen Sensor getrackt, der über i2c die x und y 
Koordinaten an einen ATMEGA 328 sendet.


nun soll dieser atmega zwei Schrittmotoren steuern, abhängig von den x 
und y Koordinaten des Objekts.

leider weiß ich einfach nicht wie ich das am besten programmieren soll, 
ohne das es zeitliche Probleme gibt.

ich habe schon einiges probiert, aber nichts läuft präzise.

Sind da Interrupts sinnvoll? wenn ja, kann mir einer erklären wie das 
ungefähr mit Interrupts geht?


Um Anlauframpen mache ich mir keine Sorgen, da das Objekt so träge ist, 
dass der Schrittmotor keine zu großen Beschleunigungen machen muss.

von Michael A. (Gast)


Lesenswert?

Was für eine Schrittmotortreiber/Controller hast/möchtest du einsetzen. 
Davon hängt viel bei der Programmierung ab. Welche Ströme brauchen deine 
Motoren.

andrea schrieb:
> Um Anlauframpen mache ich mir keine Sorgen, da das Objekt so träge ist,

Gerade wenn du ein träges Objekt (=träge Masse) hast, brauchst du die 
Rampen. Das führt allerding zu Problemen, wenn du beim Einleiten eines 
Bremsvorgangs nicht weißt, wo du anhalten möchtest.

Falls du mit "träge" mein, dass sich das Objekt nur langsam bewegt, 
sieht die Sache allerdings einfach aus. "Langsam" wäre dann 
Einzelschrittbetrieb vom Motor.

von eProfi (Gast)


Lesenswert?

Wenn Du ohne Rampen arbeiten willst (was mit einem guten Treiber / Motor 
bis ca. 1 kHz Halbschrittfrequenz gut geht):

StepTimerIRQ:

  if(xIstPos < xSollPos){xStepDir=R;xStepClk=0;}
  else
  if(xIstPos > xSollPos){xStepDir=L;xStepClk=0;}

  if(yIstPos < YsollPos){YstepDir=R;yStepClk=0;}
  else
  if(yIstPos > YsollPos){YstepDir=L;yStepClk=0;}
  delay_us(10); //wenn die StepClk-Puls-Breite zu gering ist
  XstepClk=1;YstepClk=1;



Ich mache das mit linearen Rampen und einem DDS-Positionssteller:
  if((xDist=xSollPos-xIstPos)>0){xSollSpeed= xSpeedMax;}
  else
  if( xDist                  <0){xSollSpeed=-xSpeedMax;}
  else xSollSpeed=0;

  if(xIstSpeed  < xSollSpeed){xIstAccel = xAccelMax;}
  else
  if(xIstSpeed  > xSollSpeed){xIstAccel =-xAccelMax;}
  else xIstAccel = 0;

  xIstPos+=xIstSpeed+=xIstAccel;

Ist eine einfache Form, die ein Überschwingen produziert. Deshalb muss 
die Speed proportional zur Dist heruntergedreht werden, aber das 
überlasse ich Dir.

von Michael A. (Gast)


Lesenswert?

eProfi schrieb:
> Wenn Du ohne Rampen arbeiten willst (was mit einem guten Treiber / Motor
> bis ca. 1 kHz Halbschrittfrequenz gut geht):

Das kannst du nicht so allgemein sagen, da das von der Dimensionierung 
des gesamten Antriebs abhängt. Wie hoch liegt dabei dein Drehmoment auf 
Grund von Massenträgheiten im Vergleich zum Haltemoment des Motors?

von andrea (Gast)


Lesenswert?

Vielen dank erst mal für die Antworten!


Michael A. schrieb:
> Was für eine Schrittmotortreiber/Controller hast/möchtest du einsetzen.
> Davon hängt viel bei der Programmierung ab. Welche Ströme brauchen deine
> Motoren.

ich habe da sowas hier:
http://www.sorotec.de/shop/product_info.php/info/p962_m542-schrittmotorkarte-leadshine.html

Michael A. schrieb:
> Gerade wenn du ein träges Objekt (=träge Masse) hast, brauchst du die
> Rampen.

nicht das Objekt was bewegt werden soll ist träge sondern das Objekt was 
getrackt wird.
Die Wege die der Motor fahren soll sind also von Natur aus Schrittmotor 
freundlich.

das Objekt wird aber auch "schnell". das heißt es sind oft mehrere 
schritte pro Hauptprogrammdurchlauf notwendig. Die Hauptprogrammschleife 
wird dadurch langsam, das die Werte vom i2c Sensor ausgelesen werden 
müssen

eProfi schrieb:
> Wenn Du ohne Rampen arbeiten willst (was mit einem guten Treiber / Motor
> bis ca. 1 kHz Halbschrittfrequenz gut geht):

Sehe ich das richtig, das in deinem Programm der Motor nicht direkt 
gepulst wird sondern nur die soll-Position ermittelt wird?
Ich muss meine Treiber mit einem HIGH / LOW pro schritt füttern und das 
ist mein Hauptproblem.  Die Position des Motors, wird ja permanent durch 
den Sensor vorgegeben.

Wie soll ich so schnell Pulsen und gleichzeitig den Rest erledigen, den 
das Programm machen muss???


Die Motoren sind gut dimensioniert für das was sie beschleunigen müssen. 
Hier liegt nicht mein Problem!

von Michael A. (Gast)


Lesenswert?

Die Erzeugung der Schritte würde ich vollständig im Timer Interrupt 
erledigen, d.h. in der Hauptschleife legst du nur die Richtung fest und 
welche Dauer der/die nächsten Schritte haben sollen. Ein PI-Regler für 
jeden Motor, der in der Hauptschleife aktualisiert wird, ist 
wahrscheinlich die einfachst Lösung dafür. Der Timer kümmert sich dann 
um den korrekten Zeitablauf.

von Michael S. (rbs_phoenix)


Lesenswert?

Ich hätte gesagt, du liest die aktuelle Position aus, berechnest, wo du 
hinmusst und "fährst" in die Richtung. Und das wiederholst du, bis du da 
bist.
Die Frage ist, wie schnell ist deine I2C Verbindung? Wenn du die bis 
oben hin ausreizt, kannst du ja eventuell am Anfang vom Schritt den 
Ausgang halt auf High setzen, die I²C Abfrage machen und danach wieder 
auf Low gehen, dann machst du in der Low-Pause die Berechnung und so 
weiter. 400khz I2C sind für 30bits ~ 3 byte (z.b. Adresse, Befehl, 
Antwort) knapp 75 µs. Wenn du dein Motor mit 1khz taktest, sind das 
500µs High und 500 Low. Also sollte das gehen, solange der Sensor die 
400khz mit macht.

Dazu kommt ja noch, dass du ja theoretisch nicht jede Millisekunde die 
Position brauchst.

edit: Wie bekommst du denn die Position deiner beiden Motoren? Bedenke, 
das manchmal Schritte "verschluckt" werden können, wenn der Motor durch 
irgendwas aufgehalten bzw behindert wird. Da geht reines Zählen nicht so 
gut.

von MaWin (Gast)


Lesenswert?

Im Prinzip macht jede CNC-Software so was.

Viel einfacher als mit Schrittmotoren und AVR wäre es aber gewesen,
wenn ihr die Position des Originalobjekts mit einfachen Potis
erfasst hättet, z.B. Linearpotis, und Servokontroller-ICs an
Gleichstrom(getreibe)motoren einsetzen würdet.

TLE4206 und TDA3629 geht bis 0.8A, MC33030 bis 1A, DRV590/591/593/594 
bis 3A per PWM.

Die machen genau das: Nachführung.

Und wenn man das nun unbedingt mit Inkrementalgeber und Schrittmotoren 
nachbauen muß: Der Analog-IC zeigt wie man's rechnet.

Die Software passt, wenn man's richtig programmiert, egal ob C oder 
Assembler, übrigens auf 1 Bildschirmseite und kommt ohne Interrupts aus, 
profitiert aber wenn sie einn Zeitgeber abfragen kann (sonst muß sie 
halt so geschrieben werden daß jeder Schleifendurchlauf gleich lange 
dauert damit er als Zeitmasstab herangezogen werden kann). Wichtig ist 
daß man nicht nur an langsames Beschleunigen denkt, sondern auch ans 
Abbremsen vor dem Ziel.

von eProfi (Gast)


Lesenswert?

> Sehe ich das richtig, das in deinem Programm der Motor nicht
> direkt gepulst wird sondern nur die soll-Position ermittelt wird?
Nein. Es werden Schrittimpulse (StepClk) generiert, die die Endstufe 
versteht. Es wird nur dann ein StepClk generiert, wenn die SollPos noch 
nicht erreicht ist.

Das Berechnen der sollPos geschieht im Main völlig unabhängig vom 
StepIrq (der soll mit einer Frequenz laufen, die der höchsten 
Geschwindigkeit entspricht).

Würde Dir aber dringend einen Regel-Algo empfehlen, da sonst die 
Bewegung sehr ruckartig vonstatten geht.

von Michael A. (Gast)


Lesenswert?

eProfi schrieb:
> Würde Dir aber dringend einen Regel-Algo empfehlen, da sonst die
> Bewegung sehr ruckartig vonstatten geht

Darum ja:

Michael A. schrieb:
> ... Ein PI-Regler für jeden Motor, der in der Hauptschleife
> aktualisiert wird, ist wahrscheinlich die einfachst Lösung dafür.

von Achim M. (minifloat)


Lesenswert?

Michael A. schrieb:
> Ein PI-Regler für jeden Motor

Sicher, dass das so gut ist? Das zu reglende System ist ja seinerseits 
auch ein I-System, da grob gesagt die Geschwindigkeit des Ritzels am 
Motor integriert die Position ergibt. Aber danke für die schöne 
Regelungstechnik-Aufgabe, Prüfung hab ich in nem Monat :) mfg mf

PS: Eine PT-2-Charakteristik des Gesamtsystems mit entprechender 
Dämpfung wäre doch hier gut, dann gibts garantiert keine Überschwinger 
und der Motor läuft auch sanft an.

von Uwe (Gast)


Lesenswert?

>Ist eine einfache Form, die ein Überschwingen produziert. Deshalb muss
>die Speed proportional zur Dist heruntergedreht werden, aber das
>überlasse ich Dir.

Genau so wie eProfi schrieb hab ich das auch gemacht dadurch ist ein 
Überschwingen unmöglich. Man kann auch andere Reglertypen nehmen jedoch 
schwingen die meißten erst einmal kurz übers Ziehl hinaus bzw. da die 
Gesammtfahrstrecke nicht bekannt ist und auch die Beschleunigung und 
Geschwindigkeit des zu trackenden Objekts sich ständig ändert ist es 
schon etwas schwerer ein ideales Regelsystem zu finden. Wenn dann auch 
noch kein Überschwingen erlaubt ist hat sich dieses System als einziges 
bei mir bewährt

von MaWin (Gast)


Lesenswert?

> Genau so wie eProfi schrieb hab ich das auch gemacht
> dadurch ist ein Überschwingen unmöglich.

Unsinn. Während der Motor bremst kann die Sollposition dem
entgegenkommen, und dann darf man nicht noch schneller
bremsen sondern MUSS überschwingen.
Wenn dein Programm damit nicht zurecht kommt, taugt es nichts.

von Uwe (Gast)


Lesenswert?

Kommt auf die Anwendung an. Bei CNC ist es ungeeignet, schon klar.

von andrea (Gast)


Lesenswert?

hallo

vielen dank für die vielen antworten!

ich setzt mich dann nach her mal rann und probier verschiedene 
vorschlege aus.

Was ich nach wie vor gerne wissen würde, ist wie man das mit 
timer-Interrupts macht.

hat da jemand ein beispiel code?

momentan frage ich alle 0.1 sekunden die i2c daten ab und setze dann 
einen speed, der bis zur nächsten abfrage gehalten wird.

das mach ich mit einer Timer Abfrage, aber leider gehen so immer shritte 
verloren, die ich mit zaehle und dann nach hohle. so stimmt die position 
immer, aber die bewegungen sind ziemlich ungleichmessig.

deshalb will ich mit Interrupts arbeiten, damit da nichts übersprungen 
werden kann, aber wie?

von andrea (Gast)


Lesenswert?

habes es jetzt gut am laufen

jeder Motor hat einen eigenen Timer Interrupt für den speed, der alle 
0.01 Sekunden ermittelt wird.

es ist ziemlich verblüffend wie gut der Schrittmotor z.b. eine 
Handbewegung live ohne Verzögerung nach machen kann.


vielen dank für die Beiträge!

von eProfi (Gast)


Lesenswert?

Schön für Dich, wenn es nach Deinen Vorstellungen klappt. Nur: das Forum 
klappt so nicht, denn es lebt vom Nehmen und Geben. Wäre also schön, 
Deinen Code hier zu finden.

von Daniel (Gast)


Lesenswert?

Hier mal ein Auszug in C-Pseudocode aus einem Regler mit 
Beschleunigungsbegrenzung und Velocity Feedforward für Schrittmotoren:
1
float dt = 0.01; // Periode des Lagereglers in Sekunden s
2
float max_vel = 1000;  // Maximale Geschwindigkeit in steps/s
3
float max_acc = 420;  // maximale Beschleunigung in steps/s^2
4
float max_dv = max_acc*dt; // max Geschwindigkeitsaenderung in einer Periode steps/s
5
float add = 0.5*dt*max_dv;
6
float fak = sqrtf(max_acc*2);
7
8
9
/********* Lageregler ************/
10
pos_err = tgt_pos - act_pos;
11
/* Fehler, der durch die Soll-Geschwindigkeit gegeben ist,
12
   abziehen, damit es nicht zu Ueberschwingern kommt. */
13
pos_err -= tgt_vel*dt;
14
/* cmd_vel für die naechste Periode so berechnen,
15
   dass es zu keinem Ueberschwinger kommt und die gewuenschte
16
   Zielgeschwindigkeit beruecksichtigt wird (Velocity Feedforward). */
17
if (pos_err >= 0)
18
{
19
    cmd_vel = -max_dv + sqrtf(pos_err + add)*fak + tgt_vel;
20
}
21
else
22
{
23
    cmd_vel = max_dv - sqrtf(-pos_err + add)*fak + tgt_vel;
24
}
25
/* Geschwindigkeit begrenzen. */
26
cmd_vel = limitf(cmd_vel, -max_vel, max_vel);
27
/* Beschleunigung begrenzen. */
28
cmd_vel = limitf(cmd_vel, (act_vel - max_dv), (act_vel + max_dv));

Ja, ja ich weiß: mit float und srqt.... Überschwingerer treten natürlich 
in MaWins Fall auf.

von MaWin (Gast)


Lesenswert?

> Überschwingerer treten natürlich in MaWins Fall auf.

Und das ist gut so denn sonst wäre der Code ja auch falsch.

Er sieht durch die defines die auf physikalischen Grunddaten aufsetzen 
auch sehr sauber aus.

Man kann sqrt auch im Integerbereich ausrechnen.
http://home.utah.edu/~nahaj/factoring/isqrt.c.html

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

MaWin schrieb:
> Er sieht durch die defines die auf physikalischen Grunddaten aufsetzen
> auch sehr sauber aus.

Danke für die Blumen ;)

Im Anhang mal Bilder von Simulationen mit dem Regler.
bild1: Ziel bewegt sich mit konstanter Geschwindigkeit
bild2: Ausschnitt aus Bild 1, Motor erreicht Ziel
Ruck2: Regler folgt einer Ruckbegrenzten Trajektorie

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.