Modellierung von SSelfDef-Elementen vom Typ PostProcessing

Im Gegensatz zum Typ Measurement arbeitet der Typ PostProcessing mit Vektoren. Erstmal werden alle
Eingangs-Vektoren mit den VoltInput-Samples Zeitschritt für Zeitschritt gefüllt, um dann am Ende mit
einem Schlag alle Ausgabe-Vektoren zu berechnen. Der Block #Measurement wird hier nicht benötigt, an
dessen Stelle tritt der Block #PostProcessing. Zusätzlich ist noch der Block #DefineVectors notwendig,
um alle Ausgabe- und Hilfsvektoren zu definieren.

Modellierung Spectral-Analyser:

Wir wollen nun einen Scope konstruieren, der das Real- und Imaginärspektrum der Eingangsspannung
Ui in 2 Kurven darstellen soll:

   

Um aus einem Zeit-Signal X(t) ein Spektrum Y(f) zu gewinnen, müssen wir natürlich eine Fourier-Transformation
durchführen. Diese ergibt sich für den diskreten Fall bekanntermaßen wie folgt:

Dabei ist X[ ] der komplexe Eingangsvektor und Y[ ] der komplexe Ausgabevektor.
Um diese Transformation sehr schnell zu rechnen, benutzt ToneCirc die Fast-Fourier-Transformation (FFT).

Für die FFT gibt es eine Spezialfunktion mit der Syntax:   $FFT(N, Xre, Xim, Yre, Yim)

Dabei sind N die Tab-Anzahl, Xre/Xim der reelle bzw. imaginäre Eingabevektor und Yre/Yim der reelle bzw.
imaginäre Ausgabevektor. Die Vektoren müssen mit der Länge N definiert worden sein und stehen für die 
Indizes 0...N-1 zur Verfügung.

Bei Xre tragen wir den Eingangsspannungs-Vektor ein, bei Xim muß ein 0-Vektor eingesetzt werden (Dummy).
Typisch für eine Zeitfunktion ist nämlich, dass deren Imaginär-Teil immer gleich 0 ist.
Um ein amplituden-gerechtes Spektrum zu erhalten, müssen wir das Ergebniss der FFT mit gewissen Faktoren
multiplizieren:

Dem X-Vektor weisen wir noch die Frequenzen zu:

Die Frequenzen ab N/2 benötigen wir nicht, da sich dort das konjungiert-komplexe Spektrum des ersten Teils
befindet (Spiegelung).

Nun, theoretisch hätten wir alles geklärt und kommen zum Script:

#VarsAndConstants
N = g_numtimesteps
df = 1/g_timerange
fak = 2/N
#End

#InputVolts
ui = 1,2, Rmu
#End

#CurveDefs
y1 = Real Voltage, YELLOW, 2
y2 = Imag Voltage, GREEN, 2
#End

#DefineVectors
ure    = N, 0.0
uim    = N, 0.0
ui_im = N, 0.0     ;Dummy for FFT xim
y1      = N/2, 0.0
y2      = N/2, 0.0
x        = N/2, 0.0
#End

#PostProcessing
$FFT(N, ui, ui_im, ure, uim)
y1[0] = fak/2*ure[0]
y2[0] = 0 ;fak/2*uim[0]
$FOR i=1 TO N/2-1
    y1[i] = fak*ure[i]
    y2[i] = fak*uim[i]
    x[i] = i*df
$ENDFOR
#End

Hier der vollständige Script von Voltage_RealImagSpec.sselfdef.

Bei #VarsAndConstants berechnen wir mit Hilfe der globalen Variablen g_numtimesteps und g_timerange die
Tab-Anzahl N, die Frequenzauflösung df und den Faktor fak.

