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