S&H, AD-Converter und FIR-Filter als DSelfDef-Script modellieren

Sample&Hold-Element modellieren:

Ein S&H-Element macht nichts Anderes, als bei einer Takt-Flanke die Spannung am Eingang zu speichern,
um Sie am Ausgang bis zum nächsten Takt-Ereigniss anzulegen.
Das Teil sieht so aus:

Schauen wir uns gleich die wichtigen Teile im Script an:

#InputVolts
Uin = 1,0,Rin,Cin
Uc  = 3,0,Rin,Cin
#End

#OutputVolts
Uout = 2,0,0.0,Rout
#End

#StateVars
UZ = 0
#End

#InnerBehavior
Z   = $RisingEdgeTrigger(Uc, Uth, 0)              ;if(Uc > Uth & LH-Edge) Z=1 else Z=0
UZ = {Z > 0 ? Uin : UZ}                                     ;if(Z == 1) UZ=Uin
Uout = UZ
#End

Hier der vollständige Script von SampleAndHold.dselfdef.

zu #InnerBehavior:
Die erste Zeile benutzt die Spezialfunktion $RisingEdgeTrigger, um bei ansteigender Flanke von Uc kurzzeitig
Z = 1 zusetzen. Ansonsten wird Z = 0 (letzter Parameter) zurückgegeben (Sample).
Die zweite Zeile übernimmt bei Z = 1 (Triggerung) Uin nach UZ (UZ = Uin), ansonsten wird UZ beibehalten (UZ = UZ).
Die StateVar UZ speichert also den aktuellen Ausgangs-Wert (Hold).

AD-Wandler modellieren:

Dieser AD-Wandler begrenzt das Eingangs-Signal und führt eine Quantisierung durch. 
Das Teil sieht so aus:

Schauen wir uns gleich wieder die wichtigen Teile im Script an:

#VarsAndConstants
Nq  = 2^BitRes-1
dUq = (Umax-Umin)/Nq
#End

#InputVolts
Uin = 1,0,Rin,Cin
#End

#OutputVolts
Uout = 2,0,0.0,Rout
#End

#InnerBehavior
;Limiting
Uinl = fmax(Uin, Umin)
Uinl = fmin(Uinl, Umax)

;Amplidute Quantisation
n = int((Uinl-Umin)/dUq + 0.5)
Uout = n*dUq + Umin
#End

Hier der vollständige Script von ADConverter.dselfdef.

zu #InnerBehavior:
Bei Limiting wird Uin einfach auf Umin bzw. Umax begrenzt.
Bei Ampl. Quantisation wird Uout auf das Raster dUq diskretisiert. dUq wird bei #VarsAndConstants aus BitRes,
Umin und Umax einmalig berechnet.

Um Ihn flexibler einsetzen zu können, beinhaltet dieser AD-Wandler kein S&H. Deswegen setzt man Ihn meistens
zusammen mit dem S&H-Element ein. Außerdem findet keine Wertebereich-Umsetzung von Uin nach Uout statt.

Digitales FIR-Filter modellieren:

Kommen wir nun zum eigentlich interessanten Teil dieses Kapitels. ToneCirc rechnet bei Dyna für ein digitales
IIR-Filter folgendes:

Die Syntax der FIR/IIR-Spezialfunktion sieht so aus:

UZ = $FIR(CoffFile, UZ, Uin, Z)

CoffFile ist der Name der Datei mit den Koeffizienten (wie beim Analog-IIR-Filter). UZ wird beibehalten wenn Z = 0
(UZ = UZ). Wenn Z = 1 ist, wird Uin in das Filter hineingeschoben und der neue Ausgangswert berechnet (UZ = IIR(Uin)).
Man sieht, dass das S&H-Prinzip hier mit eingebaut ist. Z ist sozusagen der Takt-Impuls, der mit der Samplefrequenz fs
auftritt.

Nun kommen wir zur Modellierung des eigentlichen FIR-Filters:

Schauen wir uns gleich die wichtigen Teile für das BandPass-Filter im Script an:

#InputVolts
Uin = 1,0,Rin,Cin
Uc  = 3,0,Rin,Cin
#End

#OutputVolts
Uout = 2,0,0.0,Rout
#End

#StateVars
UZ = 0
#End

#InnerBehavior
Z   = $RisingEdgeTrigger(Uc, Uth, 0)                                        ;if(Uc > Uth & LH-Edge) Z=1 else Z=0
UZ = $FIR(BandPass_50_55khz_fs200khz.coff, UZ, Uin, Z)    ;if(Z == 1) UZ=FIR(Uin) else Uz=Uz
Uout = UZ
#End

Hier der vollständige Script von FIR_Digi_Bandpass_50_55khz_fs200khz.dselfdef.

zu #InnerBehavior:
Wieder wird in der ersten Zeile der Takt-Impuls Z aus der Clock-Flanke gewonnen. In der zweiten Zeile findet bei jedem
Takt-Ereigniss die Filterung statt. UZ fungiert als Hold-State der dem Ausgang zugewiesen wird.