zu #DefineVectors:
Hier müssen alle Ausgabe-Vektoren (in #CurveDefs definierte Y-Symbole und X) sowie alle Hilfs-Vektoren
initialisiert werden. Die InputVolts sind per default Vektoren der Länge g_numtimesteps (Eingangsvektoren).
Eine Zeile hat folgende Syntax:
<Vektor-Symbol> = <Länge>, <Initialisierungs-Wert für alle Elemente>

zu #PostProcessing:
Hier findet die eigentlich Berechnung der Ausgabe-Vektoren aus den Eingangs-Vektoren statt. In diesem
Beispiel wird erst eine FFT mit dem Eingangsvektor ui durchgeführt. In den Hilfsvektoren ure und uim wird
das Ergebniss-Spektrum abgelegt. Danach wird aus Diesen der Ausgabe-Vektor für y1 und y2 berechnet.
Auch der Ausgabevektor X bekommt seine Werte zu gewiesen.
Man sieht und staunt, dass hier Programmier-Anweisungen verwendet werden können (siehe Tabelle).

Simulation Spektral-Analyser:

Nun probieren wir diesen Spectral-Analyser aus.
Bitte die Schaltung DocSamples/Test_SpectraScope.circ öffnen:

Wie man eine Spektral-Analyse durchführt, hatten wir alles ja hier schon besprochen. 
Habe auch mal den rechnenden Comment mit rüber kopiert, der die aktuelle Sample-Frequenz und
Frequenz-Auflösung darstellt (werden aus den Settings/AnalyserSettings berechnet).

Nach Ausführung der Dyna öffnen dann folgende Charts:

Da wir bei Sig1 den Phasentyp 0 ausgewählt haben, ist beim Original-Signal-Spektrum nur der Re-Anteil vorhanden.
Die Phase ist also für jede Frequenz 0°. Hinter dem RC-Glied sieht man, dass mit der Frequenz der Betrag abnimmt.
Ab einer bestimmten Frequenz wird der Im-Anteil größer als der Re-Anteil. Diese nennt man Grenzfrequenz (fcut).

Hier ist noch der Script von Voltage_PowSpec.sselfdef zu sehen, der ähnlich aufgebaut ist, nur das hinter der FFT die
Nachbehandlung etwas anders abläuft.

Modellierung Messgerät für Kreuz-Korrelation:

Im diskreten Zeitbereich kann die Kreuz-Korrelations-Funktion folgendermaßen berechnet werden:

Dabei sind U1 und U2 die beiden Eingangsspannungs-Vektoren. Es handelt sich um eine sogenannte Faltung. Ich
habe diesen Formalismus ausprobiert, es funktioniert zwar, aber dauert sehr sehr lange bis ein Ergebniss berechnet
ist. Aber man kann eine KK-Funktion auch über ein Kreuz-Leistungs-Spektrum berechnen. 
Das geschieht im Kontinuierlichen folgendermaßen:

Zuerst werden die Fouriertransformierten der Eingangs-Signale X(t) und Y(t) gebildet:

Dann wird das KL-Spektrum Sxy und daraus mittels inverser Fouriertransformation die KK-Funktion berechnet:

Wir überführen diesen Formalismus ins Diskrete und Lösen dieses Problem mittels der FFT:

Die beiden reellen Eingangsspannungs-Vektoren werden amplituden-gerecht fouriertransformiert:

Jetzt kann das komplexwertige KL-Spektrum bestimmt werden:

Genau genommen muß für jede Frequenz folgendes gerechnet werden:


Die KK-Funktion in Y1 erhält man dann mittels einer amplituden-gerechten Rücktransformation:

Den zweiten Teil habe ich nur hingeschrieben um zu zeigen, dass man die Faktoren 2/N herausziehen und mit 1/2
verrechnen kann. Wir machen also immer reine FFT's und multiplizieren das Endergebniss dann mit 2/N^2.

Im Grunde genommen macht die KK mit FFT das Selbe, wie die KK in Time, nur dass hier die Faltung mittels
schneller Fouriertransformation durchgeführt wird. Deswegen spricht man ja auch von schneller Faltung.

Hier noch das Symbol mit den Eingangsspannungen:

  

Wir können nun endlich in den Script schreiben:

#VarsAndConstants
N = g_numtimesteps
dt = g_timestep
fak = 2/(N*N)
#End

#InputVolts
u1 = 1,2, Rmu
u2 = 3,4, Rmu
#End

#CurveDefs
y1 = Correlation, YELLOW, 2
#End

#DefineVectors
u1fre = N, 0.0
u1fim = N, 0.0
u2fre = N, 0.0
u2fim = N, 0.0
xim = N, 0.0    ;Dummy for FFT xim, yim
Sre = N, 0.0
Sim = N, 0.0
y1 = N, 0.0
x = N, 0.0
#End

#PostProcessing
;CrossPower-Spectrum S
$FFT(N, u1, xim, u1fre, u1fim)
$FFT(N, u2, xim, u2fre, u2fim)
$FOR k=0 TO N-1
    Sre[k] = u1fre[k]*u2fre[k] + u1fim[k]*u2fim[k]
    Sim[k] = u1fim[k]*u2fre[k] - u1fre[k]*u2fim[k]
$ENDFOR

;IFT
$FFT(N, Sre, Sim, y1, xim) 
$FOR i=0 TO N-1
    y1[i] *= fak
    x[i]     = i*dt
$ENDFOR
#End

Ich denke hier muß man nichts mehr dazu sagen. 
Hier der vollständige Script von Voltage_CrossCorrelation_FFT.sselfdef.

Simulation des Kreuz-Korrelations-Analysers:

Bitte die Schaltung DocSamples/CrossCorrelation.circ öffnen:

Ich habe eine Frequenzauflösung von 10Hz und eine Samplefrequenz von 100khz für die Analyse eingestellt.
Der Addierer Def1 summiert auf den Sinus von Sig2 das Rauschen von Sig3 auf und erzeugt so ein verrauschtes
Sinus-Signal. Nebenbei nimmt M2 noch die Häufigkeit, der im Rauschen auftretenden Spannungen, in einem
Hystogramm auf.

Nach Ausführung der Dyna öffnen folgende Charts:

Das erste Fenster zeigt das stark verauschte Signal am Ausgang des Addierers. Das zweite Fenster dagegen zeigt
die Kreuz-Korrelation zwischen dem reinen Sinus und dem verrauschten Sinus an. Sig1 dient gewissermaßen als
Referenz-Signal. Nur ein ungestörtes Signal mit der gleichen Frequenz führt zu einem Korrelationsmaxwert von 1VV.
Es ist zu berücksichtigen, dass der Frequenz-Anteil des Rauschens bei 500Hz mit korreliert wird. Abhängig von der
Amplitude und Phase des Rauschsignals bei dieser Frequenz, variiert der Korrelationsmaxwert um 1VV herum.

Wir machen noch folgendes Experiment. Wir ändern die Frequenz des gestörten Signals auf 490Hz. Wegen der
Frequenzauflösung dürfen nur Vielfache von 10Hz eingestellt werden.
Der Korrelationswert sackt auf 30mVV ab, was dem Rausch-Anteil bei 500Hz entspricht.
Unser KK funktioniert also (bei der Einstellung df = 10Hz) wie ein Filter mit einer Bandbreite von etwa 10Hz.
Genaugenommen ist der KK nichts Anderes, als ein FIR-Filter, dessen Koeffizienten vom Referenz-Signal gespeist
werden. An der Multiplikation der beiden Eingangs-Spektren bei der Berechnung von Sxy, erkennt man die Filter-
Eigenschaft. Im Zeitbereich betrachtet, haben wir es mit einer Mittelung über viele Perioden (hier 500Hz/10Hz = 50)
zu tun. Je größer man TimeRange (T) macht, desto kleiner wird die Frequenzauflösung df = 1/T (und damit diie
Bandbreite), und um so größer die Anzahl der zu mittelnden Perioden. Man könnte auch sagen: Je höher die
Redundanz, desto besser die Filterwirkung, aber um so niedriger die Übertragungsrate. Wenn man eine Schwingung als
Informations-Bit ansieht, dann wird Dieses, hier 50 mal übertragen. Die Übertragungsrate wäre aber höchstens 10Bit/s.

Hier noch das Hystogramm des Rauschens von Sig3:

Man erahnt, dass die Häufigkeit der Spannungen einer Gauss-Verteilung unterliegt.

zur Hauptseite