Umgang mit MultiArray
Ein MultiArray ist ein mehrdimensionaler Datenpuffer, welcher in der Condition Monitoring Library in Kombination mit dem Transfer Tray genutzt wird. Er ermöglicht einer Anwendung mehrdimensionale Daten problemlos zwischen mehreren SPS-Tasks auszutauschen. Während der Kommunikation zwischen den Tasks wird kein Speicher kopiert, sondern es werden lediglich Verweise auf die Datenpuffer übergeben, wodurch die Kommunikation extrem effizient wird. Die Kommunikation erfordert lediglich ein sehr geringes Overhead mit Ausführungszeiten im Mikrosekundenbereich.
Der MultiArray-Kommunikationsring
Das Füllen (Schreiben von Inhalt) und Senden (Weitergabe der Zugriffsrechte) von MultiArrays für Eingangs- oder Ergebnisdatenströme haben zur Folge, dass ständig „freie“ MultiArrays gefordert werden. Deswegen werden die ausgewerteten MultiArrays als „leere“ Datenbehälter an diejenige Task zurückgegeben, welche sie auch gefüllt hat. So entsteht ein stetiger Kreislauf von MultiArrays, vgl. Abbildung im Abschnitt Parallelverarbeitung mit Transfer Tray.
Normalerweise sind mindestens drei MultiArrays pro Kreislauf notwendig: Das erste MultiArray „gehört“ der Steuerungstask und ist dabei, mit neuen Daten gefüllt zu werden. Auf das zweite MultiArray greift die Prozesstask zu und verarbeitet ihn. Ein drittes MultiArray muss in Reserve gehalten werden, so dass es verfügbar ist, falls die Steuerungstask das aktuelle MultiArray gefüllt hat, jedoch verbleibende Oversampling-Daten in genau diesem Zyklus auch noch in ein nächstes MultiArray geschrieben werden müssen. Deswegen ist die Mindestanzahl gleich drei.
Anzahl von MultiArrays Zur Sicherheit wird als Worst-Case-Abschätzung eine Anzahl von vier MultiArrays pro Kreislauf empfohlen. Greift mehr als ein Algorithmus auf die Daten eines MultiArrays zu wird empfohlen, für jeden weiteren zugreifenden Algorithmus jeweils ein zusätzliches MultiArray bereitzustellen. |
Die Anzahl von bereitgestellten MultiArrays wird über die Eingangsparameter nResultBuffers
der Funktionsbausteine der Condition Monitoring Library eingestellt, default-Wert ist entsprechend 4.
Anzahl von MultiArrays im Kommunikationsring Mehr als vier MultiArrays sind nur dann erforderlich, wenn die Ergebnispuffer (= MultiArrays) direkt von mehreren Algorithmen abgearbeitet werden sollen. Also nehmen mehr als zwei Analysebausteine im Kommunikationsring für diese Ergebnisse teil. Es wird empfohlen, die Anzahl Ergebnispuffer mit jedem zusätzlichen Baustein um eins zu erhöhen. Die Anzahl der in einem asynchronen Kommunikationsring verwendeten MultiArray Puffer kann in jedem Analysefunktionsbaustein konfiguriert werden. |
Diese zusätzlichen Puffer werden intern erzeugt und verwaltet. Sie erfordern eine bestimmte Größe an zusätzlichem Speicher im AMS Router.
Grundsätzlich kann die Dimension eines MultiArrays getrennt im Hinblick auf Länge, Größe und sogar Datentyp konfiguriert werden. Die Parameter definieren zusammen die sogenannte Shape (Form) des MultiArrays für dessen gesamten Lebenszyklus.
Es ist zu beachten, dass die interne Struktur des MultiArrays automatisch verwaltet wird und keinerlei Programmierung erfordert. Die Lebensdauer des MultiArrays ist die gleiche, wie diejenige der Anwendung, d.h. ab SPS Start bis zum SPS Stopp, wobei die MultiArrays von der einen zur anderen Task mit Hilfe des sogenannten Transfer Tray übergeben werden.
Das Konzept ist sehr flexibel. Das Ändern und Neuverteilen der Berechnung auf andere Tasks und/oder CPUs ist einfach und unkompliziert.
Konfiguration von MultiArrays
MultiArrays werden mit der ST_MA_MultiArray_InitPars Struktur konfiguriert. Diese ist Teil der Tc3_MultiArray Bibliothek, welche mit dem Condition Monitoring Setup installiert wird.
Beispielkonfiguration eines MultiArray:
cInitSource : ST_MA_MultiArray_InitPars:= ( eTypeCode := eMA_TypeCode_LREAL,
nDims := 2,
aDimSizes := [cChannels, cBufferLength]);
Wird das MultiArray mit dem FB_CMA_Source
Funktionsbaustein verwendet, dann wird eine konfigurierte MultiArray Instanz (oder mehrere) von der Source-Instanz fbSource
gefordert. Das oben beschriebene MultiArray hat 2 Dimensionen (nDims = 2,
erlaubt ist ebenfalls nDims = 1
), wobei die Größe der Dimensionen mit aDimSizes
beschrieben wird. Entsprechend ist das beschriebene MultiArray von der Dimension cChannelsxcBufferLength
mit dem Datentyp LREAL für jedes Element.
Beispiel für die Nutzung von MultiArrays mit dem FB_CMA_Source
:
fbSource : FB_CMA_Source := ( stInitPars := cInitSource,
nOwnId := eID_Source,
aDestIDs := [eID_Rms],
nResultBuffers := 4);
MultiArrays sind hinsichtlich der Verwaltung des Datenspeichers flexibel. So sind z.B. im obigen Fall die Zeilen und Spalten vollständig austauschbar, und bei korrekter Zuweisung/Identifizierung der Dimensionen (wie im Beispiel unten gezeigt), hat dies keinerlei Einfluss auf die Ergebnisse.
Erweiterte Konfigurationsoptionen
Wie Sie unten im Beispiel sehen, bietet FB_CMA_Source (oder FB_CMA_Sink, FB_CMA_BufferConverting) Parameter wie nWorkDim
, pStartIndex
oder nElementsDim
. Diese Parameter können verwendet werden um:
- Ein bestimmtes Segment des MultiArray zu beschreiben/auszulesen
- Ab einer bestimmten Stelle zu schreiben/lesen/kopieren
- Eine bestimmte Anzahl Elemente ab einer bestimmten Stelle zu kopieren
Eine Kombination dieser Parameter garantiert nicht nur Speicheroptimierung, sondern garantiert auch die Selektivität in mehrkanaligen, Multi-Task Anwendungen. Siehe Beispiel unten.
Anwendungsszenario
Dieses Anwendungsszenario hat lediglich innerhalb des TwinCAT Condition Monitoring Anwendungsbereichs Gültigkeit. Wie bereits erwähnt, werden die MultiArrays automatisch verwaltet, aber sie müssen zunächst initialisiert werden. Dies geschieht in der SPS Deklaration mit Hilfe von ST_MA_MultiArray_InitPars
und wird an die FB_CMA_Source-
Instanz übergeben.
Jeder Algorithmen-Funktionsbaustein übergibt seine Ergebnisse mit Hilfe der mit stInitPars konfigurierten MultiArrays. Deren Formen werden mit den Initialisierungsparametern (siehe jeweilige Erläuterungen zu den Funktionsbausteinen), mit Ausnahme des FB_CMA_Sink
, definiert. Es ist zudem möglich nur einen Teil des MultiArray in ein SPS Array zwecks weiterer Bearbeitung oder Auswertung zu kopieren. Dies wird mit Hilfe von FB_CMA_BufferConverting
erledigt.
Die Funktionsbausteine verfügen über Methoden, mit denen SPS Variablen in MultiArrays geschrieben oder ausgelesen werden können. Weitere Erläuterungen zu den Methoden und deren Parametern finden Sie in den Beschreibungen der Funktionsbausteine.
Der Jede Dimension eines MultiArray, genannt Arbeitsdimension (WorkDim), hat einen mit 0 beginnenden Index. Bei zweidimensionalen MultiArrays wird in der Condition Monitoring Library die Arbeitsdimension 0 normalerweise mit der Anzahl von Kanälen verknüpft (vgl. „Beispielkonfiguration eines MultiArray“ im obenstehenden Text) |
Beispiele zur Handhabung von MultiArrays
Für das bessere Verständnis bezüglich der Verwendung eines MultiArray in einer Condition Monitoring Anwendung, betrachten wir folgendes Fallbeispiel.
Es werden, z.B. mit zwei EL3632, drei Signale von einem Beschleunigungssensor mit einem Oversampling-Faktor von 10 aufgenommen. Die Eingangsdaten werden in einem MultiArray mit der Länge 1000 gesammelt und an einen Funktionsbaustein übergeben. In diesem Fall ist es der Baustein für die Berechnung der Moment Coefficients. Der FB_CMA_MomentCoefficients
berechnet für jeden Kanal, je nach Konfiguration, verschiedene statistische Kenngrößen der Eingangsdaten. Unser Ziel ist es nun das MultiArray am Ausgang des FB_CMA_MomentCoefficients
so zu konfigurieren, dass nur ein gewisser Teil des Ergebnisses, zum Beispiel der Mittelwert und die Standardabweichung, ausgegeben werden.
Die Ein- und Ausgangsvariablen werden folgendermaßen deklariert und initialisiert:
cInitSource : ST_CM_MultiArray_InitPars := (eTypeCode := eMA_TypeCode_LREAL,
nDims := 2,
aDimSizes := [3,1000]);
aBuffer : ARRAY [1..3] OF ARRAY [1..cOverSamples] OF LREAL;
fbSource : FB_CMA_Source := (stInitPars := cInitSource,
nOwnID := eID_Source,
aDestIDs := [eID_MomentCoeffs]);
// MultiArray indices begin with 0, not 1!
// aStartIndex := [0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],...
aStartIndex : ARRAY [1..2] OF UDINT := [0, 1];
// Select channels := 1: one, 2: one and two, 3: one, two and three and so on
// Select moments := 0: count, 1: mean, 2: standard deviation, 3: skew, 4: kurtosis
aMomentCoef : ARRAY [1..3, 1..2] OF LREAL;
Wie oben gezeigt, erhält der fbSource
ein MultiArray mit 2 Dimensionen und soll die Daten von aBuffer
nach entsprechender Aufpufferung den FB_CMA_MomentCoefficients
übergeben. In Funktion der Initialisierungsparameter, kann man entweder die Daten speichern:
- Indem die Kanäle über die Zeilen und die Abtastungen über die Spalten gespeichert werden,
- oder, indem die Abtastungen über die Zeilen und die Kanäle über die Spalten gespeichert werden.
Weil das MultiArray zweidimensional ist, wird dies mit dem Aufruf der Input2D() Methode erledigt.
fbSource.Input2D(pDataIn := ADR(aBuffer),
nDataInSize := SIZEOF(aBuffer),
eElementType := eMA_TypeCode_LREAL,
nWorkDim0 := 0, (* aBuffer stores channels across first dim*)
nWorkDim1 := 1, (* aBuffer stores samples across second dim*)
pStartIndex := 0,
nOptionPars := 0 );
Gehen wir diesen Aufruf der Methode Schritt für Schritt durch:
- Die lokale SPS Variable
aBuffer
wird als Referenz übergeben. - Es wird der Datentyp spezifiziert, welcher übergeben wird.
- Die Methode weist hier die erste Arbeitsdimension des MultiArray der ersten Dimension von
aBuffer
(cChannels
) und die zweite Arbeitsdimension den Abtastwerten (cOversamples
) zu. Alternativ könnte z. B. die VariableaBuffer : ARRAY [1.. cOversamples] OF ARRAY [1.. 3] OF LREAL
deklariert sein, und die notwendige Transponation durchnWorkDim0 =1
undnWorkDim1 =0
realisiert werden. pStartIndex=0
kopiert hier den gesamtenaBuffer
in das MultiArray, was der Standardeinstellung entspricht. Wie nur Teile eines Arrays kopiert werden, wird anhand desFB_CMA_Sink
nachfolgend gezeigt.
Alle obigen Einstellungen konfigurieren das MultiArray vollständig, um die Kanäle entlang seiner ersten Dimension (Zeilen) und die Abtastwerte entlang seiner zweiten Dimension (Spalten) bis zur Länge cBufferLength
zu speichern.
Auf ähnliche Weise kann eine FB_CMA_Sink
Instanz die Inhalte des MultiArray in die lokale SPS-Variable aMomentCoef
schreiben.
fbSink.Output2D(pDataOut := ADR(aMomentCoef),
nDataOutSize := SIZEOF(aMomentCoef),
eElementType := E_MA_ElementTypeCode.eMA_TypeCode_LREAL,
nWorkDim0 := 0, (* aMomentCoef stores channels across first dim *)
nWorkDim1 := 1, (* aMomentCoef stores moments across second dim *)
nElementsDim0 := 3, (* aMomentCoef stores all 3 channels *)
nElementsDim1 := 2, (* aMomentCoef stores mean and deviation*)
pStartIndex := ADR(aStartIndex),
nOptionPars := 0);
Gehen wir auch diesen Aufruf der Methode Schritt für Schritt durch:
- Die lokale SPS Variable
aMomentCoef
(in welche nun geschrieben werden soll) wird als Referenz übergeben. - Es wird der Datentyp spezifiziert.
- Es wird die erste Arbeitsdimension des MultiArray der ersten Arbeitsdimension des Variable
aMomentCoef
zugewiesen, also den Kanälen. Die zweite Dimension wird analog übergeben und entspricht im Beispiel den statistischen Parametern count, mean, deviation, skew, kurtosis. - Mit den Parametern
nElementsDim0
undnElementsDim1
wird spezifiziert wie viele Elemente des MultiArray in WorkDim0-Richtung und WorkDim1-Richtung kopiert werden sollen. In diesem Fall also 3 Elemente in WorkDim0-Richtung (alle drei Kanäle) und 2 Elemente in WorkDim1-Richtung. - Der Paramater
pStartIndex
definiert das erste Element in dem 2x3 großen Rechteck, welches kopiert werden soll. Der Paramater ist ein Pointer auf ein 2D-Array (hieraStartIndex
).
In der dargestellten Konfiguration wird die Output2D() Methode lediglich ein Segment des MultiArrays in die SPS Variable aMomentCoef
kopieren. Das zu kopierende Segment wird, wie oben näher erläutert, mit den Parametern nWorkDim0
, nWorkDim1
, nElementsDim0
, nElementsDim1
, und pStartIndex
konfiguriert.