Moin,
ich brächte mal Hilfe bezüglich eines Reglerentwurfs in VHDL.
Mein gegenwärtiges Problem : ich bekomme Quadratursignale aus einem
Encoder, die ich in meinen FPGA einlese. Nun möchte ich zusätzlich zu
der Position die Geschwindigkeit aus meinem Encoderblock ausgeben um
beide Größen mit Hilfe eines PID Reglers zu regeln. Jetzt dachte ich,
könnte ich einfach die Position ableiten und hätte dann die
Geschwindigkeit, aber da hab ich wohl falsch gedacht...
Kurzum, wie differenziert, bzw. integriert man in VHDL?
Über Hilfe würde ich mich freuen!
Beste Grüße
Dave
Dave schrieb:> Kurzum, wie differenziert, bzw. integriert man in VHDL?
Vergiss solche abstrakten Begriffe wie "differenzieren" und
"integrieren" und "ableiten" vorerst mal.
Für die Ermittlung einer Geschwindigkeit gibt es pragmatischerweise 2
Wege:
1. man misst die Zeit zwischen 2 Impulsen. Das ist ein wenig blöd, weil
man dann für die Geschwindigkeit erst noch den Kehrwert bilden muss. Und
es ist dumm, dass beim Stillstand die Zeit unendlich wird...
2. man nimmt ein feste Zeit und misst welche Strecke in dieser Zeit
zurückgelegt wird.
Also Geschwindigkeit kann man schon aus dem Weg ermitteln.
Ich schreibe das mal etwas abstahiert:
angenommen du hast einen Takt /sek
Das ganze musst di in einen Process machen, sofern du VHDL nutzt:
diverse Variablen erstmal deklarieren und dann:
geschwindigkeit <= pos_n - pos_n_1;
pos_n_1<=pos_n;
pos_n ist der aktuele Wert,
pos_n_1 der Wert vom letzten Takt.
So erhällst du Quasi die Geschwindigkeit (Weg/Takt)
für den Fall, dass sich das Wegsignal pro Takt zu wenig ändert,
summierst du das Ganze sagen wir 256x auf. Das Ganze Teilst du dann
durch 256 (einfach die letzten 8 bit wegwerfen).
und führst oben das mit dem Ergebnis aus.
Das ist quasi differenzieren....
Integrieren geht ähnlich:
integrierter_wert<=integrierter_wert+neuer_wert;
So in der Art hab ich mir das auch vorgestellt, aber so ganz versteh ich
das noch nicht. Wenn ich das mal an dem Beispielcode von Lothar Miller
festmache, müsste das doch ungefähr so aussehen:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entityEncoderis
6
Port(clk:inSTD_LOGIC;
7
A:inSTD_LOGIC;
8
B:inSTD_LOGIC;
9
Position:outSTD_LOGIC_VECTOR(31downto0);
10
Geschw:outSTD_LOGIC_VECTOR(31downto0));
11
endEncoder;
12
13
architectureBehavioralofEncoderis
14
typezustaendeis(Z00,Z01,Z11,Z10);
15
signalz:zustaende:=Z00;
16
signalp:integer:=0;
17
signalg:integer:=0;
18
signalp_alt:integer:=0;
19
signali:std_logic_vector(1downto0);
20
signale:std_logic_vector(1downto0);
21
begin
22
processbegin-- Eintakten der asynchronen Signale
23
waituntilrising_edge(clk);
24
i<=A&B;-- Zusammenfassen der Eingänge A und B
25
e<=i;
26
endprocess;
27
28
process-- Weiterschalten und Zählen
29
variablecu,cd:std_logic:='0';
30
begin
31
waituntilrising_edge(clk);
32
cu:='0';-- lokale Werte
33
cd:='0';
34
casezis
35
whenZ00=>if(e="01")thenz<=Z01;cu:='1';
36
elsif(e="10")thenz<=Z10;cd:='1';
37
endif;
38
whenZ01=>if(e="11")thenz<=Z11;cu:='1';
39
elsif(e="00")thenz<=Z00;cd:='1';
40
endif;
41
whenZ11=>if(e="10")thenz<=Z10;cu:='1';
42
elsif(e="01")thenz<=Z01;cd:='1';
43
endif;
44
whenZ10=>if(e="00")thenz<=Z00;cu:='1';
45
elsif(e="11")thenz<=Z11;cd:='1';
46
endif;
47
endcase;
48
if(cu='1')thenp<=p+1;
49
elsif(cd='1')thenp<=p-1;
50
endif;
51
52
g<=(p-p_alt);
53
p_alt<=p;
54
55
endprocess;
56
57
Position<=std_logic_vector(to_signed(p,32));-- Position ausgeben
Als Ergebnis für die Geschwindigkeit, wenn ich jetzt mal noch seine
Testbench dazuziehe, kriege ich jetzt als analgoges Signal leider nur 1
bzw. -1 raus, was ja irgendwie auch klar ist, da ich ja nur den alten
vom aktuellen Wert abziehe...was verraff ich denn da?
Das ist ok so, das ist ja das Ergebnis der Differenziation. Bei einem
Analogendocder bekämst du eben aus dem SIN (I-Signal) den COS und aus
dem COS (Q-Signal) den invertierten SIN. Wozu brauchts Du die
Differenziation?
Für einen echten Differenzialquotient reicht das natürlich nicht. Da
musst Du durch die Zeit teilen. Die müsstest du messen und das möglichst
genau.
Also ich denke ich beschreibe mein Prfoblem mal etwas genauer:
Für die Ansteuerung eines Piezomotors soll ein FPGA eingesetzt werden.
Dieser übernimmt sowohl das generieren der Wellenform, als auch das
einlesen und Regeln der Position, als auch der Geschwindigkeit. Wie
bereits geschrieben, liest ein Encoder meine Position aus und gibt das
Quadratursignal an meinen FPGA. Für die Regelung der Position und der
Geschwindigkeit sollen zwei PID Regler zum Einsatz kommen. Nun dachte
ich halt, das ich aus der Position, die ich ja habe, durch "Ableiten"
die Geschwindigkeit errechne, die ich dann dem zweiten Regler übergebn
kann.
Soweit der Plan. Ich wüsste zur Zeit nicht, wie ich anderweitig eine
Geschwindigekitsregelung in VHDL umsetzen könnte, außer halt über den
oben genannten Weg.
Regeln kannst Du nur 1 von beiden! Entweder, du regelst die
Geschwindkeit und nimmst die falsche Postition in Kauf oder Du regelst
die Position und passt die Geschwindigkeit an. Nur 1 von beiden kann
stimmen.
Dave schrieb:> Jetzt dachte ich,> könnte ich einfach die Position ableiten und hätte dann die> Geschwindigkeit, aber da hab ich wohl falsch gedacht...
Du musst durchaus so verfahren, also den Differenzenquotient anstelle
des Differenzialquotienten verwenden. Allerdings hast du in Deinem
AB-Signal (Decoder) durch die Stufigkeit gefaltet mit der Abtastung
bereits Harmonische enthalten, die zuvor gefiltert werden müssen, sonst
erhälst Du als Differenzial mehr Artefakte der Spiegelfrequenzen, also
eigentliche Wunschinformation. Du musst also dein Signal durch einen
Tiefpass geben, dann abtasten und die abgetasteten Werte vergleichen.
Die Differenz / Intervall ist dann der DQ = Delta Y / Delta T (dy/dt).
Die Grenzfrequenz des Filters ist dabei entscheidend. (-Shannon).
Ralf schrieb:> Regeln kannst Du nur 1 von beiden! Entweder, du regelst die> Geschwindkeit und nimmst die falsche Postition in Kauf oder Du regelst> die Position und passt die Geschwindigkeit an. Nur 1 von beiden kann> stimmen.
Das ist jetzt ein wenig Auffassungsfrage! Wenn beides wichtig ist, muss
beides übewacht werden und beides in die Regelschleife einfliessen. Aber
bitte nur mit EINEM Regler, der die Summe zweier (gewichteter) Kriterien
erhält. Würde man zwei Regler nehmen, würden die gegeneinander arbeiten.
Dave schrieb:> Nun dachte ich halt, das ich aus der Position, die ich ja habe,> durch "Ableiten" die Geschwindigkeit errechne, die ich dann dem> zweiten Regler übergebn
Wie Du richtig interpretierst, sind beide eng verknüpft. Von daher
regelst Du dadurch, dass Du einen Parameter steuerst, nämlich die
Beschleunigung! Diese ergibt sich durch die Position Deines
Solldrehfeldes, welches in Anrechnung des Motorwinkels einen Vorlauf
haben muss. Der Vorlauf muss so gross sein, dass die Beschleunigung =
Funktion (Winkeldifferenz, Winkel) - Bremskraft) genau der Änderung der
Steuer-Geschwindkeit ist. Diese musst du BRECHNEN! und zwar so, dass du
einen Kompromiss bildest zwischen der idealen statischen
Sollgeschwindigkeit, die der Motor drehen soll und der fiktiven
Geschwindigkeit, die zum Aufrechterhalt der Position nötig ist.
Du hast also eine Positionsmessung, eine geglättete Position, daraus
eine Geschwindigkeit und daraus eine errechnete Zielposition im nächsten
time step, daraus eine Differenz zwischen Sollposition und
wahrscheinlich erreichter, daraus eine relative Sollpositionsänderung
und damit eine relative Geschwindigkeitsänderung und mit der Strategie
von oben damit eine absolute Geschwindigkeitsänderung und damit eine
Soll-Beschleunigung. Diese setzt Du ins Verhältnis zur IST
Beschleunigung (ebenfalls gemessen) und ermittelst die
Beschleunigungsänderung. Diese führt direkt in die Änderung des
Drehfeldvorlaufs.
Letztens steuerst Du nur also nur einen Parameter, nämlich das Drehfeld.
Alles was unterwegs an Messungen und Kriterien oder Wissen einfliesst,
muss als Strategie in eine Funktion führen, die auf diesen einen
Parameter abgebildet wird.
Je nachdem, wieviel Wissen du noch über das motorische System hast,
(Momente, Verschmutzung, Federwirkung, Resonanz und Steigungen) kannst
du die Änderungen = Differenziale mehr oder weniger gut präzisieren und
feiner = leiser = stromsparender = verschleissärmer und auch schneller
werden. Jeder Fehler, der aus Nichtwissen bei den Änderungen und der
Steuerung gemacht wird, muss ansonsten im nächsten Schritt wieder
weggeregelt werden. Interessant ist hierbei das exakte Wissen über die
Funktion der Beschleunigung in Abhängigkeit des Winkels. Die ist infolge
von Rotationstorsion, Reibung und vor allem Rastmomente nicht trivial.
Mit einem einfachen PID-Regeler gelingt das nur gut, wenn man die
Messungen passend nichtlinear aufarbeitet und den P.I.D. Parametern die
richtigen Werte zuleitet. Ich habe mir seinerzeit ein Motormodell in
VHDL gebaut, um ein ähnlich gelagertes Problem anzugehen.
Eines wollte ich noch bringen: Um zu verdeutlichen, warum zwei Regler
nicht funktionieren: Angenommen, der Motor hängt etwas seiner idealen
Position hinterher, hat aber eine etwas höhere Geschwindigkeit, als er
haben soll. Eine Geschwindigkeitsregelung würde runterregeln. Wenn es es
zwei verkettete Regeler sein sollen, müsste ein langsamer Regler eine im
Vergleich zum Ideal erhöhte SOllgeschwindigkeit vorgeben, damit der
Motor weiter aufholen kann. Das ist nur dann sinnvoll auszulegen, wenn
ein schneller Regler innerhalb einer langsamen Schleife arbeitet. Mit
einem Regler ist das wesentlich einfacher zu kontrollieren.
Moin, erstmal vielen Dank für eure Beiträge. Ich hätte vielleicht noch
erwähnen sollen, dass es sich um einen Linearmotor handelt.
Meine Idee wäre gewesen, eine Position und eine Geschw. vorzugeben, und
der Motor würde dann bis kurz vor die Sollposition nur
Geschwindigkeitsgeregelt und dann ab der Sollposition nur noch
Positionsgeregelt arbeiten. Also wäre immer nur ein Regler aktiv.
Oder hab ich da nen Denkfehler?
Dave schrieb:> Also wäre immer nur ein Regler aktiv.> Oder hab ich da nen Denkfehler?
Ja, für so etwas nimmt man einen Kaskadenregler. Dein äußerer Regelkreis
bekommt die Sollposition und Istposition und liefert eine
Sollgeschwindigkeit. Die geht dann mit der berechneten Geschwindigkeit
an den zweiten Regler. Das Stellsignal des zweiten Reglers geht dann an
den Linearmotor.
Die ganze digitale Regelungstechnik geht von einer zeitlich
äquidistanten Abtastung aus. Dein Encoder liefert aber eine Weg
äquidistante Abtastung. D.h. du musst deinen Weg berechnen und diesen
Wert zeitlich abtasten. Da spielt das rein, was Jürgen oben beschrieben
hat. Jedoch musst du mit dem Filtern vorsichtig sein, da du eine
Regelung hast, die will mit möglichst aktuellen Werten arbeiten. Ewig
lange Filter wirken wie eine Totzeit.
Die Samplingfrequenz muss deutlich größer als die Taktfrequenz sein.
Wenn deine Samplingfrequenz zu hoch ist, ist dein KI zu klein (fast
Null) und dein KD zu groß (fast Eins). Eine Verdopplung der
Samplingfrequenz halbiert KI und verdoppelt KD. Eventuell brauchst du
für deine Regler unterschiedliche Samplingfrequenzen. Normalerweise
simuliert man so einen Regelkreis erstmal mit Matlab/Simulink und gießt
in nicht gleich in einen FPGA.
Viel Erfolg
Tom
Auch wenn es etwas länger her ist, eine kleine Note von Thomas zu
Thomas:
Thomas R. schrieb:> Die ganze digitale Regelungstechnik geht von einer zeitlich> äquidistanten Abtastung aus.
N....ein, das ist durchaus nicht so. Sie geht nur von einer
quantisierten Abtastung aus. Vereinfacht fallen dann die Differenziale
nach der Zeit (größtenteils) weg, was sich bei Rechnungen besonders in
der Komplexität im Nenners niederschlägt.
Generell ist das absolut nicht so, daß man die weglassen könnte und es
macht auch wenig Sinn, besonders im Bezug auf die hier vorgestellte
Abtastproblematik.