# Mit SCL 2 Dimensionales ARRAY auslesen und zurückkonvertieren (AWL Vorschläge)



## Mtroniker (19 Juni 2008)

Zunächst wollte ich alle in diesem forum begrüßen.

Aktueller Stand:
In einer Matrix UDT wird die Dimension einer Matrix [0..10,0..10] fest im Speicher reserviert. Die Anzahl der Zeilen und Spalten sind in der STRUCT vom Typ int und die einzelnen Elemente der Matrix wird mit 


> elemente: ARRAY[1..10,1..10] *OF REAL*;             //in UDT
> Erstellung der Matrix in FB gemäß:
> A.elemente[1,1]:=2.3;     etc.


um die Matrix von Außen parametrieren zu können werden die einzelnen elemente der Matrix (z.B. A) mittels For-Schleifen beschrieben, dessen values aus einem DB gelesen werden und in einem anderen DB hinterlegt werden.





> DATA_BLOCK DB20 FB20
> BEGIN
> 
> END_DATA_BLOCK


 Da aber auch die Dimension der Matrix Variabel sein soll (mittels input Berechnungen), werden in dem neuen abgelegten DB ebenfalls die  inputs aufgelistet. Somit liegt meine Zeilenanzahl in DB20.DBW18, Spaltenzahl in DB20.DBW20 und das Array in DB20.DBD22 (Anzahl elemente kann ja berechnet werden). Bei einer kleineren Dimension der Matrix wird nur der benötigte Bereich des reservierten Speichers belegt.

Nun möchte ich dieses 2 dimensionale Array auslesen und zurückkonvertieren bzw. in einem separaten DB ablegen damit ich diese Matrix für weitere Berechnungen (in vorhandenen Matrizen Funktionen z.B. Transponieren) heranziehen kann um das Ergebniss erneut in DB's abzulegen.

Datenbausteine sind ja in der S7 vom Typ struct. In meinem DB20 habe ich ein nun zweidimensionales Array hinterlegt. Es muss doch eine rationale Möglichkeit geben, auf diese Matrix Global zugreifen zu können, was ja die DB's in dem Sinne auch erfüllen. 

Eigentlich muss ja nur ein STRUCT mit zwei int Werten und einem Array in SCL aus dem DB in den Originalen Struct umwandeln. STRUCT heißt Matrix.

Mein Problem. In einem DB (DB10) Habe ich nun die neu erstellte Matrix hinterlegt. Die neue Matrix beginnt ab DBD22 und stellt kein in S7 deklariertes Array mehr dar.
Zum Testen würde ich die Matrix gerne in einem FB mittels Funktion *"Transponieren*" (Funktion Fehlerfrei getestet mit Matrix Deklaration im FB selbst).
Hat jemand eine Idee?


----------



## Larry Laffer (19 Juni 2008)

Leider habe ich überhaupt nicht verstanden, was du wissen möchtest ...
Möchtest du das 2-D-Array in ein gleich großes 1-D-Array in einem anderen Daten-Baustein umwandeln ...?
Wenn nein, dann beschreib es doch bitte noch einmal ...

Gruß
LL


----------



## Mtroniker (19 Juni 2008)

Zunächst danke für Deine Bemühung.
Ein Beispiel. Ich lege meine maximale Array größe im UDT vor (s.o. [0..10,0..10]).Mit meinen Inputs in FB20 entsteht nun eine Matrix *A* der Dimension 3x3, dessen Werte aus dem DB10 gelesen werden. FB20 enthält anweisungen, die die Elemente der Matrix A in einer bestimmten Reihenfolge vergibt und im DB20 (siehe Bild 1) ablegt. Die Matrix stellt ein 2 Dimensionales array dar. Wenn ich nun im FB20 meine Matrix A meinem FC input zum Transponieren übergebe, funktioniert es ohne Probleme.
Die Berechnung soll aber nicht in diesem FB ausgeführt werden. Ich möchte nun Global auf meine Matrix in DB20 zugreifen können, damit ich in einem anderen FB meine Operationen ausführen kann. Ich habe wie beschrieben zwei int Werte die Dim. der Matrix bestimmen und das array der abgelegten Matrix (allerdings beginnend DB20.DBD*22*). Wie kann ich diese Matrix in einen DB30 ablegen und global über einen FB zugreifen um mit dieser Matrix wieder rechnen zu können.
Hoffe jetzt ist die Beschreibung etwas präziser.

