Ableitung eines zeitlich veränderlichen Wertes bilden

Zuviel Werbung?
-> Hier kostenlos registrieren
Hey Larry,

ähm - also ein kompletter Suchlauf ist leider nicht möglich, nein. Die SPS muss es "on the fly" machen, ansonsten muss man sich eben eine andere regelungstechnische Strategie überlegen, die das möglich macht.
Und wegen Werteglättung - ich habe mich gerade gefragt, ob das tatsächlich nötig ist. Letztenendes vergleichen wir immer zwei benachbarte Werte. Wenn deren Differenz bereits im "Rauschbereich" liegt, dann haben wir den Minimumspunkt bereits mit ausreichender genauigkeit erreicht. Ich habe mir sogar überlegt, den Motor ruhen zu lassen, sobald der zu fahrende Winkel kleiner als 1,8° beträgt. Ansonsten wird er eventuell immer um den Minimumspunkt oszillieren und kommt nicht zu Ruhe.
 
Weil mich das doch interessierte ob das funktioniert, habe ich gerade mal einen Versuch gemacht und die Skizze in Programmcode umgesetzt. Vom Prinzip her findet das Programm den optimalen Punkt :)

Ich habe zum Test eine Regelstreckensimulation programmiert deren Form einer Gaußschen Glockenkurve entspricht. Der Punkt an dem die Stellgröße einen maximalen Istwert annimmt kann man einstellen.
Dieses sind die Kurvenverläufe bei zwei verschiedenen Werten:
Maximaler Wert bei 50% Stellgröße:
strecke50.png
Maximaler Wert bei 70% Stellgröße:
strecke70.png

Die Maximumerkennung habe ich in Form einer Schrittkette programmiert. Es fehlen natürlich noch ein paar Dinge wie Grenzwertüberprüfungen, Zeitumstellungen nur bei Inaktivität ändern etc., aber das Prinzip sollte daraus hervorgehen:
Code:
FUNCTION_BLOCK "Extremwertregler"

VAR_INPUT
    Run : BOOL;                 // Funktion aktivieren
    X : REAL;                   // Istwert
    T_Wart : TIME := T#500ms;   // Wartezeit zwischen Suchfunktionen
    T_Takt : TIME := T#500ms;   // Dauer für welche die Stellgröße nach oben/unten verschoben wird
    T_Paus : TIME := T#500ms;   // Wartezeit zwischen oben/unten
    Gain : REAL := 0.1;         // Verstellverstärkung
    Y_Diff : REAL := 1.0;       // Differenz um die die Stellgröße verändert wird
    Y_Start : REAL := 30.0;     // Startwert für Y
END_VAR

VAR_OUTPUT
    Y : REAL;                   // Stellgröße
    Y_Basis : REAL;             // Bezugs-Stellgröße
    X_Basis : REAL;             // Bezugs-Istwert 
    Sum_UpDn : REAL;
    State : INT;                // Schrittkette
END_VAR

VAR    
    Timer1 : TON;    
END_VAR

BEGIN
IF NOT Run THEN
    State := 0;
END_IF;

(* Schrittkette Suchlauf *)
CASE State OF    
    0:  (* Initialisieren *)
        Y := Y_Start;
        Y_Basis := Y;
        X_Basis := X;
        Sum_UpDn := 0.0;
        Timer1.IN := false;
        IF Run THEN
            Timer1.PT := T_Takt;
            State := 1;
        END_IF;     
    1: (* Stellgröße nach oben fahren *)
        Y := Y_Basis + Y_Diff;
        IF Timer1.IN THEN
            Sum_UpDn := Sum_UpDn + (Y - Y_Basis) * (X - X_Basis);
        END_IF;        
        Timer1.IN := true;        
        IF Timer1.Q THEN
            Timer1.IN := false;
            Timer1.PT := T_Paus;
            State := 2;
        END_IF;
    2: (* Pausenzeit *)
        Y := Y_Basis;        
        Timer1.IN := true;
        IF Timer1.Q THEN
            Timer1.IN := false;
            Timer1.PT := T_Takt;
            State := 3;
        END_IF;
    3:  (* Stellgröße nach unten fahren *)
        Y := Y_Basis - Y_Diff;
        IF Timer1.IN THEN
            Sum_UpDn := Sum_UpDn + (Y - Y_Basis) * (X - X_Basis);
        END_IF;        
        Timer1.IN := true;        
        IF Timer1.Q THEN
            (* neue Basisstellgröße bestimmen *)
            //Y_Basis := Y_Basis + Sum_UpDn * Gain; // << funktioniert nicht so gut
            IF Sum_UpDn >= 0 THEN
                Y_Basis := Y_Basis + Y_Diff * Gain;
            ELSE
                Y_Basis := Y_Basis - Y_Diff * Gain;
            END_IF;
            Y := Y_Basis; 
            Sum_UpDn := 0.0;
            Timer1.IN := false;
            Timer1.PT := T_Wart;
            State := 4;
        END_IF;
    4:  (* Wartezeit für nächsten Durchlauf *)         
        Timer1.IN := true;
        IF Timer1.Q THEN
            X_Basis := X;
            Timer1.IN := false;
            Timer1.PT := T_Takt;
            State := 1;
        END_IF;        
