Für das nachfolgende System 3. Ordnung, bestehend aus el. Widerständen und Kondensatoren, liegt ein Zustandsraummodell vor.
Die Bauteile genügen den Bedingungen:
\[ R_1 = R_2 = R_3= R \quad R_4 = R_e \quad C_1 = C_2 = C_3 = C \quad \quad T = RC \]Das Zustandsraummodell der RC-Schaltung ist:
\[ \left[ \begin{array}{c} \dot{x}_1 \\ \dot{x}_2 \\ \dot{x}_3 \end{array} \right] = \begin{bmatrix} -(2/T+1/(CR_e)) & 1/T & 0\\ 1/T & -(2/T+1/(CR_e) ) & 1/T \\ 0 & 1/T & -(1/T+1/(CR_e))\end{bmatrix} \left[ \begin{array}{c} x_1 \\ x_2 \\ x_3\end{array} \right] + \left[ \begin{array}{c} 1/T \\ 0 \\ 0\end{array} \right] u_{ein}\]Das Modell wird in Python mit Bauteildaten wie folgt dargestellt
import numpy as np import control as ct import matplotlib.pyplot as plt # Regelstrecke in Zustandsraumdarstellung C = 100e-6 # Kond R = 10e3 # Widerstand 1, 2 und 3 Re = 1200e3 # Rein ADW 1,2M R4 = 100e3 # Widerstand 4 T = R*C T2 = C*Re Am = np.array([[-(2/T + 1/T2), 1/T, 0], [1/T, -(2/T + 1/T2), 1/T], [0, 1/T, -(1/T + 1/(Re*C))]]) bm = np.array([[ 1/T],[0],[0]]) cmt = np.array([ [0], [0], [1]]) # transponierter Ausgangsvektor für Ackermannformel CC = np.identity(3) D = np.zeros((3,1)) RC3 = ct.ss(Am, bm, CC, D, name='rc3',inputs='u', outputs=['y1','y2','y3'])
Der Entwurf des Beobachters setzt die Vorgabe der Dynamik voraus (siehe im Buch ab S. 256).
# Beobachterentwurf p = -1/0.7 # Vorgabe Dynamik/Pole # Rückkoppelvektor mit Hilfe der Formel von Ackermann berechnen h = ct.acker(Am,cmt,[p,p,p]) # Bildung Eingangsmatrix Beobachter bo = np.zeros((3,2)) bo[:,0]=bm.T bo[:,1]=h DD = np.zeros((3,2)) #Beobachtermodell bmod = ct.ss(Am, bo, CC, DD, name='beob',inputs=['u','e'], outputs=['x1','x2','x3'])
Für die Simulation werden Strecke und Beobachter zusammengeführt:
# Bildung Fehlersignal sumblk = ct.summing_junction(inputs=['y3', '-x3'], output='e') # Strecke mit Beobachter Sb = ct.interconnect([RC3,sumblk, bmod ], inplist='u', outlist=['y1','y2','y3','x1','x2','x3','e']) t=np.arange(0,30,0.05) ww = np.ones(len(t)) x0 = [0.4,0.4,0.4,0,0,0] # Vorgabe Anfangswerte t, yy = ct.input_output_response(Sb, t, ww,x0,solve_ivp_method='BDF') plt.figure() plt.plot(t,yy.T) plt.title('Beobachter für RC3R') plt.xlabel('t [s]'); plt.ylabel('alle x') plt.grid() #plt.figure() # plot step x ohne Beobachter #plt.plot(t,y[:,0,:].T) # Diskretisierung Beobachter modd = ct.c2d(bmod,0.1) print(modd)
Das nachfolgende Bild zeigt die Sprungantwort aller Zustände der Strecke mit Beobachter. Die Strecke wurde mit gleichen Anfangswerten versehen (0,4), der Beobachter (Anfangswerte alle 0) schätzt aber nach ca. 5 Sek. alle Zustände korrekt. Die Vorgabe einer schnelleren Beobachterdynamik (z.B. mit p =-1/0,4) verbessert das Verhalten deutlich.
Ein Beobachter wird in der Praxis nicht so glatte Zeitverläufe aufweisen, jedoch die Zustände gut schätzen können. Das folgende Beispiel zeigt die gemessenen Werte des RC-Netzwerks und die Reaktion des Beobachters, der mit microPython auf einem esp32 realisiert wurde. Die Zustände des RC-Netzwerks starten bei ca. 0,4 Volt, die Beobachterzustände starten bei 0 Volt.