Allgemein ohne Matrix. Matrix stellt jetzt nur ein 2 Dim. Array dar. Wie bekomme ich die Struktur (STRUCT A) 
mit den zwei int Werten und dem Array in SCL aus dem DB20 in einen anderen DB, damit ich mit diesem und meinen Matrizen Operationen weiter rechnen kann?


----------



## Larry Laffer (19 Juni 2008)

Leider hat auch dein 2.Versuch bei mir noch nicht gefruchtet. Ich versuche trotzdem mal was :

Ich würde zunächst in dem SCL-Script bleiben. Dieses kann ja vortrefflich mit der Indexierung deines Array's umgehen. Auch kannst du mittels SCL in einen anderen DB (den du vielleicht sogar als Parameter übergibst) schreiben. Vielleicht übergibst du hier sogar gleich eine Ziel-Adresse (ANY-Pointer). Welche Einträge deines 2-D-Array's du in den anderen DB (muß es überhaupt ein anderer DB sein ? Kann doch auch in dem gleichen DB bleiben) schreiben willst, weißt du ja. Ich nehm,e an, dass du die Liste fortlaufend füllen willst. Somit kannst du über einen Hilfs-Index direkt den 2.DB indizieren (von SCL aus) und die Daten an die jeweils gewünschten Adressen schreiben.
Bin ich halbwegs in der Spur ?
Wenn ja, brauchst du hier irgendwelche Zusatz-Info ?

Gruß
LL


----------



## Mtroniker (19 Juni 2008)

Genau, für einen bestimmten Fall soll eine Matrix von außen gefüllt werden können. Allerdings liegen im DB20 mehrere Matrizen. Zum vereinfachen habe ich eine Matrix genommen. Aus diesem Grund würde ich gerne für jede erzeugte Matrix aus dem DB20 die einzelnen Matrizen in separate DB's legen. Mit :ANY-Pointer habe ich noch nicht gearbeitet. Vielleicht haben Sie einen nützlichen link oder beispiel-code.

Das Problem ist, dass die erzeugte Matrix als array im DB liegt. Wie meine Matrix UDT (von TYPE Matrix) arbeitet habe ich im ersten Thread geäußert. Damit ich aber mit meinen Functionen weitere Berechnungen führen kann, muss ich aus den arrays die in den DB's liegen wieder diese Konvention erfüllen, da die funktionen als Input den typen Matrix erwarten. Ich meine im FB20 wird A als matrix erkannt. Aber aus einem anderen FB aus habe ich es noch nicht umgesetzt bekommen.

Haben Sie eine Idee. Ein Beispiel zum ablegen des Arrays ("der Matrix") in einen DB sowie das Rückkonvertieren wäre sehr hifreich.


----------



## Larry Laffer (19 Juni 2008)

... ich bin fast sicher, da behilflich sein zu können - sonst hätte ich auch nicht geantwortet ...

Zunächst zum Thema ANY-Pointer zur Adressen- und/oder Bereichs-Übergabe. Hier ist der folgende Beitrag aus der Rubrik FAQ bestimmt hilfreich : http://www.sps-forum.de/showthread.php?t=12923

Die Adressierung von extenen DB's in SCL erfolgt so :
	
	



```
a_Daten [i] := WORD_TO_BLOCK_DB (DB_Nr).DW [Index] ;
 
bzw.

WORD_TO_BLOCK_DB (DB_Nr).DW [Index] := a_Daten [i] ;
```
In AWL ist es wesentlich komplizierter aber genausogut machbar ...

Ich fände es grundsätzlich hilfreicher, wenn wir uns über konkreten Code unterhalten würden ... Eventuell ein Ansatz ...?

Gruß
LL


----------



## Borsti (19 Juni 2008)

Hoihoi...

Wenn ich das richtig sehe, liegt das Problem hier bei sowas wie dynamischer Speicherverwaltung...


> Bei einer kleineren Dimension der Matrix wird nur der benötigte Bereich des reservierten Speichers belegt.