Erstellung der FIR-BandPass-Koeffizienten-Datei:

Einen BandPass von 50khz bis 55khz für eine Abtastfrequenz von 200khz habe ich mal schon mit Hilfe der IFT-Methode
erstellt. Also: fu = 50khz,  fo = 55khz, fs = 200khz, N = 200

Absofort gibt es das FIR-Filter-Erstellungs-Programm ToneFIRDesigner. Mit diesem Programm könnt ihr ganz
schnell und unkompliziert euer Wunsch-FIR-Filter erstellen.

Simulation des FIR-Filters

Um unsere oben definierten Elemente zu testen, bitte die Schaltung DocSamples/Test_DigiFIR_Bandpass.circ öffnen:

Wir können diese Schaltung in 2 grobe Teile zerlegen, in die "reale Welt" (RWorld) mit Sig1, IC1, dem Eingang von
IC2 und den Scopes, und in die "digitale Welt" (DWorld) mit dem Ausgang von IC2, IC3 und Sig2. Die DWorld wird in
der Regel in einem Digitalen Signal Prozessor (DSP) als Programm implementiert. Die Abtastfrequenz fs muß
mindestens doppelt so groß sein, wie die im Gesamtsystem zu erwartende höchste Frequenz. Es gilt die Deviese:
je größer die Abtastfrequenz desto höher die Rechen-Genauigkeit (kleine Zeit-Schrittweite).

Um eine genaue Spectral-Analyse durchführen zu können, müssen wir folgendermaßen vorgehen:
Für die RWorld legen wir ersteinmal die Abtastfrequenz fs und die Frequenzauflösung df  fest. Hier also:
fs = 2Mhz und df = 100Hz.
Daraus berechnen wir die Periodendauer T = 1/df = 10ms und die Sample-Anzahl N = fs/df = 20k.
Im Settings/AnalysisSettings-Dialog stellen wir nun bei TimeRange: T also 10ms ein. Bei NumberOfTimeSteps tragen
wir N also 20k ein. Im Property-Dialog von Sig1 wählen wir die Funktion RectSpec aus. 
Ich habe einen rechnenden Comment eingefügt, der fs und df anzeigt.
Bei Sig1 legen wir noch den gewünschten Frequenzbereich des Test-Signals fest und wählen bei Phase den Typ 2 aus, um
ein stochastisches Signal (Rauschen) zu erzeugen.

Nun können wir eine Dyna starten und erhalten folgende Ergebnisse:

Links sehen wir den DynChart Sig1.Uout, der das Original-Spektrum des Test-Signals anzeigt. Rechts dagegen sehen
wir den DynChart IC1.Uout, der das Ausgangs-Spektrum des S&H-Elements zeigt. Bei diesen Scopes muß natürlich
Spectrum abs, Auto und Peek eingestellt sein. 
Durch den S&H haben wir es hier mit einer Abtastung zu tun. Bei einer idealen Abtastung (Dirac-Nadeln) würde das
Orignal-Spektrum sich unverändert alle 200khz spiegeln und wiederholen. Wir sehen hier aber, dass das Spektrum
stark abfällt. Das liegt an der Rechteck-Abtastung (0. Ordnung) des S&H, das Dirac-Folge-Spektrum muß so noch
mit einer sogenannten Spaltfunktion multipliziert werden. Hier wird das sehr schön erläutert.

Hier noch das Ausgangs-Spektrum des Bandpass-Filters IC3 in voller und in Zoom-Darstellung:

Man sieht, dass das Filter auch Frequenzen oberhalb des Durchlass-Bereichs (150khz, 250khz,...) ausgibt. Das liegt
daran, dass ein FIR-Filter seine Wirkung an allen Vielfachen von Fs wiederholt. Deswegen ist es auch
notwendig nach der DA-Wandlung ein Tiefpass-Filter (Smothing-Filter) einzusetzen um diesen Mist wegzufiltern.
Den DA-Wandler habe ich mal weggelassen, weil dessen Einfluß hier sehr gering ist.
Die gezoomte Darstellung zeigt die Filter-Charakteristik. Die 20dB-Bandbreite beträgt etwa 7khz, die 3dB-Bandbreite
etwa 6khz. Die Welligkeit entsteht zwischen den 1khz-Auflösungs-Stellen, da das Filter mit der IFT-Methode erstellt
wurde. Wesentlich bessere Filter können einfach und schnell mit ToneFIRDesigner erstellt werden.
Eine genauere Analyse des Filter-Transfer-Verhaltens ist mit der LSA möglich, wenn man die Filter-Koeffizienten-
Datei in ein Analog-FIR-Filter einsetzt.

Hier die Gesamt-Ansicht der Simulation.

Sicherlich ist dem geneigten Leser aufgefallen, dass auch innerhalb der DWorld mit Volt-Größen gearbeitet wird,
obwohl hier ja Digi-Werte gespeichert werden. Das spielt keine Rolle, bitte einfach die Volt-Einheiten wegdenken.
Außerdem soll es ja auch noch diskrete digitale FIR/IIR-Filter als Schaltung geben.

Zurück zur Hauptseite