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.
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.
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.
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?
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!
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.
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.
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.
> 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.
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.
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.
>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
> 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.
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?
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!
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.
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.
> Ü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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.