PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PID Regler



hacker
31.10.2006, 12:51
Hallo,

habe vor, einen PID Regler zu implementieren, der meine beiden DC Motoren in der Drehzahl regelt, um ein Synchronlauf zu ermöglichen.

So steht es im rn-wissen:


esum = esum + e
y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta
ealt = e

Jetzt ergeben sich aber noch ein paar Fragen daraus:

1. Wie kann man Ta, die Abtastzeit ermitteln?
2. Durch esum = esum + e werden alle Abweichungen aufaddiert. Wenn es keine Abweichung mehr gibt, muss dann esum auf 0 gesetzt werden, oder wie läuft das im Allgemeinen, sobald die Abweichung "weggeregelt" wurde? Was passiert dann?
3. Oben genannte(r) Algo/Berechnung ist nur für ein Motor. Lasse ich beide getrennt regeln, ists auch nicht das Gelbe vom Ei. Wie verbinde ich die beiden Reglungen? Da muss doch auch die Abweichung von dem einem Motor in die Berechnung der Stellgröße des anderen Motors mit einfließen?


Ich hoffe ihr könnt mir da ein wenig auf die Sprünge helfen.

Danke.

Gruss Hacker

hacker
31.10.2006, 13:18
4. Die Stellgröße wird doch der PWM nachher aufgerechnet, welche aber z.B nur bis max 255 geht. Das heißt doch im Endeffekt, dass der Regler bei Max.Speed gar nicht greift?

voidpointer
01.11.2006, 08:18
Hi Hacker,

ich bin kein Regler-Guru, aber versuche mal, Deine Fragen zu beantworten:

1. Ta ist die Zeit zwischen zwei Messungen der Drehzahl. Die solltest Du kennen, weil Du ja mit einem Sensor die Drehzahl ermittelst. Wenn Du z.B. 10 mal pro Sekunde die Drehzahl ermittelst, dann ist Ta = 0.1
2. kann ich nicht exakt beantworten. Ich würde nichts zurücksetzen, solange nicht von aussen eingegriffen wird. Wenn Du aber im RN-Wissen mal weiterliest, findest Du noch eine andere Formel (mit q0, q1, q2), die ohne esum auskommt. Vielleicht nimmst Du diese.
3. Pro Stellgröße ein Regler. Du hast hier zwei Stellgrößen: Gesamtgeschwindigkeit und Differenz zwischen den zwei Motoeren. Entweder Du benutzt für jeden Motor einen eigenen Regler oder je einen Regler für Basis-Geschwindigkeit und Drehzahldifferenz.
4. Wenn Du einen Regler für die Drehzahldifferenz baust, könnte dieser beide Motoren steuern. Das Ergebnis des Reglers müsste auf die jeweilige Basis-Geschwindigkeit jedes Motors aufaddiert werden. Wenn ein Motor schon auf Vollgas ist, aber noch schneller drehen soll, muss dann eben der andere langsamer laufen. Das sollte man mit einer einfachen if-else-Anweisung hinkriegen.

Gruß, Achim.

hacker
01.11.2006, 17:22
Danke erstmal für deine Erklärungsversuche! :)

Ich bin jetzt auf einer Seite auf folgende Ausdrucksweise gestoßen:


RN = RN-1 + KP · (eN - eN-1) + KI · (eN - eN-1)/2 + KD · (eN - 2 · eN-1 + eN-2)

Aber irgentwie ist bei dieser Berechnung die Abtastzeit gar nicht mehr drin.

Jedenfalls funktionierts doch nach ein paar Versuchen überraschender Weise gut. (mit o.g. "Formel") Ich nehme den Betrag der Differenz der beiden Radimpulse als Abweichung

Jedoch nach ca. 1,5 - 2 Metern fängt der Roboter an, stoßweise zu fahren. Also immer volle Pulle dann sofort wieder beide Motoren aus, dann wieder volle Pulle...usw.
Das liegt ja nehm ich an an den noch nicht richtig gefundenen Werte für Kp, Ki, Kd oder?

Noch eine Frage zu der Abtastzeit, die oben mir scheint nicht mehr in die Berechnung einfließt:

Besser eine kleinere oder größere Zeit nehmen? Ich messe ja die Umdrehung der Räder mit Radencoder, welche mir Impulse liefern. Wieviel Impulse sollte ich ca. pro nächster Berechnung haben? Ihr versteht meine Frage? Reichen da z.B 2-5 oder sollten es schon mindestens 10 sein?

Gruss Hacker

