Erstellen von Zeitfunktionen mit dem SigScr-Script, Typ SignalOfTime

Folgendes Diagramm zeigt beispielhaft, wie eine Zeitfunktion im SigScr-Script formuliert wird:

Eine Zeitfunktion kann immer in einen oder mehrere Bereiche (Range's) geteilt, dargestellt werden. In dem
Beispiel hier haben wir 3 Bereiche, die ersten Beiden (a und b) sind Zeitfuntionen, das Dritte (c) ist eine Sequenz.
Bereiche werden im #DefinePulsFunction-Block definiert. Für jeden Bereich k wird eine Zeile mit dem
Schlüsselwort Rangek= benötigt.

Eine Range-Zeile für eine Zeitfunktion hat folgende Syntax:

Range<k> = <fk(p_time)>, <EndTimek>

Eine Range-Zeile für eine Sequenz hat folgende Syntax:

Range<k> = <<SampleWidth>: <S1>, <S2>, ..., <Sn>>, <EndTimek>

k muß bei 1 beginnend fortlaufend durchnummeriert werden.

Für obiges Beispiel könnte #DefinePulsFunction folgendermaßen aussehen:

#DefinePulsFunction
Range1 = sin(w*p_time), Ta
Range2 = {p_time < Q*Tb ? 1 : -0.5}, Ta+Tb
Range3 = <Ts: 0,0.3,0.6,0.9,1.0>, p_PulseLength
#End

Die Range-Zeit p_time beginnt in jedem Bereich k immer mit 0, sie berechnet sich  nämlich aus der Differenz
zwischen g_time und der EndTime des Vorgängerbereiches k-1. Also:  p_time[k] = g_time - EndTime[k-1] mit
EndTime[0] = 0. p_time[k] endet bei EndTime[k] - EndTime[k-1] - dt.
Das Ganze nochmal in einer ordentlichen Formel:

0 <= p_time[k] < EndTime[k] - EndTime[k-1]

Der Vorteil dieser "Modulo-Zeit" liegt in der einfachen Formulierbarkeit der Range-Funktion. Man muß keine
Rücksicht auf die Vorgänger-Zeiten nehmen.

In Range3 erfolgt eine Sequenz-Definition. Eine Sequenz gibt feste Werte (Samples) einfach hintereinander weg aus.
Die zeitliche Länge mit der jedes Sample ausgegeben wird, ist vor dem ':' als Symbol oder Wert anzugeben. Dann
folgen hinter dem ':' die einzelnen Symbole oder Werte für die Samples S1...Sn.

Ist die EndTime des letzten Bereiches kleiner als die Gesamt-Pulse-Länge p_PulseLength wird mit 0-len auf-
gefüllt. Die Definition der Gesamt-Puls-Länge muß im folgenden Block geschehen:

#PulseParameter
p_PulseLength = Ta+Tb+Tc
p_NumPulses = Np
#End

Außerdem muß hier die Definition des PulseParameters p_NumPulses erfolgen, der festlegt, wie oft die Pulse-
Funktion hintereinander ausgegeben werden soll. Für eine unbegrenzte Puls-Abfolge (periodische Funktion) setzt
man den Wert 0 ein.

Am Ende muß noch die Gesamt-Signal-Funktion beschrieben werden:

#DefineSignal
y = Vo + Amp*$SignalOut(g_time-tv)
#End

Hier muß letztendlich dem Symbol y mit Hilfe der Spezial-Funktion $SignalOut die Zeitfunktion zugewiesen werden.
In der Regel wird hier noch der Y-Offset (Vo), die Amplitude (Amp) sowie eine zeitliche Verschiebung tv des Signals
festgelegt.

Schauen wir uns noch an, was in den anderen wichtigen Blöcken steht:

#AutoComment=PulseLen=<p_PulseLength>s

#Parameter
Amp= Amplidute ($), 1
Ta   = SineTime(s), 2m
Tb   = RectTime(s), 2m
Q    = TH/Tb(0..1), 0.7
Tc   = SamplesTime(s), 2m
Vo   = Offset ($), 0
tv    = TimeOffset (s), 0
Np   = Num Pulses, 0
#End

#DefineDefaultTimeRange = 10m

#VarsAndConstants
w  = c_2pi/Ta
Ts = Tc/5
#End

zu #Parameter:
Im Unterschied zu den anderen Scripten, sollte hier die Y-Einheit mit einem '$'-Zeichen angegeben werden. Im Volt-
Signal-Generator-Dialog wird dieses Zeichen durch 'V' ersetzt. Die Zeitfunktionen bei Circuit-Vars können aber andere
Einheiten annehmen, die dann anstelle des '$'-Zeichens automatisch eingesetzt werden.

zu #DefineDefaultTimeRange:
Damit im Signal-Dialog durch Drücken der Taste SetDefault ein sinnvoller Signal-Verlauf vorgeschlagen wird, beziehen
sich die bei #Params angegebenen Standart-Werte auf diesen hier definierten Wert. Abhängig von der Einstellung
AnalyserSettings/TimeRange werden die Standartwerte entsprechend so umgerechnet, dass die Form des Signals
gewahrt bleibt. Damit das reibungslos funktioniert, sollten alle Zeitparameter-Symbole mit 't' oder 'T'  beginnen, alle
anderen Parameter-Symbole natürlich nicht. 

zu #AutoComment:
Die hier definierte Zeichenkette wird beim VoltSignalgenerator-Element als AutoComment verwendet.

Hier der vollständige Script von Test_DifferentRanges.sigscr.

Alle Signal-Scripte müssen im Verzeichniss Data/Signalscripts abgelegt werden, um von ToneCirc gefunden werden
zu können. Eine GUID ist daher nicht notwendig, da die Dateinamen eindeutig sein müssen.

Und hier noch unsere Wurstel-Funktion im Volt-Signal-Dialog:


Als weiteres Beispiel scripten wir die Trapez-Funktion:

Die Skizze der Trapez-Funktion mit allen Zeitparametern sieht so aus:

Die Funktion wird in 4 Bereiche aufgegliedert, die EndTimes der Bereiche habe ich mit t1 bis t4 bezeichnet.
Bei #VarsAndConstants berechnen wir t1 bis t4, das spart Rechenzeit:

#VarsAndConstants
tr2 = fmax(tr, g_stepmin)
tf2 = fmax(tf, g_stepmin)
th2 = fmax(th, g_stepmin)
t1 = tr2
t2 = tr2+th2
t3 = tr2+th2+tf2
t4 = tp
#End

Zusätzlich begrenzen wir noch die Zeitparameter nach unten, denn g_stepmin darf nicht unterschritten werden.

Die Hauptblöcke sehen dann folgendermaßen aus:

#PulseParameter
p_PulseLength = tp
p_NumPulses = Np
#End

#DefinePulsFunction
Range1 = p_time/tr2, t1
Range2 = 1, t2
Range3 = 1-p_time/tf2, t3
Range4 = 0, t4
#End

Man sieht, wie einfach die Formulierung einer Trapezfunktion ist. Für t4 hätten wir auch tp oder p_PulseLength
schreiben können.

Folgender Block ist neu hinzu gekommen:

#DefineDependentParams
fp = 1/tp
tp = 1/fp
#End

tp und fp wurden als Parameter definiert, sind aber voneinander abhängig. Das heißt, wenn man den einen Parameter
im Parameter-Dialog ändert (Enter, Pfeiltasten), wird der Andere automatisch berechnet und im Parameter-Feld
neu ausgegeben. Wir nutzen in diesem Beispiel dieses Feature, um zwischen der Eingabe der Periodendauer oder der
Frequenz wählen zu können.

Hier der vollständige Script von Trapez_Periodical.sigscr.

Der Signal-Dialog sieht mit TimeRange = 1us standartmäßig so aus:


Als weiteres Beispiel scripten wir noch den Gaussian-Pulse:

Die Skizze der Gauss-Funktion mit allen Zeitparametern sieht so aus:

Die Gauss-Funktion wird ausgedrückt mit der Gleichung:

Das Ganze läßt sich nun in einem einzigen Bereich darstellen. In den Script kann dann reingeschrieben
werden:

#VarsAndConstants
tsigma2 = tsigma*tsigma*2
tm = tp/2
#End

#PulseParameter
p_PulseLength = tp
p_NumPulses = Np
#End

#DefinePulsFunction
Range1 = exp( -((p_time-tm)^2/tsigma2) ), tp
#End

Für tm setzen wir einfach die Hälfte von tp an. Sonst muß hier nichts mehr dazu gesagt werden.

Hier der vollständige Script von GaussianPulses.sigscr.

Der Signal-Dialog sieht mit TimeRange = 1ms und NumPulses = 3 standartmäßig so aus:


Als letztes Beispiel noch kurz die Rampen-Funktion:

Da die Rampe kontinuierlich linear ansteigt, ist ihre Pulse-Länge unendlich. Um Derartiges zu
definieren, benutzen wir das Schlüsselwort INFINITE. Schauen wir uns den Script an:

#VarsAndConstants
tramp2 = fmax(tramp, stepmin)
S = (Amp-vo)/tramp2
#End

#PulseParameter
p_PulseLength = infinite
p_NumPulses = 1
#End

#DefinePulsFunction
Range1 = S*p_time, p_PulseLength
#End

p_PulseLength setzen wir also auf infinite, für p_NumPulses tragen wir 1 ein. Der Anstiegsfaktor S
ist so berechnet, dass bei t = tramp der Wert von Amp erreicht wird.

Hier noch der vollständige Script von Ramp.sigscr.


Erstellen von Zeitfunktionen mit dem SigScr-Script, Typ SignalOfSpectrum

Neben dem standartmäßigen Typ SignalOfTime, wo eine Zeitfunktion definiert wird, gibt es noch den Typ
SignalOfSpectrum, wo ein Betrags-Spektrum definiert wird. ToneCirc erzeugt mittels einer IFT dieses Spektrums
eine Zeitfunktion.
Den Typ SignalOfSpectrum muß man explizit festlegen mit der Zeile #CalculationType = SignalOfSpectrum am
Anfang des Scripts. 

Wir schauen uns die Sache mal anhand eines einfachen Beispiels an. Das beliebte SpecRect-Signal sieht folgender-
maßen aus:

Das Script für die Definition dieses Spektrum-Signals sieht dann so aus:

#Parameter
Xeff = Effective Val ($), 0.707
Fl = Lowest Freq (Hz), 2k
Fh = Highest Freq(Hz), 6k
vo = Offset ($), 0
tv = TimeOffset (s), 0
ptype = Phase(0-0°/1-90°/2-rand), 2
#End

#PulseParameter
p_NumSamples = Auto
p_FreqStep        = Auto          ;p_SampleFreq = p_NumSamples*p_FreqStep
p_EffectiveValue = xeff
p_PhaseType = ptype        ;0: 0°, 1: 90°, 2: randomize
p_NumPulses = 0
#End

#DefinePulsFunction
Range1 = 0, Fl
Range2 = 1, Fh+p_FreqStep    ;<=Fh
Range3 = 0, p_SampleFreq/2
#End

#DefineSignal
y = Vo + $SignalOut(g_time-tv)
#End

Hier der komplette Script von SpecRect.sigscr.

zu #PulseParameter:

Im Gegensatz zum SignalOfTime-Typ müssen hier die Parameter p_NumSamples, p_FreqStep, p_EffectiveValue
und p_PhaseType definiert werden. Der Parameter p_PulseLength (T) fällt hier weg, da er sich aus NumSamples 
und FreqStep ergibt.

p_NumSamples ist die Anzahl der Abtastungen bzw. die Anzahl der Frequenz-Punkte (N, Ns).
Benutzt man das Auto-Flag hinter dem '='-Zeichen, dann wird der Wert in AnalyserSettings/NumTimeSteps 
zugewiesen.

p_FreqStep ist die Frequenz-Auflösung (df, fdelta).
Benutzt man das Auto-Flag hinter dem '='-Zeichen, dann wird der Wert  1/AnalyserSettings/TimeRange 
zugewiesen.

p_EffectiveValue ist der Effektiv-Wert, mit der das Signal am Ende ausgegeben werden soll.

p_SampleFreq (fs) muß hier nicht angegeben werden, sie ergibt sich aus N und df.

p_PhaseType ist der Typ des Phasenwinkels, der zur Berechnung des komplexen Spektrums aus dem Betrags-
Spektrum benötigt wird.

ToneCirc verschiebt das Zeit-Signal dann noch um T/2, damit die Peeks in der Mitte auftreten.

p_NumPulses ist wieder die Anzahl der Pulse (macht keinen Sinn wenn bei p_FreqStep das Auto-Flag
benuzt wird).

Die Abtastfrequenz (fs), Zeitschrittweite (dt) und PulsLänge (T) des Signals ergibt sich

zu #DefinePulsFunction:

Dieser Block ist praktisch identisch zum SignalOfTime-Typ aufgebaut, es muß nur <EndTime> duch <EndFreq>,
p_time durch p_freq und p_pulselenght durch p_samplefreq/2 ersetzt werden. Ist im letzten Range die End-Frequenz
kleiner als p_samplefreq/2, wird bis dahin mit 0 aufgefüllt. In diesem Beispiel hätten wir Range3 deswegen auch
weglassen können. Alle Frequenzen größer gleich p_samplefreq/2 werden ignoriert.
Auch die Sample-Folge ist hier verfügbar, um einzelne Frequenzbereiche oder Linien (Kamm-Spektren) zu
erzeugen.

Hier die Ergebnisse für verschiedene Einstellungen im VoltSignal-Dialog:

Effective Val = 1.2V
fl = 0Hz
fh = 6khz
NumSamples = 1000
FreqStep = 1khz
Phase = 0


Effective Val = 1.2V
fl = 0Hz
fh = 6khz
NumSamples = 1000
FreqStep = 1khz
Phase = 1


Effective Val = 1.2V
fl = 0Hz
fh = 100khz
NumSamples = 1000
FreqStep = 1khz
Phase = 2

NumSamples und FreqStep werden automatisch (Auto-Flag) aus den Analyse-Einstellungen bestimmt.
Für alle diese Signale haben wir also mit T = 1ms und N = 1000: df = 1/T = 1khz, fs = N*df = 1Mhz
und dt = 1/fs = 1us eingestellt.
In den allermeißten Fällen wird für die Spektral-Analyse einer Schaltung ein Rausch-Signal (PhaseTyp 2)
verwendet. Mit den beiden anderen Typen kann man Koeffizienten-Dateien für FIR-Filter erstellen.

zur Hauptseite