Ich bin mir jetzt nicht sicher, aber mir ist kein Weg bekannt den Speicher einer SPS dynamisch zu verwalten.
Wenn ich das nämlich richtig verstanden habe, sollen bei folgendem Besipiel:
DBD18 = Zeile = 3; DBD 20 = Spalte = 4 ; Array[1..10(3),1..10(4)]
nur 3 * 4 (12) Realwerte abgelegt werden. Also, nur 48 (12Real * 4Byte) Byte belegt werden, statt der üblichen 400 Byte (10*10Real * 4Byte). Und nach den 48 Byte (+Zeile+Spalte=52Byte) eine neue STRUCT angelegt werden.
Hab ich das richtig verstanden?

Oder sollen immer die 404Byte reserviert werden, dann neue 404Byte große STRUCT, dann wieder 404Byte STRUCT, etc...?
Wenn ja, dann wie LL schon sagte über ANY-Pointer kopieren.
Oder in SCL eine FOR Schleife machen, welche 101 mal stur Doppelwörter aus einem DB in einen anderen kopiert (natürlich mit Variabler Anfangsadresse, daher wieder ANY)...

Oder ich hab gar nichts verstanden... 

MfG
Borsti


----------



## vierlagig (19 Juni 2008)

@borsti:

dynamisch verwalten geht so einigermaßen und zwar mit CREATE_DB und DEL_DB ...


----------



## Mtroniker (19 Juni 2008)

@ Borsti


Borsti schrieb:


> Besipiel:
> DBD18 = Zeile = 3; DBD 20 = Spalte = 4 ; Array[1..10(3),1..10(4)]
> nur 3 * 4 (12) Realwerte abgelegt werden.
> Hab ich das richtig verstanden?
> ...



In der UDT muss das Array so groß wie die größt möglich vorkommende Matrix gewählt werden, damit gewährleistet werden kann, alle Matrizen beschreiben zu können. Wenn die Matrix kleiner als der reservierte Bereich ist, wird nur dieser im Speicher belegt. Sehr elegant wäre es natürlich, wenn die UDT der Matrix auch variabel gestaltet werden könnte. Da habe ich noch keine idee, da ich mit UDT's noch nicht viel gearbeitet habe. (siehe ersten Beitrag auf Seite 2 für UDT)

@ alle

In DB10.0 steht der Wert 2.5
In DB10.4 steht der Wert 3.5 etc.

Wäre echt super, wenn für dieses Problem eine Möglichkeit gefunden werden kann. Ich stehe für jegliche Ideen offen und würde gerne noch viel mehr ausprobieren. Vielleicht führts ja zum Ziel. 
Die Sache ist ja, dass ich für weitere Berechnungen der Abgelegten Werte in ensprechenden DB's nicht der Datentyp Matrix aufgewiesen wird. Die Funktionen FC'S für die Matrizen-Operationen erwarten jedoch am Eingang den TYP Matrix. *
In anderen Hochsprachen lässt sich dieses Problem auch relativ einfach lösen. In SCL muss das doch auch möglich sein.
Vielen Dank noch mal an dieser Stelle.*[/quote]Es wäre natürlich sehr gut, wenn BLOCK_DB_TO_MATRIX funktionieren würde. Dabei müssten die hinterlegten int Werte für das 2-D-Array auch beherzigt werden.


----------



## Larry Laffer (20 Juni 2008)

Hallo,
mit dem Beispiel komme ich schon etwas weiter, wobei ich nach wie vor noch kein Bild von dem Problem habe. Aber vielleicht einen schönen neuen Ansatz ...

Wenn ich es richtig verstanden habe (Feedback erwünscht), dann benötigst du den FC eigentlich nur um deine Matrix auch von anders woher beschreiben zu können ...?
Wenn ja, dann hier der Vorschlag :
Deinen FB mit dem DB kannst du in deinem Programm auch mehrfach aufrufen. Du kannst ferner über entsprechende Steuer-Eingänge den FB veranlassen, mal das Eine und bei einem anderen Aufruf das Andere zu tun (z.B. Schreibe Wert in Matrix [x,y] oder lese Wert aus Matrix [x,y]).

