Formeleditor

Note

Der Formeleditor dient berechneten Variablen. Mit ihm haben wir die Möglichkeit komplexe auf Bedingungen aufbauende Berechnungen vornehmen zu lassen, die sowohl auf Plc Variablen als auch auf anderen berechneten Variablen aufbauen.

../../_images/241.png

Im Formeleditor stehen uns diverse Funktionen und eine eigene Syntax Sprache zur Verfügung. Wir können andere Variablen referenzieren, Platzhalder definieren und zahlreiche mathematische Operatoren und Funktionen, sowie, Bedingungen mit If/Else Konstrukten benutzen.

Variablen die wir einsetzen wollen können wir per Drag&Drop aus der Navigation in den Text kopieren.

Formel Beispiele

$MS.SGas.Q_ein.plc->Auto - $MS.SGas.Q_aus.plc->Auto
var p_ein = $VK_Vk.SGas.p_ein.v->Auto;
var p_aus = $VK_Vk.SGas.p_aus.v->Auto;
return p_aus / p_ein * 100;
var q_plc = $K_KK.SGas.Q.plc->Auto;
var rel = $MS.SGas.rel.calc->Auto;
var q_calibrated = q_plc * rel;
return if (IsValid(rel)) {
  q_calibrated
} else {
  0
};
var q = $K_KK.SGas.Q.calc->Auto;
var v_aus = if (q < 0) {Integral(Abs(q) @ Raster = Hour)} else {0};
return v_aus;
var q = $K_KK.SGas.Q.calc->Auto;
var v_ein = if (q > 0) {Integral(q @ Raster = Hour)} else {0};
return v_ein;
Avg($K_KK.SGas.p_M1.plc->Auto, $K_KK.SGas.p_M2.plc->Auto)
Sum(
  $TSp.SGas.Q_kavmess.calc->DirectChildren,
  $K_KK.SGas.Q.plc->DirectChildren
  @OptionalParams = True
)

Syntax Elemente

var

Ein Schlüsselwort, welches man vor Platzhalternamen schreibt, gefolgt von ist gleich und dem zugewiesenen Wert. Die Zeile wird mit einem Semikolon beendet.

Beispiele

var q = $K_KK.SGas.Q.calc->Auto;
var v_aus = if ($K_KK.SGas.Q.calc->Auto < 0) {Integral(Abs($K_KK.SGas.Q.calc->Auto) @ Raster = Hour)} else {0};

return

Dieses Schlüsselwort wird vor einen Rückgabe-Wert oder -Block geschrieben.

Beispiele

return $MS.SGas.Q_ein.plc->Auto - $MS.SGas.Q_aus.plc->Auto;

Auch in Kurzform möglich in letzter Zeile

$MS.SGas.Q_ein.plc->Auto - $MS.SGas.Q_aus.plc->Auto;

Oder als Block

return if (IsValid(value)) {
  calibrated
} else {
  0
};

if, else

Ermöglicht differenzierte Logik. Wenn A gilt, tue dies, ansonsten das.

Beispiele

return if (IsValid(value)) {
  calibrated
} else {
  0
};
var q = $K_KK.SGas.Q.calc->Auto;
var v_aus = if (q < 0) {Integral(Abs(q) @ Raster = Hour)} else {0};

NaN

Ein spezieller Wert, der angibt keine Zahl zu sein (Not a Number).

Note

Jeder Wert (einer Variablen) besteht aus 2 Zahlen, einmal dem Wert selbst, und einmal der Qualität zwischen 0 und 1, 0 = schlecht, 1 = gut. Es kann in Berechnungen und der Verwendung bestimmter Variablen passieren, dass Werte eine schlechte Qualität aufweisen. Ist dies der Fall, so wird bei bestimmten Operationen aus z.B. der Multiplikation einer Zahl mit einer schlechten Qualität auch das Ergebnis als schlecht gewertet und so erhält das Ergebnis daher den Wert NaN.

NaN steht für Not a Number

Operatoren

