Hab versucht einen PID-Regler in VHDL zu basteln, als Vorlage diente ein
Mathlab Block Diagramm.
Die jeweiligen Anteile sollen durch vorgegebene Werte für Kp, Ki, Kc
festgelegt werden. Da jetzt mein Problem, ich kann ja nicht mit 0.5 oder
0.1 rechnen. Wie kann ich das umgehen, bzw. zum Laufen bekommen ?
Hab gedacht man könnte real benutzen, geht aber wohl nicht -.-
Dennis Lindner schrieb:> Da jetzt mein Problem, ich kann ja nicht mit 0.5 oder> 0.1 rechnen. Wie kann ich das umgehen, bzw. zum Laufen bekommen ?
In VHDL-2008 gibt es auch Festkomma-Zahlen, also sfixed und ufixed. Die
können auch kleiner 1 sein.
Falls du mit signed auskommen willst, musst du deine k-Faktor mit 2**n
multiplizieren und zum Schluss von deiner Stellgröße n-Bit weglassen.
Tom
Thomas Reinemann schrieb:>> In VHDL-2008 gibt es auch Festkomma-Zahlen, also sfixed und ufixed. Die> können auch kleiner 1 sein.>> Falls du mit signed auskommen willst, musst du deine k-Faktor mit 2**n> multiplizieren und zum Schluss von deiner Stellgröße n-Bit weglassen.
Wenn ich jedoch mein Faktor, der 0.1 ist mit 2**n multipliziere, dann
komm ich ja auch nicht auf einen Integer Wert ohne zu runden. ?_?
Dennis Lindner schrieb:> Wenn ich jedoch mein Faktor, der 0.1 ist mit 2**n multipliziere, dann> komm ich ja auch nicht auf einen Integer Wert ohne zu runden. ?_?
Willkommen in der Welt der binären Arithmetik.
Auf
http://www.h-schmidt.net/FloatApplet/IEEE754de.html
kannst du dir Single Gleitkommazahlen zusammen klicken, versuche mal
eine 0.1 hinzubekommen?
Selbst dein vor dir stehender PC kann es nicht. Du kannst die
Rundungsfehler nur minimieren.
Unabhängig davon, woher weißt du, dass du einen Reglerkoeffizienten von
0.1 brauchst? Ich gehe mal davon aus, dass du den willkürlich festgelegt
hast. Früher hat man Reglerkoeffizienten mit einem Poti eingestellt,
alleine dessen Temperaturdrift war größer als der Rundungsfehler in
binärer Arithmetik. Und der Rundungsfehler ist bekannt und konstant.
Tom
Also wenn ich das Richtig verstanden habe, dann multipliziere ich meine
faktoren mit 2**n, dann hab ich ein integer, notfalls gerunden, und dann
rechne ich mit dem integer und dividiere dann am ente wieder mit 2**n ?
Dennis Lindner schrieb:> Also wenn ich das Richtig verstanden habe, dann multipliziere ich meine> faktoren mit 2**n, dann hab ich ein integer, notfalls gerunden, und dann> rechne ich mit dem integer und dividiere dann am ente wieder mit 2**n ?
Im Großen und Ganzen: Ja.
Oder du machst es wie so, dass du deinen Integer-Zahlenbereich statt auf
-214783648..+214783647 (= -2^31--.2^31-1) als -1..+0,99999999
definierst.
Dann ist 10000000_00000000_00000000_00000000 = -1
und 00000000_00000000_00000000_00000000 = 0
und 01111111_11111111_11111111_11111111 = +0,99999999953
Und du bleibst auch bei Multiplikationen immer im definierten Bereich,
denn -0,5*-0,5 = +0,25... ;-)
So ist es. Mit der Wahl von n kannst du den Rundungsfehler beeinflussen.
je größer n umso kleiner der Rundungsfehler. Je nach FPGA können die
Multiplizierer 18 oder 25 Bit Faktoren verarbeiten. Da ist dann die
Grenze. Da dein AD und DA Wandler aber sicher nicht mehr als 16 Bit
haben, reicht das aber auch aus.
Achso, 0.1 kann man doch mit einer Gleitkommazahl in einfacher
Genauigkeit darstellen. Dazu braucht man aber alle 23 Bit der Mantisse.
Tom
Danke erstmal, jetzt bekomm ich beim compilieren eine fehlermeldung mit
der ich nichts anfangen kann.
Error (10511): VHDL Qualified Expression error at pid3.vhd(79): RESIZE
type specified in Qualified Expression must match std_logic_vector type
that is implied for expression by context
Die entsprechende Zeile dazu:
1
y_m<=resize(y_o,16);
Damit wollte ich das signal y_m (18bit) auf 16 bit kürzen, das soll für
ein antiwindup am ende des reglers sein.
Dennis Lindner schrieb:> Die entsprechende Zeile dazu:y_m <= resize(y_o, 16);>> Damit wollte ich das signal y_m (18bit) auf 16 bit kürzen, das soll für> ein antiwindup am ende des reglers sein.
Der Quellcode wäre schon gut.
Woher soll resize wissen, wo die Bits weg sollen?
y_m <= y_o (y_m'high downto y_m'high - y_o'high);
Tom
Jetzt fällt mir erst auf, dass es wohl nicht so einfach funktioniert, da
ich ja mit signed arbeite und wenn man da einfach nur die stellen kürzt,
dann kommt ggf. einfach mal -1 raus.
Nun bin ich total verwirrt und nichtmehr sicher wie ich das mit den
werten nun machen soll -.-
Hab den Quellcode mal angehängt
Dennis Lindner schrieb:> ich ja mit signed arbeite und wenn man da einfach nur die stellen kürzt,> dann kommt ggf. einfach mal -1 raus.
Sag ich doch: du mußt deinen Zahlenbereich anders definieren, und am
unscheinbaren, unwichtigen hinteren Ende (LSB) abschneiden.
Wie kann ich denn meinen Zahlenbereich definieren?
Naja am ausgang also y soll ja maximal den wert 1 haben bei einer breite
von 16 bit, durch die addition vorher könnte ja ein größerer wert
entstehen und den will ich begrenzen und die differenz dann rückführen.
Dennis Lindner schrieb:> Naja am ausgang also y soll ja maximal den wert 1 haben bei einer breite> von 16 bit, durch die addition vorher könnte ja ein größerer wert> entstehen und den will ich begrenzen und die differenz dann rückführen.
Das ist stupide Rechentechnik: du addierst die beiden Zahlen und wenn
ein Übertrag ins nächste Bit passiert, dann sättigst du den Wert auf 1.
Dennis Lindner schrieb:> Hab den Quellcode mal angehängt
Den hab ich mir mal angesehen. Zwei Fragen habe ich
1. Wie hoch ist die Samplingfrequenz?
2. Wie hoch ist die Taktfrequenz?
Tom
Vielen Dank für die Hilfe.
Jetzt hab ich noch ne Frage zu ModelSim, kann ich mir mein
Ausgangssignal, also y irgendwie als Pegel darstellen lassen, dort
sollte dann ja ein Anstieg zu sehen sein, momentan seh ich nur die 16
bits und dort kann man zwar erahnen, dass der wert weiter ansteigt, aber
gibt es noch eine variante das besser auszugeben?
Thomas Reinemann schrieb:> Den hab ich mir mal angesehen. Zwei Fragen habe ich>> 1. Wie hoch ist die Samplingfrequenz?> 2. Wie hoch ist die Taktfrequenz?>> Tom
Bin gerade etwas verwirrt, welche Frequenzen du genau meinst.
Also dem Regler hab ich jetzt erstmal ein Takt von 5 MHz gegeben, wird
aber sicher noch weiter runter gehen, weil mein ADC nicht alle 200 ns
neue Werte liefert.
Desweiteren musste ich noch was ändern am Code, weil sonst Fehler in der
Simulation aufgetreten sind.
Deshalb jetzt so:
Dennis Lindner schrieb:> Bin gerade etwas verwirrt, welche Frequenzen du genau meinst.>> Also dem Regler hab ich jetzt erstmal ein Takt von 5 MHz gegeben, wird> aber sicher noch weiter runter gehen, weil mein ADC nicht alle 200 ns> neue Werte liefert.
Aus der Samplingfrequnez des ADC ergibt sich eine Frequenz, mit der der
Regler die Stellgröße berechnet. Normalerweise startet man den Regler
einmal für jedes neue Sample. Dann hast du aber bei deinem von dir
programmierten Regler eine Totzeit von drei Samplen
1. Takt Berechnung der drei Anteile P, I und D des Reglers
2. Takt Summierung der drei Anteile
3. Takt Korrektur und Ausgabe
Das ist nicht der Sinn eines Reglers im FPGA. Du kannst auch nicht
einfach den Regler dreimal auf ein Sample loslassen, weil
1. du dreimal integrierst
2. der D Anteil zwei mal Null ist
Grundsätzlich ist dein yi falsch, da in die Berechnung von yi(k) bei dir
yi(k-2) eingeht. Denn yi(k) = f[yi_alt(k-1)] und yi_alt=f[yi(k-1)].
Du musst dir eine FSM schreiben, die mit dem Mehrfachen deiner
Samplingfrequenz läuft. Diese FSM wird mit jedem neuen Sample einmal
gestartet und arbeitet alle Rechenschritte ab, bevor das nächste Sample
da ist.
z.B. so
Zustand 0
auf Sample warten
Zustand 1
Regelabweichung berechnen
Zustand 2
yp, yi, yd und aw berechnen
Zustand 3
yo berechnen
Zustand 4
ym ausgeben
und nach Zustand0 zurück
Tom
Dennis Lindner schrieb:> momentan seh ich nur die 16> bits und dort kann man zwar erahnen, dass der wert weiter ansteigt, aber> gibt es noch eine variante das besser auszugeben?
Vielleicht hilft Dir: RMT -> Format -> Analog
Duke
Thomas Reinemann schrieb:>> Grundsätzlich ist dein yi falsch, da in die Berechnung von yi(k) bei dir> yi(k-2) eingeht. Denn yi(k) = f[yi_alt(k-1)] und yi_alt=f[yi(k-1)].>
Ich habe so aus einem Block Diagramm von Matlab übernommen, da wird für
die Berechnung yp mit delay genommen, also yp(k-1) und am ende wird
dieser wert dann zusammen mit dem vorherigen addiert.
Danke für den Tip mit der FSM
Wie kann ich denn eine Begrenzung erreichen?
Mein Problem:
maximalwert für y = 0111_1111_1111_1111
Durch die Addition passiert es aber, dass y = 1000_0100_0001_0100
was ja einem Wert nahe dem Minimum entspricht.
Wie kann ich das abfangen oder verhindern??
Hab meine Frage selbst beantwortet, dafür war das Antiwindup ja auch
gedacht, man sollte es nur richtig einbauen ;)
Werd mal versuchen das Ganze nun noch in eine FSM zu verpacken.
Schönes Wochenende
Thomas Reinemann schrieb:> Du musst dir eine FSM schreiben, die mit dem Mehrfachen deiner>> Samplingfrequenz läuft. Diese FSM wird mit jedem neuen Sample einmal>> gestartet und arbeitet alle Rechenschritte ab, bevor das nächste Sample>> da ist.
Wie kann ich das denn am besten steuern, mit dem Sample?
Hatte erst gedacht, ich frage ab, ob sich ein Eingangswert ändert, aber
es kann ja auch sein, dass diese sich nicht ändern.
Mir fehlt jetzt gerade eine passende Idee wie ich das mache.
Dennis Lindner schrieb:> Wie kann ich das denn am besten steuern, mit dem Sample?
Du legst eine Samplingrate fest. Mit der liest du den ADC aus und
startest den Regler.
Tom
Mein Problem ist da nur, dass ich die Samplerate im ADC noch nicht
festgelegt habe.
Mache ich das über ein extra taktsignal? wenn ja, ich bekomm meinen
internen Takt, 80MHz nicht auf einen passenden Wert, ich würde gerne von
1-250 kHz variieren können.
Wenn ich die Samplerate hätte wär es natürlich kein Problem diese auch
im PID Regler zu nutzen.
Dennis Lindner schrieb:> Mein Problem ist da nur, dass ich die Samplerate im ADC noch nicht> festgelegt habe.
Dann mach das doch mal.
> Mache ich das über ein extra taktsignal?
Das hängt von Deinem ADC und dessen Ansteuerung ab.
> wenn ja, ich bekomm meinen> internen Takt, 80MHz nicht auf einen passenden Wert, ich würde gerne von> 1-250 kHz variieren können.
Dann leg doch das ganz erstmal auf 250 kHz aus. Da hättest Du 320 Takte
Zeit bis zum nächsten Sample (bei 80 MHz FPGA-Takt).
Duke