Weiterer Ansatz:
Ein DB ist von seiner Struktur her immer ein eindimensionales Array. Innerhalb von SCL kannst du auf diese Struktur aber z.B. mit dem Befehl AT eine vollkommen neue Sicht generieren. Hier mußt du nur aufpassen, dass Quellgröße und Sichtgröße identisch sind.



> Wäre echt super, wenn für dieses Problem eine Möglichkeit gefunden werden kann. Ich stehe für jegliche Ideen offen und würde gerne noch viel mehr ausprobieren. Vielleicht führts ja zum Ziel.
> Die Sache ist ja, dass ich für weitere Berechnungen der Abgelegten Werte in ensprechenden DB's nicht der Datentyp Matrix aufgewiesen wird. Die Funktionen FC'S für die Matrizen-Operationen erwarten jedoch am Eingang den TYP Matrix.


 
Es gibt nicht den Typ Matrix, aber es gibt den Typ UDT. Innerhalb einer UDT kannst du eine beliebige Struktur erzeugen und diese (auch) an andere Funktionen übergeben. Ob das unbedingt ein eleganter Weg ist (Bearbeitungszeit) soll mal dahingestellt sein ...

Soviel bis hierhin - ich bin auf das Feedback gespannt ...
Gruß
LL


----------



## Mtroniker (20 Juni 2008)

@ Larry Laffer


> Wenn ich es richtig verstanden habe (Feedback erwünscht), dann benötigst du den FC eigentlich nur um deine Matrix auch von anders woher beschreiben zu können ...?LL



Also, die FC's benötige ich für die Berechnung von Matrizen. z.B. um eine Matrix zu Transponieren oder zwei Matrizen miteinander zu multiplizieren. Dort sind die Rechenregeln für Matrizen hinterlegt. Wie es auf jeden Fall funktioniert (Wenn Matrizen Fest vorgegeben werden! (jedoch nicht gewünscht)):

```
FUNCTION_BLOCK FB1

VAR
  A, B, C  : MATRIX;
END_VAR
   A.zeilenzahl:= 2;  // Deklaration einer 2x2 Matrix
   A.spaltenzahl:= 2;
   A.elemente[1,1]:= 11;
   A.elemente[1,2]:= 12;
   A.elemente[2,1]:= 21;
   A.elemente[2,2]:= 22;
   
   B.zeilenzahl:= 2;
   B.spaltenzahl:= 2;
   B.elemente[1,1]:= 0.11;
   B.elemente[1,2]:= 12;
   B.elemente[2,1]:= 21;
   B.elemente[2,2]:= 22;

   MxMul( MxA:= A, MxB:= B, MxC:= C);  // A*B=C  (Matrix Multiplikation)
   //
END_FUNCTION_BLOCK

//---------------------------------------------------------------------------
DATA_BLOCK DB1 FB1
BEGIN

END_DATA_BLOCK

//---------------------------------------------------------------------------
ORGANIZATION_BLOCK OB1
 //call
VAR_TEMP
  info : ARRAY[0..19] OF BYTE; //reserviert
END_VAR
   FB1.DB1();
END_ORGANIZATION_BLOCK
```
Um meine Matrizen nicht fest vorzugeben wurde mittels FOR-Schleifen in die elemente der Matrix geschrieben, dessen Werte im DB bzw. DB's abgelegt wurden.

```
FOR i := 1 TO input1*input2 BY 1 DO
 A.elemente[i,i] := DWORD_TO_REAL (DB10.DBD[i*4-4]); [/quote]Wenn Sie nochmal in meinen letzten Beitrag gucken, liegt nun in dem DB eine Diagonalmatrix. Wie Sie mir ja gesagt haben mit der Dimension 1. Meine Funktionen erwarten jedoch ein zwei Dimensionales Array (aus Matrix UDT "Type Matrix") als INPUT.
[code]VAR_INPUT
    MxA: MATRIX;
    MxB: MATRIX;
END_VAR

VAR_OUTPUT
    MxC: MATRIX;
END_VAR
```
Die Matrizen "A,D,E" (siehe letzten Beitrag Bild 1.2) liegen als ein Dimensionale Arrays im DB. Wie kann ich die wiederum an meine FC'S übergeben, die den Datentyp Matrix als Input erwarten.