Uns stehen die typischen arithmetischen Opeartoren zur Verfügung.

  • + Addition

  • - Subtraktion

  • * Multiplikation

  • / Division

  • % Modulo

Funktionen

Aufruf

Beschreibung

Abs( x1 )

Absolutwert

And( x1 ... xn )

Logische && Operation über alle Variablen. 0 = false, 1 = true.

Avg( x1 ... xn @ OptionalParams = [True | False] )

Wie Average

Average( x1 ... xn @ OptionalParams = [True | False] )

Mittelwert über alle übergebene Argumenten.

BitAnd( x1, x2 ... xn )

Bitweise & Operation über 2 Argumenten.

BitOr( x1, x2 ... xn )

Bitweise | Operation über 2 Argumenten.

Diff( x1, x2 ... xn )

Differenz. Ergebnis: arg0 - arg1 - arg2 - … - argn.
Das selbe wie SumDiff @ NPositiv = 1

Div( x1, x2 )

Division. Ergebnis arg0 / arg1

Eq( x1, x2 ... xn )

Logische == Operation über alle Argumenten.
Liefert 0 wenn FALSE, 1 wenn TRUE.

Ge( x1, x2 ... xn )

Logische >= Operation über alle Argumenten.
Liefert 0 wenn FALSE, 1 wenn TRUE.

Gt( x1, x2 ... xn )

Logische > Operation über alle Argumenten.
Liefert 0 wenn FALSE, 1 wenn TRUE.

If( Messages.FormulaOperation_If, 3 )

Logisches If - else Block. Argument 1 - Bedienung,
Argument 2 - Wert wenn TRUE, Argument 3 - Wert wenn FALSE.
Argument 1 ungleich 0 wird als TRUE interpretiert.

IsValid( x1 )

Boolesche funktion, welche überprüft ob die Qualität
des Wertes größer 0 und Plausibliltät gleich Ok ist.

LastValid( x1 @ Raster = [Raster-Wert], Width = [Int-Wert] )

Liefert den letzten gültigen Wert unnerhalb eines
spezifizierten Zeitberechs. Parameter sind Raster, Width.
Falls nichts spezifiziert ist die Width = 1.

NextValid( x1 @ Raster = [Raster-Wert], Width = [Int-Wert] )

Liefert den nächsten gültigen Wert unnerhalb eines
spezifizierten Zeitberechs. Parameter sind Raster, Width.
Falls nichts spezifiziert ist die Width = 1.

LastValidValueInRaster( x1 @ Grid = [Hour | Das | Week | Month | Year] )

Liefert den letzten gültigen Wert innerhalb eines Virtuellen Raster

Le( x1, x2 ... xn )

Logische <= Operation über alle Argumenten.
Liefern 0 wenn FALSE, 1 wenn TRUE.

Lt( x1, x2 ... xn )

Logische < Operation über alle Argumenten.
Liefern 0 wenn FALSE, 1 wenn TRUE.

LocalHour( x1 )

Gibt die aktuelle Stunde des Wert-Zeitstempels
in der Localen Zeitzone zurück.

LocalFractionalHour( x1 )

Gibt die aktuelle Stunde (Partiell) des Wert-Zeitstempels
in der Localen Zeitzone zurück.

LocalWeekDay( x1 )

Gibt den aktuellen Wochentag des Wert-Zeitstempels
in der Localen Zeitzone zurück.

LocalDayOfMonth( x1 )

Gibt den aktuellen Tag seit Monatbegin des Wert-Zeitstempels
in der Localen Zeitzone zurück.

LocalDayOfYear( x1 )

Gibt den aktuellen Tag seit Jahresbegin des Wert-Zeitstempels
in der Localen Zeitzone zurück.

VirtualZoneHour( x1 )

Gibt die aktuelle Stunde des Wert-Zeitstempels
in der Virtuelen Zeitzone zurück.

VirtualZoneDayOfMonth( x1 )

Gibt den aktuellen Tag des Monats des Wert-Zeitstempels
in der Virtuellen Zeitzone zurück.

VirtualZoneDayOfYear( x1 )