jeffrey
01.11.2006, 18:19
hi,
du hast die möglichkeit deine drehzahl zu bestimmen, indem du die zeit zwischen 2 impulsen misst, oder die anzahl der impulse innerhalb einer festen zeit. bei der 2. möglichkeit ist ta die zeit, in der die impulse gezählt werden.
esum wird nicht auf 0 gesetzt, sondern bleibt wie es ist. es wird dann halt etwas weiter zurückgeregelt, sodass es wieder 0 ist. bei esum spielt die abweichung seit dem start ne rolle. du hast die möglichkeit eine art vergessen einzubauen, indem du esum=0.95*esum+e machst, so werden weit zurückliegende ereignisse schwächer gewichtet.
wenn du die drehzahl differenz als eingang verwendest, bekommt du dann eine pwmdifferenz heraus. du kannst es ja dann so machen, dass du das ergebnis zum einen rad addierst, beim anderen abziehst, und jeweils begrenzst, falls es den maximalen oder minimalen wert überschreitet. wenn du willst, kannst du dann das beim nächsten regeldurchlauf weiterverwenden.
du kannst auch einfach auf ta verzichten, und ki_neu=ki*ta und kd_neu=kd/ta als konstanten verwenden.
dann hast du:
pwmdiff=kp*e+ki_neu*esum*kd_neu*(e-ealt)
dann kannst du mal ungefähre werte für die konstanten abschätzen, wenn du weißt wie groß dein eingangsignal e ist, und wie groß dein ausgangssignal pwm sein soll. ich würde am anfang ki ganz klein, oder sogar 0 wählen.
mfg jeffrey

waste
02.11.2006, 14:57
Noch eine Frage zu der Abtastzeit, die oben mir scheint nicht mehr in die Berechnung einfließt:

Besser eine kleinere oder größere Zeit nehmen?
Die Abtastzeit ist sehr kritisch für die Stabilität des Regelkreises. Sie darf nicht zu groß sein, sonst schwingt die Regelung. Sicherheitshalber also lieber eine kleinere Abtastzeit wählen. Es nützt aber auch nichts, den Berechnungszyklus sehr schnell zu machen, wenn die Information vom Radencoder nur selten kommt. Das muss zusammen passen. Ich würde da auf jeden Fall zur Messung der Zeit zwischen 2 Radencoderpulsen raten, da dies die schnellere Variante ist. Als Faustregel sagt man: Die Abtastzeit sollte mindestens um den Faktor 10 kleiner sein als die gewünschte Regelzeitkonstante (entspricht grob der Einschwingzeit) der Regelung.

Ich messe ja die Umdrehung der Räder mit Radencoder, welche mir Impulse liefern. Wieviel Impulse sollte ich ca. pro nächster Berechnung haben? Ihr versteht meine Frage? Reichen da z.B 2-5 oder sollten es schon mindestens 10 sein? Bei 2-5 Pulse kannst du die Drehzahl auch nur auf ganzzahlige Werte (2, 3, 4 oder 5) regeln. Die Auflösung der Drehzahl ist also sehr grob. Für eine bessere Auflösung dauert es aber wiederum länger um sie zu messen. Deswegen ist es auch aus diesem Grund besser, die Zeit zwischen 2 Encoderpulsen zu messen, weil hierbei die Totzeit am geringsten ist und die Auflösung durch einen entsprechenden Zeittakt meist beliebig gewählt werden kann.

Waste

hacker
02.11.2006, 15:15
Hab ich dich richtig verstanden Waste? Ich soll also nicht als "Einheit" Radencoderimpulse/Zeiteinheit nehmen, sondern Zeit/zw. zweien Radencoderimpulsen ? Ist das richtig so ?

Ich will halt eigentlich im Endeffekt, den Roboter exakt geradeausfahren lassen mit unterschiedlichen Geschwindigkeiten.

Das heißt ich geb einem Regler die Zeit vor, die zwischen 2 Impulsen sein soll. Und ich nehm dann als Abweichung e die Zeitdifferenz ? Dann ein Regler für jedes Rad.

Ich tue den Regelzyklus natürlich mit einem Timer umsetzen. Ist dann die Zeit, wann der nächste Overflow ausgelöst wird Ta in Sekunden?
Und Die Abweichung e ist die Zeitdifferenz der Impulse?

Ich blicks net so ganz. Ich hoffe ihr habt Geduld mit mir ;)

waste
02.11.2006, 16:02
Hab ich dich richtig verstanden Waste? Ich soll also nicht als "Einheit" Radencoderimpulse/Zeiteinheit nehmen, sondern Zeit/zw. zweien Radencoderimpulsen ? Ist das richtig so ?Ja!
Außer, du willst nur in groben Schritten regeln und dein Encoder ist an der Motorwelle angebracht, dann könnte es auch mit der anderen Methode funktionieren. Aber da du von Radencoder schreibst, nehme ich an, dass der Encoder auch am Rad sitzt. Hier wird die Zeiteinheit für die Methode "Radencoderimpulse/Zeiteinheit" zu lange werden um eine genügende Auflösung zu erhalten.