Der Vorteil an der ganzen Überlegung liegt darin, die Matrizen Global von außen vorgeben zu können und für jede zwischenberechnungen das Ergebnis in einen separaten DB abzulegen, damit mit dem Zwischenergebnis weitergerechnet werden kann. Das soll eigentlich die Bearbeitungsschritte kürzen, da bestimmte zwischenergebnisse an anderen stellen benötigt werden "könnten".
Jetzt sollte die Problemstellung bei Ihnen sehr nahe gekommen sein.


----------



## Larry Laffer (20 Juni 2008)

Zum letzten Punkt:
Hierfür wäre der Any-Pointer prädestiniert.
Der genannte übergibt die Informationen eines Datenbereichs an eine andere Routine. Er könnte also so aussehen :

```
DB1.DBX814.0 Byte 404
oder auch
DB1.DBX818.0 REAL 100
```
 
An dieser Stelle kommt aber lediglich eine Bereichs-Information zum Tragen. es halt nur ein Pointer. Derselbe müßte in der Ziel-Prozedur wieder zerlegt werden. Hier wäre es dann aber gar kein Problem mehr, die Daten in ein vollkommen anderes ARRAY zu schreiben.

Eine andere Möglichkeit, die ich sehe, wäre, dem Quell-FB schon gleich die Info zu geben, das und wo er die (oder auch bestimmte) Daten hinzuschreiben hätte. 

Passt das jetzt für dein Problem ?

Gruß
LL


----------



## volker (20 Juni 2008)

zu meinem verständnis.

dein typ matrix hat nicht immer die gleiche länge.
die länge ergibt sich aus zeilen * spalten ? richtig?
z.b.
zeilen = 2, spalten = 3
=> elemente array(1..2,1..3) richtig?

nun möchtest du, das der udt matrix automatisch so aufgebaut wird und dann so aussieht ?

```
STRUCT
    zeilenanzahl: INT := 2;
    spaltenanzahl: INT := 3;
    elemente: ARRAY[1..2,1..3] OF REAL;
END_STRUCT
```
das geht nicht.
du kannst dir zwar die adressen berechnen wo a,d,e beginnt und auch die länge des benötigten dbs errechnen können.
aber in der onlineansicht des db wirst du das nicht so sehen können da du einen udt nicht aus dem prog heraus ändern kannst. die anzahl der werte im array lässt sich leider nicht variabel gestallten
wie z.b. so 
elemente: ARRAY[1..zeilen,1..spalten] OF REAL

programmtechnisch was die funktion betrifft ist das natürlich machbar. der steuerung ist es völlig egal (hautsache der db ist lang genung) was du für einen text du am db stehen hast. der ist nur für uns zum besseren verständnis.


----------



## Mtroniker (20 Juni 2008)

@ Volker 





volker schrieb:


> zu meinem verständnis.
> 
> dein typ matrix hat nicht immer die gleiche länge.
> die länge ergibt sich aus zeilen * spalten ? richtig?
> ...


Alles richtig so weit. Gut, die UDT Variabel zu gestalten wäre dann geklärt. Das geht bei UDT's dann nicht. Damit kann ich leben. Wie kann aber nun das Array aus Bild 1.1 bzw. Bild 1.2 [z.B. die Matrix A und D] meiner Funktion als Bausteinparameter übergeben werden, der als INPUT 

```
VAR_INPUT
    MxA: MATRIX;
    MxB: MATRIX;
END_VAR

VAR_OUTPUT
    MxC: MATRIX;
END_VAR
```
Matrix erwartet.
z.B.
Jetzt will ich Matrix A mit Matrix D multiplizieren gemäß:

```
MatxMul( MxA:= A, MxB:= D, MxC:=G)
```
Fehler beim kompilieren: ungültiger Datentyp. (nicht das es mich wundert) Nur wir bekomme ich den Datentyp wieder aus dem Array?


----------



## Ralle (20 Juni 2008)

Ich hab das immer noch nicht so gerafft, hab mal Folgendes probiert. Die Array werden per UDT definiert und in einem Datenbaustein abglegt.

*AWL-Quelle:*

