Forum: Mikrocontroller und Digitale Elektronik PIDT1-Regler implementieren


von malte (Gast)


Lesenswert?

Hallo!

Ich hab das folgende Problem schonmal in einem anderen Forum gepostet, 
leider konnte mir dort niemand helfen. Ich versuche es hier also mal.

Ich habe bereits an verschiedenen Stellen PID-Regler auf AVRs 
implementiert und verwendet - sonderlich schwierig ist das ja auch 
nicht. Allerdings muss ich zugeben, dass ich mir die Sache nie ganz zu 
Ende überlegt habe, auch wenn mir der D-Anteil schon immer irgendwie 
etwas seltsam vorkam ;-). Erst vor kurzem wurde mir also klar: Das 
Problem bei einem "digitalen D-Anteil" ist ja wohl, dass er immer nur 
instantan wirken kann, also von Sample zu Sample. Ändert sich die 
Regelabweichung von einem Sample n(t) zum nächsten Sample n(t+1), wirkt 
sich der D-Anteil nur zum Zeitpunkt t+1 aus. Das ist ja eigentlich 
nicht Sinn der Sache. Wie ich jetzt durch einiges Nachlesen 
herausgefunden habe, setzt man bei einem "realen" digitalen Regler nicht 
einen einfachen D-Anteil, sondern einen DT1-Anteil ein, also ein 
D-Glied, das einen exponentiellen Abfall aufweist - ein analoges D-Glied 
verhält sich ja immer so.

Mir geht es nun darum, einen solchen PIDT1-Regler (ich nenne ihn mal 
so...) korrekt zu implementieren. P- und I-Anteil sind hier 
unproblematisch. Meine Herangehensweise für DT1 war schlicht: DT1 müsste 
ein einfacher Hochpass sein, den man in diesem Anwendungsfall am besten 
als rekursiven Filter implementiert. Also habe ich da nochmal 
nachgelesen und komme zu dem Ergebnis:
1
out(i) = a0 * in(i) + a1 * in(i-1) + b1 * out(i-1)

Wobei in(i) das Eingangs- und out(i) das Ausgangssignal zum Zeitpunkt i 
sind.

Ich habe außerdem gelesen, dass man die Zeitkonstante des DT1-Gliedes 
auf Tv/4 stellt (wobei kp, Tn und Tv ja empirisch aus einer 
Sprungantworten ermittelt werden). Wie ich aus der gewünschten 
Zeitkonstante die Parameter a0, a1 und b1 bestimme, ist mir klar. Somit 
kann ich den nötigen Hochpass umsetzen. Ich poste hier erstmal etwas 
Pseudocode von meiner Idee zur Implementierung:

1
do
2
   //aktuelle regelabweichung
3
   e = soll - ist;
4
   
5
   //P-Anteil
6
   P = e * kp;
7
   
8
   //I-Anteil
9
   I = esum * ki * ta;
10
 
11
   //DT1-Anteil
12
   //grundlage: out(i) = a0 * in(i) + a1 * in(i-1) + b1 * out(i-1);
13
   DT1 = a0 * e + a1 * ealt + b1 * DT1;
14
   
15
   //zu PIDT1 kombinieren
16
   PIDT1 = P + I + DT1 * kd;
17
   
18
   esum = esum + e;
19
   ealt = e;
20
loop

Die Werte Ki und Kd sind hier die Gewichte für die einzelnen Glieder des 
Reglers, die man ja neben Kp empirisch mittels klassischen 
Einstellregeln bzw. durch probieren bestimmen kann. ta ist die 
Abtastzeit (also der zeitl. Abstand zwischen zwei Samples). Qualitativ 
sieht die Sprungantwort meines Reglers korrekt aus. Mein Problem ist 
jetzt aber folgendes: Ich bin mir unsicher, ob die Dinge auch 
quantitativ stimmen, ob also die Werte, die ich aus den typischen 
Parametrisierungsverfahren erhalte, den DT1-Anteil korrekt gewichten. 
Ist es also korrekt, wenn ich, analog zum PID, den DT1-Anteil nochmal 
mit kd gewichte? So habe ich es im Code getan, wie man sieht. Täte man 
das nicht, würde ja nur die Zeitkonstante des DT1-Gliedes von kd (bzw. 
Tv) abhängen, aber nicht, wie stark der DT1-Wert in den Stellwert 
eingeht.

Ich hoffe ich habe mich halbwegs verständlich machen können, ich würde 
mich wirklich freuen, wenn jemand die Mühe auf sich nehmen könnte, die 
Sache einmal im Detail nachzuvollziehen. Wenn ansonsten niemand so recht 
Lust hat, sich durch den Gedanken zu wurschteln - was ich verstehen 
könnte - wäre mir auch schon mit einem kleinen Stück Code geholfen, egal 
welche Sprache, der einen PIDT1-Regler korrekt implementiert. Den könnte 
ich dann mit meinem Machwerk vergleichen.

Ganz vielen Dank schonmal!
Malte

von Alex97 (Gast)


Lesenswert?

Hi,
ich stand vor dem gleichen Problem ein DT1-Element zu implementieren.
Ich habe es wie unten beschrieben umgesetzt und es funktioniert soweit 
auch ganz gut.

Bin mir aber nicht sicher, ob das alles so korrekt ist...
1
Die Grundfunktion für ein DT1-Element lautet ja:
2
T1*(dy(t)/dt) + y(t) = KD * (dx(t)/dt)
3
4
Diese habe ich in eine Differenzengleichung umgewandelt:
5
T1*(y(k)-y(k-1))/TTakt + TTakt*y(k) = KD * (x(k)-x(k-1))/TTakt
6
7
Diese muss jetzt nur noch nach y(k) aufgelöst werden:
8
y(k) = [KD(x(k) - x(k-1)) - T1 * y(k-1)]/( T1 + TTakt)
9
10
k entspricht immer dem aktuellen Wert
11
k-1 ist der vorherige Wert
12
TTakt ist die Zykluszeit, in welcher der Regler aufgerufen wird

Ich hoffe das hilft dir weiter

Gruß
Alex

von Frank (Gast)


Lesenswert?

> Ändert sich die Regelabweichung von einem Sample n(t) zum nächsten Sample 
n(t+1), wirkt sich der D-Anteil nur zum Zeitpunkt t+1 aus. Das ist ja eigentlich 
nicht Sinn der Sache

Wieso nicht? So ist nun mal eine Ableiutung definiert. Wenn sich 
allerdings deshalb nichts ändert, weil die Auflösung zu niedrig ist, 
würde ich eher daran arbeiten - oder die Zykluszeit erhöhen.

von kwasposer k. (kwasposer_k)


Lesenswert?

zu Alex97:

ich bin der Ansicht , dass die diskrete DGL nach x(k) umgestellt werden 
muss, da y(k) der Ausgang ist bzw. die Regelabweichung e(k)=w(k)-y(k)

x(k) ist doch die Stellgröße u(k), oder?

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.