
72
Mathematischer Hintergrund
Zeitkontinuierlich: 2
$
}
@FA
e
•
$
E
Programmcode
'#### Totzeitglied ####
Public Class DeadTime
Inherits BaseClass.FuncRetrospectiveTimeDependent
Public Overrides Property ApproxType As [Enum] = ApproxTypeEnum.ShorterTimeDelay
Public Enum ApproxTypeEnum
ShorterTimeDelay 'Kürzere Verzögerungszeit
LongerTimeDelay 'Längere Verzögerungszeit
Interpolation 'Genaueste Verzögerungszeit
End Enum
Property T_t As Double = 1 'Verzögerungszeit
Private PQueue As New System.Collections.Queue() 'Alle gespeicherten Punkte
Private Structure DeltaTAndValue 'Punkt bestehend aus Zykluszeit und Wert
Property DeltaT As Double : Property Value As Double
Sub New(ByVal DeltaT As Double, ByVal Value As Double)
Me.DeltaT = DeltaT : Me.Value = Value
End Sub
End Structure
Protected Overrides Function Functionality() As Double
'Verzögern eines nicht zeitäquidistanten abgetasteten Signals.
' P5 P4 P? P3 P2 P1 P0 (Punkte)
' | | ! | | | !
' |-DeltaTP4-|----------DeltaTP3----|--DeltaTP2---|-DeltaTP1-|-DeltaTP0-! (DeltaT einzeln)
' ! |<------TimeAfter-------------------! (DeltaT danach)
' |<-----------------------------TimeBefore------------------! (DeltaT davor)
' !<--Delay=-(T_t-SmallestDeltaT/2)-------------------! (Verzögerungszeit)
'Die Werte und dazugehörigen Zykluszeiten aller Funktionsblockaufrufe werden gespeichert.
'Zum Verzögern des Signals wird im Verlauf nach einem T_t-SmallestDeltaT/2 alten Wert gesucht
'und je nach Approximations-Typ der Wert davor oder danach oder eine Interpolation der beiden
'Werte zurückgegeben. Dabei wird T_t um SmallestDeltaT/2 korrigiert, weil der ausgegebene Wert
'voraussichtlich über eine Zykluszeit lang aktuell sein wird. Die Korrektur erfolgt um die im
'Verlauf kleinste vorkommende Zykluszeit, da bei schwankenden Zykluszeiten sonst evtl. Werte
'zurückgegeben werden, die älter sind als bereits zurückgegebene Werte. Nicht mehr benötigte
'Werte werden aus dem Verlauf gelöscht.
'Falls noch kein Punkt im Speicher ist, einen Punkt mit dem Wert NaN hinzufügen
If PQueue.Count = 0 Then PQueue.Enqueue(New DeltaTAndValue(1 / 0, Double.NaN))
'Aktuellen Punkt (DeltaT mit Wert) hinzufügen
PQueue.Enqueue(New DeltaTAndValue(T, u(0))) 'T=Zykluszeit, u(0)=Eingangswert
'Kleinstes DeltaT aller Punkte ermitteln
Dim SmallestDeltaT As Double = Double.PositiveInfinity 'Kleinste Zykluszeit
For Each DeltaTAndValue As DeltaTAndValue In PQueue 'Alle Punkte durchlaufen
If DeltaTAndValue.DeltaT < SmallestDeltaT Then SmallestDeltaT = DeltaTAndValue.DeltaT
Next
'Queue für bessere Laufzeit in ein Array kopieren
Dim PArray(PQueue.Count - 1) As DeltaTAndValue 'Array, das den Werteverlauf enthält
Dim PIndex As Integer = PQueue.Count - 1 'Array-Index
For Each DeltaTAndValue As DeltaTAndValue In PQueue 'Queue durchlaufen
PArray(PIndex) = DeltaTAndValue 'Array rückwärts beschreiben (PArray(0) = Aktuellster)
PIndex -= 1 'Array-Index dekrementieren
Next
'Ausgangswert berechnen
Dim TimeBefore, TimeAfter As Double 'Zeitpunkt vor und nach dem gesuchten Punkt Px
'Bis zur geforderten Verzögerungszeit zurückzählen, um einen verzögerten Wert auszugeben.
For i As Integer = 1 To PArray.Count - 1 'Alle Index der Punkte durchlaufen
'Zeitpunkt davor durch Aufsubtrahieren der P(x).DeltaT ermitteln
TimeBefore -= PArray(i - 1).DeltaT 'Zeitpunkt negativ, weil er in der Vergangenheit liegt
'Gesuchten Punkt ermitteln (T_t wird um DeltaTAverage/2 korrigiert (Beschreibung oben))
Dim Delay As Double = -(T_t - SmallestDeltaT / 2)
'Liegt der gesuchte Punkt in der Zukunft, suche den aktuellsten Punkt.
If Delay > 0 Then Delay = 0
'Liegt der gesuchte Punkt zwischen den beiden aktuellen Punkten (DateBefore und DateAfter)?
If TimeBefore <= Delay And TimeAfter >= Delay Then '>= und <= weil Zykluszeit 0 sein kann
'Überflüssige Punkte aus der Queue löschen
'i+1, weil evtl. darauf zurückgegriffen wird
For k As Integer = i + 1 To PArray.Count - 1
PQueue.Dequeue() 'Überflüssigen Punkt der Vergangenheit löschen
Next
Select Case DirectCast(ApproxType, ApproxTypeEnum)
Case ApproxTypeEnum.ShorterTimeDelay 'Kürzere Verzögerungszeit
Return PArray(i - 1).Value
Case ApproxTypeEnum.LongerTimeDelay 'Längere Verzögerungszeit
Return PArray(i).Value
Case ApproxTypeEnum.Interpolation 'Genaueste Verzögerungszeit
'Verhältnis für Interpolation
Dim Ratio As Double = (Delay - TimeBefore) / (TimeAfter - TimeBefore)
Return Ratio * PArray(i - 1).Value + (1 - Ratio) * PArray(i).Value
End Select
End If
TimeAfter = TimeBefore 'Der Punkt davor wird im nächsten Durchlauf der Punkt danach sein.
Next
Return Double.NaN 'Der Punkt zur gesuchten Verzögerungszeit liegt außerhalb des Verlaufs.
End Function
End Class