```
TYPE "MATRIX"
  STRUCT 	
   zeilenanzahl : INT ;	
   spaltenanzahl : INT ;	
   elemente : ARRAY  [1 .. 10, 1 .. 10 ] OF REAL ;	
  END_STRUCT ;	
END_TYPE

DATA_BLOCK "Matrixarray"
TITLE =
VERSION : 0.1


  STRUCT 	
   A : "MATRIX";	
   D : "MATRIX";	
   G : "MATRIX";	
  END_STRUCT ;	
BEGIN
 
END_DATA_BLOCK

ORGANIZATION_BLOCK "Main"
TITLE = "Main Program Sweep (Cycle)"
VERSION : 0.1


VAR_TEMP
  OB1_EV_CLASS : BYTE ;	//Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
  OB1_SCAN_1 : BYTE ;	//1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
  OB1_PRIORITY : BYTE ;	//Priority of OB Execution
  OB1_OB_NUMBR : BYTE ;	//1 (Organization block 1, OB1)
  OB1_RESERVED_1 : BYTE ;	//Reserved for system
  OB1_RESERVED_2 : BYTE ;	//Reserved for system
  OB1_PREV_CYCLE : INT ;	//Cycle time of previous OB1 scan (milliseconds)
  OB1_MIN_CYCLE : INT ;	//Minimum cycle time of OB1 (milliseconds)
  OB1_MAX_CYCLE : INT ;	//Maximum cycle time of OB1 (milliseconds)
  OB1_DATE_TIME : DATE_AND_TIME ;	//Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =

      CALL "Mulaufruf" (
           RET_VAL                  := MW    10);

END_ORGANIZATION_BLOCK
```

*SCL-FC100: MatMul*


```
FUNCTION MatMul : INT

VAR_INPUT
    MxA: UDT10;//MATRIX;
    MxB: UDT10;//MATRIX;
END_VAR

VAR_OUTPUT
    MxC: UDT10;//MATRIX;
END_VAR

VAR_TEMP
    // temporäre Variablen

END_VAR

    // Anweisungsteil
    
       
    ;
    MatMul := 100;
END_FUNCTION
```

*SCL-FC101:Mulaufruf*


```
FUNCTION Mulaufruf : INT

VAR_TEMP
    // temporäre Variablen
  Erg: Int;
END_VAR

    // Anweisungsteil
    
    Erg := MatMul( MxA:= "Matrixarray".A, MxB:= "Matrixarray".D, MxC:="Matrixarray".G);
    
    
    Mulaufruf := 101;
    
END_FUNCTION
```


Das läßt sich zumindest übersetzen, also könnte man die Matritzen durchaus als UDT übergeben, diese liegen in einem globalen DB. 

Was allerdings nicht geht, eine UDT als Durchgangstyp zu übergeben. Da weigert sich Step7. Willst du also deine UDT an weitere Funktionen nach "unten" durchreichen, geht das nur über Larry's Vorschlag, einen Zeiger oder Any-Pointer zu übergeben.

PS: Ich würde dann diesen Pointer zerlegen und die Daten von der daraus resultierenden Adresse per Blockmove (SFC20) in eine interne Struct kopieren, diese dann weiterreichen. Ob das "Weiterrreichen" und nochmalige "Umkopieren" allerdings so einfach geht, bleibt auszutesten.

Vielleicht wäre es am Einfachsten, immer einen Zeiger zu übergeben, dann erst zum Rechnen die Daten umzukopieren und danach das Ergebnis zurückzukopieren und auch dieses als Zeiger zurückzugeben.


----------



## volker (20 Juni 2008)

Mtroniker schrieb:


> aus PN
> Dabei bin ich im Downloadbereich auf ein 2-D-Array gestoßen. Meine 2-D-Arrays beschreiben ja nichts anderes als eine Matrix mit zeilen und spalten. Vielleicht haben Sie ja noch eine sehr gute Idee für mein Anliegen.
> 
> Unterschied (nach meinem Verständnis): Ihre arrays liegen alle in einem eigenen DB. So wie ich es gelöst habe, ensteht in einem DB (DB20) Mehrere Matrizen in bestimmten Datenbereichen. Nüzlich wäre es, wenn ich nun diese erzeugten Matrizen in eigene DB's ablegen könnte um diese dann an meine Function (multipliziere Matrix) als Bausteinparameter übergeben könnte. Als Eingang erwartet die Funktion den Typ Matrix, die im UDT definiert wurde. Siehe nochmal im Thread. Ich habe auf Ihren Bericht nochmals eine Antwort erstellt



