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.

Umgang mit MultiArray 1:

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.

Umgang mit MultiArray 2:

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:

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.

Umgang mit MultiArray 3:

Der FB_CMA_Sink Funktionsbaustein erfordert keinerlei Initialisierung eines MultiArray. Die Shape der von FB_CMA_Sink verwendeten MultiArrays wird intern spezifiziert.

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:

Umgang mit MultiArray 4:

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:

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:

Umgang mit MultiArray 5:

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.