Gibt den aktuellen Tag des Jahres des Wert-Zeitstempels
in der Virtuellen Zeitzone zurück.

VirtualZoneFractionalDayOfYear( x1 )

Gibt den aktuellen Tag des Jahres (partiell) des Wert-Zeitstempels
in der Virtuellen Zeitzone zurück.

VirtualZoneYear( x1 )

Gibt den Jahr des Wert-Zeitstempels in der Virtuellen Zeitzone zurück.

Map( x1, x2, x3 ... xn )

Wertmapping. Parameter 1 - Wert, Parameter n - Testwert,
Parameter n+1 - Ausgabwert, wenn Parameter n gleich Parameter 1 ist.

Mult( x1 ... xn )

Produkt über alle Argumenten. arg0 * arg1 * … * argn.

Min( x1 ... xn )

Minimum aus allen Argumenten.

Max( x1 ... xn )

Maximum aus allen Argumenten.

Merge( x1 ... xn @ OptionalParams = [True | False] )

Zusammenführen aller Argumenten über die Variablenqualität.
Der Wert mit der höchster Qualität wird geliefert.
Bei gleicher Qualität wird der Wert des Arguments

Median( x1 ... xn )

TODO

MovingAverage( x1 @ Width = [Int-Wert], Offset = [Int-Wert], Centered = [True | False], Model )

Mittelwert gebildet über Zeit aus mehreren nachfolgenden Werten.
Anzahl der Werte wird über Parameter Width bestimmt.

MovingMedian( x1 @ Width = [Int-Wert], Offset = [Int-Wert], Centered = [True | False], Model )

TODO

Not( x1 )

Logische ‘Nicht’ Operation.

NotEq( x1, x2 ... xn )

Logische != Operation über alle Variablen. Liefert 0 wenn FALSE, 1 wenn TRUE.

Negate( x1 )

Wert * -1. Dabei wird weder der Zeitstempel noch die Qualität des
Wertes verändert.

Or( x1 ... xn )

Logische || Operation über alle Variablen. Liefert 0 wenn FALSE, 1 wenn TRUE.

Power( x1, x2 )

Potenzfunktion: arg1^arg2.

Random( x1, x2 )

Zufallswert zwischen arg1 und arg2.

TimeInterval( x1 @ Raster = [Raster-Wert] )

Zeitinterval des aktuellen Zeitabschnitts in Rastereinheiten.

LowerLimit( x1 )

TRUE(1) wenn der Wert die untere Grenze verletzt.

UpperLimit( x1 )

TRUE(1) when der Wert die obere Grenze verletzt

Quality( x1 )

Wertqualität.

Sign( x1 )

Liefert den Vorzeichen des Arguments. ‘1’ bei positiven, ‘-1’ bei negativen
und ‘0’ bei 0-Werten.

Sum( x1 ... xn, @ OptionalParams = [True | False] )

Summe über alle Argumenten.

SumDiff( x1 ... xn )

Summe/Differenz über die Needs, wobei die ersten
nPositiv Argumenten positiv und der Rest negativ eingeht.

Integral( x1 @ Raster = [Raster-Wert] )

Integral über die Zeit (z.B. Q -> V).

IntegralKum( x1 @ Raster = [Raster-Wert], ResetOnNaN = [True | False] )

Integriert kummulativ über die Zeit (z.B. Q -> V_kum).

Rate( x1 @ Raster = [Raster-Wert] )

Rate aus Volumen.

SumKum( x1 @ Raster = [Raster-Wert], ResetOnNaN = [True | False] )

Summiert kummulativ über die Zeit (z.B. V -> V_kum)

Differential( x1 @ Raster = [Raster-Wert] )

Dividiert einen Wert durch die Rasterzeit.
Berechnet zB. Volumenstrom Q aus Volumen V.

Delta( x1 )

Liefert jeweils den Unterschied zwischen zwei aufeinanderfolgenden
Werten des Arguments.
Damit kann zB. aus Zählwert eine Volumina ausgerechnet werden.