@ralle
da sich der udt ja immer, abhängig von zeilen/spalten, ändert geht das so nicht.
ich würde garnicht den udt übergeben sondern nur die db-nr.

im anhang mal ein prog als awl-quelle
das prog löscht auf anforderung die bestehenden db's und erzeugt diese dann neu in abhängigkeit der anzahl der elemente.
fc102 multipliziert dir die elemente des matrix_db_1 mit matrix_db_2.
das ergebnis liegt im matrix_db_3


----------



## Mtroniker (20 Juni 2008)

Jetzt nochmal alles vergessen, was im vorfeld besprochen wurde. Ich glaube manch zusatzinformationen haben Verwirrung gestiftet.


```
UDT
Zeilenanzahl : int:
Spaltenanzahl: int;
```

Ich habe ein Struct vom Typ Matrix im DBxxx (siehe Bild 2.1). Ich möchte nun diese Struct in ein User Datentyp Matrix (gleicher aufbau wie im DB) von einer anderen SCL aus zuückwandeln.
Gibt es etwas wie ein typecast oder ähnliches.
Das muss wessentlich einfacher gehen.
___________
Gruß
Micha


----------



## Ralle (20 Juni 2008)

Ich denke, du mußt die gleiche UDT (Struct) in der SCL-Funktiion als Variable zuweisen und deine Daten dann dort hinein kopieren. Evtl. geht das einfacher mit der AT-Zuweisung in SCL, das ist ja eine Art Typecast, allerdings muß man das mal ausprobieren. 

@Volker

Ist schon klar, aber man kann ja ein Array [0..10, 0..10] vereinbaren und dann mit Zeilen- und Spaltenzahl die tatsächlich für die Matrix genutzte Anzahl angeben. Das ist zwar einiges an verschenktem Speicherplatz, aber das variabelste, was man machen kann.


----------



## Mtroniker (20 Juni 2008)

@ Ralle


> Ich denke, du mußt die gleiche UDT (Struct) in der SCL-Funktiion als Variable zuweisen und deine Daten dann dort hinein kopieren. Evtl. geht das einfacher mit der AT-Zuweisung in SCL


Könntest du ein Beispiel für beides posten?


Was jetzt zu funktionieren scheint: Ich Rufe aus einem x beliebigen FB die Function TRANSPONIERE auf. Ich übergebe die Matrix DB20.A.

```
MatxTransp( MxA:= [SIZE=3][B]DB20.A[/B][/SIZE], MxA_transp:=G)
```
Der Compiler gibt keinen Fehler aus. 
Ja, es funktioniert. Vielen Dank an alle.

Beispiel von Ralle würde ich dennoch gerne sehen.


----------



## Ralle (20 Juni 2008)

Mtroniker schrieb:


> @ Ralle
> Könntest du ein Beispiel für beides posten?
> 
> 
> ...



Das Beispiel müßte ich mit auch erst zurechtklimpern, war auch erstmal eine rein theoretische Überlegung, da ich eher selten UDT und Struct nutze. Daher erstmal kein Beispiel, leider. Zum Thema AT gibts hier einiges schon im Forum zu lesen. Mit dem Umkopieren meine ich folgendes:

Im FC eine Temp (oder im FB auch Stat) mit deiner UDT definieren.
Dann dem einen Any übergeben (siehe Larry). Ich glaube, wenn man eine Struct übergibt kann man selbst daraus diese Daten gewinnen, da wohl eigentlich auch ein Any übergeben wird. Der Any enthält im Prinzip, den DB, den Start und die Länge der Daten. Diese Daten aus dem Any extrahieren (siehe Forum und AT-Befehl). Nun könnte man mit dem SFC 20 (Blk_Move) die im FC definierte Variable mit Daten füllen. Auf diese Variable kann man anschließend im FC zugreifen. Das klingt sehr umständlich, wenn man es aber mal umgesetzt hat, kann man es immer wieder verwenden.


----------



## Ralle (21 Juni 2008)

