# Codesys Array of Word -> Beliebiges Struct



## MSB (25 Dezember 2007)

Hardware: Wago 750-841 + 750-650

Ich test gerade die HMI-Kommunikation zwischen dem Controller und einem Bediengerät.
Die Kommunikation ansich funktioniert schon ohne Probleme.

Ich verwende zur Kommunikation die Wago-Library TerminalSlave_04, mit den Baustein "TERMINAL_MODBUSSLAVE_RTU".
Als Datenfeld hat dieser ein Array of WORD, mit variabler Länge (VAR_GLOBAL Constant).

Wie kann man nun am geschicktesten dieses Array irgendwelchen Globalen Variablen, oder einem Datentyp zuweisen,
unter beibehaltung der Lese/Schreib Funktionalität des Arrays?

Der AT Befehl funktioniert ja scheinbar nur für "echte" Adressen.

Mfg
Manuel


----------



## zotos (25 Dezember 2007)

Der Baustein ist mit zwar nicht bekannt aber laut der Doku von WAGO ist die Variable (VAR_IN_OUT) aDATA vom Typ typSLAVE_DATEN was einem WORD-ARRAY entspricht.
 
Also wenn Du jetzt eine globale Variable vom Typ typSLAVE_DATEN anlegst und in Deinem Programm beschreibst werden die Daten an den FB TERMINAL_MODBUSSLAVE_RTU übergeben, der wiederum ändert die Variable ab und Du kannst die Variable auswerten.

usw.


----------



## MSB (25 Dezember 2007)

Insoweit sind wir uns ja einig.

Ich habe nun letzten Endes ein Array,
also ARRAY [0..255] OF WORD.

Also eine Globale Variable:
Datenfeld: typSlave_Daten; an der entsprechenden Stelle an den FB geschrieben ...

Wie mache ich nun sinngemäß sowas:
Sollwert AT Datenfeld[0]: REAL;

Mfg
Manuel


----------



## zotos (25 Dezember 2007)

MSB schrieb:


> ...
> Wie mache ich nun sinngemäß sowas:
> Sollwert AT Datenfeld[0]: REAL;
> ...



Also Du willst das "aufdröseln"?

Angenommen Du hast ein Array mit 256 Word Werten. Und Du weist ganz genau welches einzelne Byte welche Funktion hat, kannst Du doch ein eigenen Datentyp anlegen der in Summe UND in der Reihenfolge dem Übereinstimmt (*WICHTIG*: eine einfache BOOL Variable ist ein BYTE lang!). 

Ich interpretiere das in das REAL da oben mal rein, dass Du das weist.

So das mit dem AT geht ja nur auch echte Adressen. Aber man kann mit Pointern arbeiten und das ganze Kopieren.



```
VAR
  myDATA    : myType;                      (* Programminterne Daten *)
  ExtDATA   : typSLAVE_DATEN;              (* Externe Daten von dem IN_OUT vom FB *)
  pExtDATA  : POINTER TO myType;
  pMyDATA   : POINTER TO typSLAVE_DATEN;
END_VAR


(* Pointer ermitteln *)
pExtDATA := ADR(ExtDATA);
pMyDATA  := ADR(myDATA);

(* Daten Manipulieren im Programm *)
myDATA.Erstes[0] := 123;

(* vor dem FB aufruf Programminterne Daten an den FB übergeben *)
extDATA   := pMyDATA^;

(* FB Aufruf hier Symbolisch verändern von Daten *)
ExtDATA.typSLAVE_DATEN[128] := 321;

(* nach dem FB Aufruf die externen Daten auf die interne variable kopieren *)
myDATA   := pExtDATA^;
```
Wenn jemand eine bessere Idee hat bin ich gerne bereit zu lernen.


----------



## MSB (25 Dezember 2007)

Also ich habe jetzt auch noch eine Variante entdeckt, auch wenn ich mir über die Auswirkung nicht 100% im klaren bin.

Wenn ich die Globale Variable so deklariere:

VAR_GLOBAL RETAIN PERSISTENT
Datenfeld AT %MW0 :typ_SlaveDaten;
END_VAR

Es hat sich nun die Projektgröße auf dem Controller von 26kB auf 150kB erweitert, aber das alleine ist ja noch nicht kritisch, oder?
Dann kann ich frei auf die Merkerwörter zugreifen, und muss mir in dem Sinn keine Gedanken machen,
und auch nichts gesondert programmieren.

Das ist zwar sicher nach der Codesys-Philosophi nicht der eleganteste weg,
aber es ist auf jeden Fall ein sehr einfacher Weg, wie ich praktisch "beliebig"
auf das Array zugreifen kann.

Wie gesagt ich kommuniziere über dieses Array mit dem Bediengerät, und dafür ist mir die Variante von Zotos
offengestanden ein wenig aufwendig.

Nachteil: Ich verblase unmengen an Merkerwörtern, andererseits, wofür braucht man die Sonst,
wenn nicht für sowas?

Mfg
Manuel


----------



## zotos (25 Dezember 2007)

Du hast recht das kann man so machen.

Ich würde trotzdem eine Struktur anlegen und beide mit AT auf den Merkerbereich setzen dann hat man eine eindeutigere Zuordnung das es ein Datenverbund ist.

VisuDaten.Sollwert := 123.4;


----------



## MSB (25 Dezember 2007)

Das Bediengerät welches ich daran betreibe hat auch ein paar Wörter Datenaustauch.

Das wäre z.B. das erste Wort im Datenaustausch.

```
BZ0 : BOOL ;    (* BEEP Hakko Panel *)
       BZ1 : BOOL ;    (* BEEP-BEEP Hakko Panel *)
       BZ2 : BOOL ;    (* BEEP_Contionously *)
       Calendar_Setting : BOOL ;    (*  *)
       Unused_0_4 : BOOL ;    (*  *)
       Unused_0_5 : BOOL ;    (*  *)
       Unused_0_6 : BOOL ;    (*  *)
       Unused_0_7 : BOOL ;    (*  *)
       Unused_1_0 : BOOL ;    (*  *)
       Unused_1_1 : BOOL ;    (*  *)
       Unused_1_2 : BOOL ;    (*  *)
       Unused_1_3 : BOOL ;    (*  *)
       Unused_1_4 : BOOL ;    (*  *)
       Unused_1_5 : BOOL ;    (*  *)
       Unused_1_6 : BOOL ;    (*  *)
       Unused_1_7 : BOOL ;    (*  *)
```
Nun teilt Codesys ja jedes BOOL einem "neuen" BYTE zu, wie du das ja schon angedeutet hattest, kann man das irgendwie verhindern?
Oder wie könnte ich genau dieses erste Wort und nicht die ersten 8 Wörter (16 Bytes) mit dieser Strucktur belegen?

Mfg
Manuel


----------



## zotos (26 Dezember 2007)

Also das einzige was mir da jetzt auf Anhieb einfällt ist, dass erste Word auch in Deinem Struct als Word zu verwenden. Dieses Word auf die Daten diese Variable dann eben in Deinem Programm auch zu verwenden und mit dem Bitoperator auf die einzelnen Bits zu zu greifen. Was besseres fällt mir gerade nicht ein.

Siehe auch: http://www.sps-forum.de/showpost.php?p=111150&postcount=22


----------



## Professor (1 Januar 2008)

Moin,

vielleicht hilft euch ja das ein Stückchen weiter:

http://forum.3s-software.com/viewtopic.php?t=1028&highlight=

Ist von hinten durch die Brust funktioniert aber und ihr bekommt symbolischen Zugriff auf die Bits eines Worts.

Grüße an allen denen das hift


----------