END_CASE;

Timer1();

END_FUNCTION_BLOCK

Wenn in der Regelstrecke eine Zeitkonstante vorhanden ist, muss zwischen den Prüf-Schritten gewartet werden bis sich diese wieder eingeschwungen hat.
Was nicht so gut funktionierte ist die Basis-Stellgröße anhand der Stärke der Reaktion zu verändern (auskommentierter Teil). Es wird jetzt um einen konstanten Wert nach oben/unten verstellt. Dadurch dauert das einregeln relativ lange, da müsste man noch eine bessere Lösung finden.

Und hier mal eine Trendkurve wenn das Programm arbeitet:
Action-3.jpg
Die grüne Linie zeigt die optimale Stellgröße an, das ist der Wert der an der Streckensimulation eingestellt wird.
Wie man sieht wird die Regelrichtung automatisch richtig erkannt. Das Verfahren sollte durch die Integration auch recht unempfindlich gegenüber Messwert-Störungen sein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Thomas,

ja danke vielmals für die Simulation und den Code. Allerdings stört mich noch ein wenig, daß es nicht möglich ist, die Suchschrittweite im Verlauf der Suche anzupassen, damit man schneller zu dem Ergebnis käme. Ich vermute mal, daß der ursprüngliche physikalische Sachverhalt sich sogar tatsächlich durch eine gaußsche Glocke darstellen ließe.
 
Vom Prinzip her macht mein Programm ja nicht mehr als durch das Hoch- und Runtertakten die Steigung der Tangente am aktuellen (Basis- oder Bezugs-) Punkt zu bestimmen.

Das mit der Anpassung der Schrittweite funktioniert darum theoretisch schon (der auskommentierte Teil). Wie gut das funktioniert hängt dabei vom Kennlinienverlauf ab. Zumindest müsste man in der Praxis die Schrittweite nach oben und unten hin auf sinnvolle Werte begrenzen, damit man bei einer Messwert-Störung nicht sofort völlig aus dem Ruder läuft.

Was ich oben nicht dazugeschrieben habe: Die Funktion muss selbstverständlich in festen Zeitabständen aufgerufen werden, ansonsten müsste man die Zeit in die Berechnung noch mit aufnehmen.
 
Mal eine ganz dumme Idee:
Bei einer Analogeingangskarte zB 7KF02 werden die Kanäle in einem MUX umgeschaltet und einem ADU umgerechnet.
Hänge ich das Spannungssignal nun an zwei Kanäle gleichzeitig, sollte ich eigentlich zeitversetzt Werte bekommen, da der MUX und ADU immer eine gewisse Zeit braucht.
Das zusammen in einem schnellen WeckOB und Teilprozessabbild sollte doch bei
Kanal 0 minus Kanal 1 > 0 heissen Wert sinkt
Kanal 0 minus Kanal 1 < 0 heissen Wert steigt

eventuell kann man auch Kanal 2,3,4 oder 7 statt Kanal 1 nehmen (mehr Zeit).

Beim ersten Minuswert habe ich den Tiefpunkt erreicht.....

Glaubt irgendwer, dass das funktionieren kann?
Ich bin mir nicht ganz klar wann die AE-Karte das/die Werte zur Verfügung stellt.....

Gruß
Karl
 
Zurück
Oben