TC2 / TC3 Zeitdifferenz für PID Regler mit GetSystemTime()

Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für die Zahlreichen Anmerkungen und Korrekturen.
Ich bekomme die Variante die ich simulieren möchte einfach nicht zum Laufen. Einfach ein PID der auf einer P-T1 Strecke arbeitet.
Ich habe den simpelst möglichen Algortithmus herausgezogen (den fertigen Basis-PID könnte ich nat. nehmen, aber das muss doch zu Fuss hin zu bekommen sein 🙃) und trotzdem viel zu grosse alternierende Werte in der runtime. Erwarten würde ich ein einschwingen auf den Sollwert hier fiktiv eine Drehzahl 400 rpm.
Ich möchte hier Auszüge zeigen, vlt. sieht jemand meinen Gedankenfehler. Ich beschränke mich mal auf die nötigsten Variablen. Initialisierungen und Limitierungen hier mal weggelassen.
Der Ausgang des PID geht auf den Eingang des P-T1. Der Ausgang des P-T1 geht als Istwert auf den Eingang des PID.
Eine Simulation des P-T1 in Excel funktioniert mit eine Sprung auf 400 wie es ein P-T1 soll, weich ansteigen bis auf Sollwert.

Code:
Program Controller
Var
    rpm: REAL :=400; (*Sollwert*)
    TA: REAL:=0.02;  (*  20ms Cycluszeit ist hier nur vereinfacht fest eingesetzt *)
    t: REAL:=0.2;    (* sample intervall*)
    kp: REAL:=1.0;
    ki: REAL:=1.0;
    kd: REAL:=1.0;
    k:  REAL:=1.0;
    PIDout: REAL;
    PT1out: REAL;
END_VAR

Code:
PID(
    w:= rpm,
    x:= PT1out ,
    Ta:= Ta,
    KP:= kp ,
    KI:= ki,
    KD:= kd,
    Y=>PIDout );
  
PT1(
    y:=PIDout ,
    Ta:= Ta ,
    T:= t,
    K:= k,
    RST:= rst ,
    out=>PT1out );


Code:
FUNCTION_BLOCK FB_PID
VAR_INPUT
    w : REAL;
    x : REAL;
    Ta : real;
    KP : REAL;
    KI : REAL;
    KD : REAL;
END_VAR
VAR_OUTPUT
    Y : REAL;
END_VAR
VAR
    e: REAL;
    de: REAL;
    esum: REAL;
    ealt: REAL;
END_VAR

Code:
e:=w-x;
IF Ki > 0 THEN
    esum := esum + e * Ta;
ELSE
    esum := 0;   
END_IF
IF Kd > 0 THEN
    de:= (e-ealt) / Ta;
ELSE
    de := 0;   
END_IF
y := (KP * e) + (KI * esum ) + (KD  * de);
ealt:=e;

Code:
FUNCTION_BLOCK FB_PT1
VAR_INPUT
    y : REAL;
    Ta : REAL;
    T : REAL;
    K : REAL;
    RST : BOOL;
END_VAR
VAR_OUTPUT
        out : REAL;
END_VAR

out := out + (y * K - out) * Ta / T;

1631027564424.png
 
Zuletzt bearbeitet:
... und trotzdem viel zu grosse alternierende Werte in der runtime.
Habe Deinen Code bisher nur überflogen.
Deine Schaltung schwingt anscheinend. Lässt sich das beeinflussen durch Verringern des Wertes von K?

Der "RegelSinn" wird ja wohl nicht falsch herum sein, sonst müsste der ReglerAusgang auf seinem positiven Maximum bzw. negativen Minimum festkleben.

Zu "diese Rahmen":
CodeNF.jpg
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Liegt vermutlich an dem PT1 Glied, ich sehe da keine Zeiteinfluss...


Versuch mal dieses PT1 Bausteinchen basierend auf OSCAT ...


Code:
FUNCTION_BLOCK PT1FB
VAR_INPUT
    in : REAL;
    T  : TIME;
    K  : REAL := 1.0;
END_VAR
VAR_OUTPUT
    out : REAL;
END_VAR
VAR
    last : DWORD;
    tx   : DWORD;
    init : BOOL;
END_VAR

// Code
tx := TIME_TO_DWORD(TIME())*1000;

IF NOT init OR T = T#0S THEN
    init := TRUE;
    out := K * in;
ELSE
    out := out + (in * K - out) * DWORD_TO_REAL(Tx - last) / TIME_TO_REAL(T) * 1.0E-3;
    IF ABS(out) < 1.0E-20 THEN out := 0.0; END_IF;
END_IF;
last := tx;

sepp.JPG
 
Liegt vermutlich an dem PT1 Glied, ich sehe da keine Zeiteinfluss...


Versuch mal dieses PT1 Bausteinchen basierend auf OSCAT ...


Code:
FUNCTION_BLOCK PT1FB
VAR_INPUT
    in : REAL;
    T  : TIME;
    K  : REAL := 1.0;
END_VAR
VAR_OUTPUT
    out : REAL;
END_VAR
VAR
    last : DWORD;
    tx   : DWORD;
    init : BOOL;
END_VAR

// Code
tx := TIME_TO_DWORD(TIME())*1000;

IF NOT init OR T = T#0S THEN
    init := TRUE;
    out := K * in;
ELSE
    out := out + (in * K - out) * DWORD_TO_REAL(Tx - last) / TIME_TO_REAL(T) * 1.0E-3;
    IF ABS(out) < 1.0E-20 THEN out := 0.0; END_IF;
END_IF;
last := tx;

Anhang anzeigen 56161

Mein P-T1 Schnipsel ist aus OSCAT. Aber ist (Tx-last) nicht immer 0,02s also die 20ms Zykluszeit?
Ich habe die ablaufende Zeit hier einfach statisch als (Faktor) übernommen.
In Excel ist Ta und t auch statisch und es rechnet sich ein typischer P-T1 Verlauf. Das entscheidende ist doch der Term
out(neu) := out(alt) + (in * K - out(alt) * (Faktor) oder ? (alt): Wert aus Zyklus davor (neu): Wert aktuell
 
ok funktioniert super jetzt!
Danke Wollvieh, das hier war das entscheidene
...
tx := TIME_TO_DWORD(TIME())*1000;
...
und dann in der Gleichung wieder .... DWORD_TO_REAL(Tx - last) / TIME_TO_REAL(T) * 1.0E-3; statt Konstanten
 
Zurück
Oben