Forum: FPGA, VHDL & Co. Differenzieren in VHDL


von Dave (Gast)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Niemandundjeder (Gast)


Lesenswert?

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;

von Dave (Gast)


Lesenswert?

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
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Encoder is
6
    Port ( clk : in  STD_LOGIC;
7
           A   : in  STD_LOGIC;
8
           B   : in  STD_LOGIC;
9
           Position : out  STD_LOGIC_VECTOR (31 downto 0);
10
           Geschw : out STD_LOGIC_VECTOR (31 downto 0));
11
end Encoder;
12
13
architecture Behavioral of Encoder is
14
type zustaende is (Z00, Z01, Z11, Z10);
15
signal z : zustaende := Z00;
16
signal p : integer := 0;
17
signal g : integer := 0;
18
signal p_alt : integer := 0;
19
signal i : std_logic_vector(1 downto 0);
20
signal e : std_logic_vector(1 downto 0);
21
begin  
22
  process begin -- Eintakten der asynchronen Signale
23
    wait until rising_edge(clk);
24
    i <= A & B;  -- Zusammenfassen der Eingänge A und B
25
    e <= i;
26
  end process;
27
28
  process      -- Weiterschalten und Zählen
29
  variable cu, cd : std_logic := '0';
30
  begin
31
    wait until rising_edge(clk);
32
    cu := '0'; -- lokale Werte
33
    cd := '0';
34
    case z is
35
      when Z00 => if    (e = "01") then z <= Z01; cu := '1';
36
                  elsif (e = "10") then z <= Z10; cd := '1';
37
                  end if;
38
      when Z01 => if    (e = "11") then z <= Z11; cu := '1';
39
                  elsif (e = "00") then z <= Z00; cd := '1';
40
                  end if;
41
      when Z11 => if    (e = "10") then z <= Z10; cu := '1';
42
                  elsif (e = "01") then z <= Z01; cd := '1';
43
                  end if;
44
      when Z10 => if    (e = "00") then z <= Z00; cu := '1';
45
                  elsif (e = "11") then z <= Z11; cd := '1';
46
                  end if;
47
    end case;
48
    if    (cu='1') then p <= p+1;
49
    elsif (cd='1') then p <= p-1;
50
    end if;
51
   
52
   g <= (p - p_alt);
53
   p_alt <= p;
54
   
55
  end process;
56
57
  Position <= std_logic_vector(to_signed(p,32)); -- Position ausgeben
58
  Geschw <= std_logic_vector(to_signed((g),32)); -- Geschwindigkeit ausgeben
59
end Behavioral;

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?

von Ralf (Gast)


Lesenswert?

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.

von Dave (Gast)


Lesenswert?

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.

von Ralf (Gast)


Lesenswert?

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.

von J. S. (engineer) Benutzerseite


Lesenswert?

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).

von J. S. (engineer) Benutzerseite


Lesenswert?

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.

von J. S. (engineer) Benutzerseite


Lesenswert?

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.

von Dave (Gast)


Lesenswert?

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?

von Thomas R. (Firma: abaxor engineering) (abaxor)


Lesenswert?

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

von T.U.Darmstadt (Gast)


Lesenswert?

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.

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.