Die Programmierung für die Methode "Zeit/Radencoderimpulsen" ist aufwändiger, muss aber aus den bereits genannten Gründen oft so ausgeführt werden.

Welche Geschwindigkeiten willst du erreichen und welche Auflösung (mm/Tick) hat dein Encoder?

hacker
02.11.2006, 16:25
Gut, dass ich schon mal das eine richtig verstanden habe. 8)

Das heißt der ganze Regler kommt dann in die Interruptroutinen der beiden Radencoder rein, welche immer noch eine zusätzlichen Timer startet und stoppt, oder geht das elleganter?

Über die max. Geschwindigkeit kann ich noch nix aussagen, weil mir ganz oben noch was fehlt, wo ich nicht vorraussagen kann, wie schwer es wird.

Mein Encoder hat 120 Schritte pro einer Umdrehung und mein Rad hat einen Durchmesser von 8,6cm. Das heißt dann ca. 2,25mm/Impuls wären. War es das, was du mit mm/Tick gemeint hast?

waste
02.11.2006, 17:26
Hier ein kleines Zahlenbeispiel für die Problematik bei der Methode "Radencoderimpulse/Zeiteinheit":
Bei einer angenommenen Geschwindigkeit von 1m/s (= 3.6km/h) würde die Zeit/Radencoderpulse bei 2.25ms liegen. Um eine Auflösung von 1% bei der Geschwindigkeit zu haben, müsstest du 100 Radencoderpulse zählen, was dann 225ms benötigt. Diese 225ms sind meiner Meinung nach zu lange, um eine ausreichend schnelle Regelung zu bauen. Willst du aber nur eine Auflösung von 10% bei der Geschwindigkeit, dann reichen schon 10 Pulse aus, was nur 22.5ms Messzeit benötigt. 22.5ms als Abtastzeit wäre andererseits kein Problem für eine Regelung. Es kommt aber auch auf die Anwendung an. Bei höheren Geschwindigkeiten wird die Sache einfacher, bei niedrigeren Geschwindigkeiten wird die Problematik verschärft.

Wo du den Regler mit hineinpackst, ist Geschmacksache. Mach es so, wie es für dich einfacher ist. Ist der Regler in den Interruptroutinen der Radencoder, dann musst du die Abtastzeit Ta, die sich mit den Geschwindigkeiten mit verändert, mit berücksichtigen. Ist der Regler in einer extra Schleife mit konstantem Zyklus, dann kannst du Ta gleich in den Reglerparameter berücksichtigen. Da du die Reglerparameter sowieso durch Probieren ermittelst, ist es da im Prinzip egal welchen Wert Ta wirklich hat.

Waste

jeffrey
02.11.2006, 19:41
hi,
ich würde den regler nicht in den interrup packen, da diese routinen möglichst kurz gehalten werden sollen. ich denke eine totzeit von 50ms sollte noch problemlos für den regler möglich sein, du kannst also die impulse zählen die in 50ms auftreten, und darüber auf die geschwindigkeit schließen, wenn ta nicht konstant ist, sondern sich in geringem rahmen ändert ist das für die regelung auch egal.
mfg jeffrey

Illuminat23
27.04.2007, 10:45
HeHo,
ich sitzte auch nen bissl dran komme aber kein meter vorran...
Hat da jem. vieleicht nen bissl qellcode für einen armen schüler? *fg*

ehenkes
27.05.2007, 17:47
Es gibt da ein älteres Programm von waste, das die Vorgehensweise beim PID-Regler gut zeigt:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=11818&highlight=pid
https://www.roboternetz.de/phpBB2/viewtopic.php?p=285825#285825

Den entscheidenden Teil des Programms, der den PID-Regelalgorithmus abbildet, ziehe ich heraus:


x = don - doff; // Abweichung

yp = x * kp; // P-Anteil berechnen

isum += x;
// Begrenzung um Überlauf zu vermeiden
if (isum > 16000) isum = 16000;
if (isum < -16000) isum = -16000;
yi = isum / 625 * ki; // I-Anteil berechnen

yd = (x - xalt) * kd + drest; // D-Anteil berechnen
if (yd > 255) drest = yd - 255;
else if (yd < -255) drest = yd + 255;
else drest = 0;
y = yp + yi + yd; //Stellgröße des PID-Reglers