So, ich hab mal was probiert. Die Variante mit Any schein bei FC nicht so einfach zu funktionieren, daher hab ich es mal mit FB versucht. Wie es aussieht, kann man dann aber doch gleich die Struct durchreichen. Deshalb hab ich folgende Konstellation zum Test gewählt:

OB1 --> Baustein "Aufruf" ruft Baustein "SubAufruf" mit Übergabe der Martix als Parameter --> Baustein "Subaufruf" ruft Baustein "MatMul" und reicht die Matix durch. Dabei hab ich eine Multiinstanz gewählt, das spart einen DB, es geht aber auch ohne Multiinstanz.

OB1


```
CALL  "Aufruf"
       RET_VAL:=MW10
```
 
FC101 - "Aufruf"


```
FUNCTION Aufruf : INT
 
VAR_TEMP
    // temporäre Variablen
  Erg: Int;
END_VAR
    // Anweisungsteil
    SubAufruf.DB1(MxA2 := "Matrixarray".A // IN: STRUCT
                 ,MxB2 := "Matrixarray".D // IN: STRUCT
                 ); 
       "Matrixarray".G := DB1.MxC2; // OUT: STRUCT
 
    Aufruf := 101;
 
END_FUNCTION
```
 
FB99 - "SubAufruf"


```
FUNCTION_BLOCK SubAufruf
VAR_INPUT
    MxA2: MATRIX;
    MxB2: MATRIX;
END_VAR
VAR_OUTPUT
    MxC2: MATRIX;
END_VAR
VAR_TEMP
    // temporäre Variablen
  Erg: INT;
END_VAR
VAR
    // statische Variablen
   MatMul_Stat: MatMul;
END_VAR
    // Anweisungsteil
 
   MatMul_Stat(MxA2 := MxA2 // IN: Struct
              ,MxB2 := MxB2 // IN: Struct
              ,MxC2 := MxC2 // INOUT: Struct
              ); 
 
END_FUNCTION_BLOCK
```
 
FB100 - MatMul
Der Code darin ist nur zum Testen, stellt nicht die Multiplikation einer Matritze da!


```
FUNCTION_BLOCK MatMul
VAR_INPUT
    MxA2: Matrix;
    MxB2: Matrix;
END_VAR
VAR_IN_OUT
    MxC2: Matrix;
END_VAR
VAR_TEMP
    // temporäre Variablen
END_VAR
VAR
    // statische Variablen
END_VAR
    // Anweisungsteil
 
    MxC2.elemente[1,1] := MxA2.elemente[1,1] + MxB2.elemente[1,1];
    MxC2.elemente[2,1] := MxA2.elemente[2,1] + MxB2.elemente[2,1];
 
END_FUNCTION_BLOCK
```
 
Hoffe, das hilft dir weiter, wäre auf jeden Fall die einfachste Variante. Allerdings etwas Datenintensiv, da der InstanzDB nochmals die Matrizen enthält. Mit TempVar wäre man wahrscheinlich ohnehin an die Grenzen der S7 gestoßen, da eine 10x10 Real-Matritze schon fast die Standardeinstellungen für lokale Variablen sprengt und diese nur bei 400-er und VIPA Speed7 verstellt werden können.


----------



## Larry Laffer (21 Juni 2008)

So, jetzt bin ich wieder mit an Bord ...



Mtroniker schrieb:


> Jetzt will ich Matrix A mit Matrix D multiplizieren gemäß:
> 
> ```
> MatxMul( MxA:= A, MxB:= D, MxC:=G)
> ...


 
Ich muß mich hier noch mal dran hängen.
In dem dargestellten Beipiel soll MxC eine Output Matrix sein. Das ist das Problem. Du übergibst an dieser Stelle nicht eine Variable sondern einen Pointer. Dieser wird aber nicht aus deiner Funktion heraus generiert, sondern nur benutzt. 

Zu Beachten bei dieser Vorgehensweise (gilt auch für den Gebrauch von ANY-Pointern) :
Im eigentlichen Ziel-Code (übersetztem Script) werden aus diesen Pointern schlußedlich angepasst Daten-(Wort) hin- und her-Kopier-Funktionen. Das schlägt sich dann shon in der Laufzeit (Zykluszeit) des Programms nieder.

Gruß
LL

Schon zum Teil in der Erklärung von Ralle enthalten ...


----------