WindowCounter( x1 @ Raster = [Raster-Wert] )

Liefert Anzahl der Rastereinheiten während dessen
das Argument ‘TRUE’ (ungleich 0) bleibt.
Damit lässt sich zB. berechnen für wie lange ein bestimmtes Zustand

Sin( x1 )

Sinus (radian)

Cos( x1 )

Cosinus (radian)

Tan( x1 )

Tangens (radian)

Verfügbare Raster-Werte

Milli_1, Milli_2, Milli_5, Milli_10, Milli_20, Milli_25, Milli_50, Milli_100, Milli_200, Milli_250, Milli_500, Second_1, Second_2, Second_5, Second_10, Second_15, Second_30, Minute_1, Minute_2, Minute_5, Minute_10, Minute_15, Minute_30, Hour, Day, Week, Month, Year

Beispiele

Sum(
  $TSp.SGas.Q_kavmess.calc->DirectChildren,
  $K_KK.SGas.Q.plc->DirectChildren
  @OptionalParams = True
)
Integral(Abs($K_KK.SGas.Q.calc->Auto) @ Raster = Hour)
Avg($K_KK.SGas.p_M1.plc->Auto, $K_KK.SGas.p_M2.plc->Auto)

Suchspezifikationen bei Variablen

Sowohl im Formeleditor als auch bei der Anlage von Variablen Knoten

Auto

->Auto

Sucht in vordefinierter Reihenfolge und geht jeweils zum nächsten Punkt, aber nur solange noch nichts gefunden wurde.

  1. Sucht bei diesem Objekt, aber stoppt sofort, wenn das richtige Objekt gefunden wurde.

  2. Sucht bei den Eltern und Eltern von Eltern, aber stoppt sofort, wenn ein richtiges Objekt gefunden wurde.

  3. Sucht in die Tiefe über alle Zweige und gibt alle obserste (also zuerst gefundene) passende Kinder zurück.

Angenommen wir zeigen uns das Verdichtungsverhältnis von VK05 an und rufen in der Formel den Wert vom Eingangsdruck mit dem Schlüssel Auto, so sucht der Berechnungsalgorithmus nach einem Eingangsdruck am Objekt VK05, also am selben Objekt.

../../_images/261.png

Wenn er den Wert nicht findet, geht er den Objektbaum von VK05 wie wir ihn in der Hierarchie unter Objekte finden hoch und schaut bei den hierarchisch übergeordneten Objekten nach einem Eingangsdruck. Also zuerst bei Alle Verdichter, dann bei Kevernenspeicher und wenn das nicht klappt dann schaut er bei den Kindknoten von VK05, also VK05_E-NSA-PAC und VK05_S-NSA-PAC.

Parent

->Parent

Sucht bei allen Eltern und Eltern von Eltern aber stoppt beim ersten Fund

Children

->Children

Sucht bei den Kindern

ThisOrParent

->ThisOrParent

Sucht bei allen Eltern und Eltern von Eltern und am aktuellen Objekt

ThisOrChildren

->ThisOrChildren

Sucht bei Kindern, Kindes-Kindern und am aktuellen Objekt und nimmt alles was passt.

This

->This

Nimmt das aktuelle Objekt.

DirectChildren

->DirectChildren

Sucht nur bei direkten Kindern (also nicht Kindes-Kindern) und gibt alle passenden Geschwister zurück.

TopChildren

->TopChildren

Sucht in die Tiefe über alle Zweige und gibt alle obserste (also zuerst gefundene) passende Kinder zurück.

Ausführlicher: Sucht bei allen Kindern und allen Kindes-Kindern in allen Verzweigungen in die Tiefe, jeweils stoppend bei einem Fund, wo alle passenden Objekte gesammelt werden. Die Sammlung aus allen Fund-Zweigen wird dann zurückgegeben.

All

->All

Nimmt alle Knoten.

Objekt Angabe

Beispiel: ->vk03

Nimmt benanntes Objekt (also hier von vk03), wobei hier Bezug genommen wird auf den Object_Key