# Einausgaenge in Structur initialisieren



## Ebias (5 März 2009)

Ich moechte die IO variablen in folgender Structur initialisieren:
TYPE T_CYL :
STRUCT
 ndi_on   : BOOL;
 ndi_off   :BOOL;
 ndo_on  :BOOL;
 ndo_off   :BOOL;
 pb_on :BOOL;
 pb_off :BOOL;

END_STRUCT
END_TYPE

Habe folgendes versucht:

IF NOT bFlag
THEN
 bFlag := TRUE;
 cyl_sig.ndi_off  := %IX0.0 ;
 cyl_sig.ndi_on  := %IX0.1;
 cyl_sig.ndo_off  := %QX0.0;
 cyl_sig.ndo_on := %QX0.1;
 cyl_sig.pb_off  :=%M*;
 cyl_sig.pb_on  :=%M*;

END_IF;

cyl_sig.ndo_off := cyl_sig.ndi_off OR cyl_sig.pb_off;
cyl_sig.ndo_on:= cyl_sig.ndi_on OR cyl_sig.pb_on;

Funtioniert aber leider nicht.
%IX0.0 kann einschalten, aber cyl_sig.ndi_off wird nicht gesetzt.
Natuerlich cyl_sig.ndo_off natuerlich auch nicht.

Vielen Dankf fuer jede Hilfe.


----------



## trinitaucher (5 März 2009)

Ebias schrieb:


> IF NOT bFlag
> THEN
> bFlag := TRUE;
> cyl_sig.ndi_off  := %IX0.0 ;
> ...


cyl_sig.ndi_off  := %IX0.0 gilt nur für einen Zyklus, nämlich solange bFlag  = FALSE ist. Nur in diesem Zyklus findet eine Zuweisung des Zustands von %IX0.0  auf cyl_sig.ndi_off usw. statt. War  %IX0.0 im Zyklus der Zuweisung = FALSE, dann bleibt das auch so. 

Das Konzept geht so nicht, wenn du damit bezwecken willst, dass während des ganzen Programms die EIn-/Ausgänge abgefragt werden.

Du könntest gleich bei der Deklaration in der Struktur die E/As zuweisen oder das ganze gleich über Variablen machen.
Oder lass gleich diese bFlag-Abfrage sein.


----------



## Ebias (5 März 2009)

Die IO variablen sollen eher auf die physicalischen Ein/Ausgaenge zeigen.
Pointer habe ich auch schon versucht, aber nicht den richtigen Weg gefunden.
Die Structure direkt zu initialisieren geht nicht, da ich sie ja fuer eine Anzahl von
Cylindern einsetzen will.


----------



## Ralle (5 März 2009)

Vielleicht hilft dir das etwas weiter: http://www.sps-forum.de/showthread.php?t=21157&highlight=zuweisen

In irgendeinem Beitrag hatten wir mal die unterschiedlichen Möglichkeiten diskutiert, einem FB seine In und Out zuzuweisen. Leider kann ich den Beitrag gerade nicht finden.


----------



## Ebias (5 März 2009)

Stimmt. Den Beitrag habe ich gesehen. 
Aber, ich glaube es endet nicht recht conclusiv.


----------



## trinitaucher (5 März 2009)

Und wieso mappst du nicht zunächst alle in Frage kommenden I/Os auf Variablen ...

```
bIn1 := %IX0.0;
bIn2 := %IX0.1;
```
Und später im Programmablauf machst du dann nur noch:

```
cyl_sig.ndi_off  := bIn1  ;
cyl_sig.ndi_on  := bIn2 ;
```
usw.

Ich verstehe noch nicht so recht den Anwendungsfall und den Grund für dein "bFlag". Eine einmalige Zuweisung macht für mich keinen Sinn, wenn du später auf die Eingänge reagieren willst.
Wenn du während des Programms dynamisch die I/Os auf verschiedene Strukturinstanzen mappen willst, bleibt dir gar keine andere Möglichkeit als entweder (statisch) die I/Os durch Variablen (oder auch direkt) zuzuweisen oder (dynamisch) mit Pointern zu arbeiten.
Kannst du mal bitte näher erläutern?

btw.:
Verwendet du TwinCAT oder nen allgemeines CoDeSys?


----------



## Ebias (5 März 2009)

Der Gedanke hinter dem bFlag ist das am begin des Programs initialisiert wird. Eben Pointer oder dergleichen.
Und dann laeuft das Program ja eh zyklisch im Task.
Die cyl_sig structure soll eben alle signale halten, die fuer einen simplen zylinder noetig sind. Die structure soll dann in einem FB_Cyl sein Zuhause finden. Der FB_cyl waere dann der blue print fuer simple zylinder.
Pointer waeren eh okay. Aber wie ist die frage. Auf ein/ausgaenge kann ich nur mit BITADR dereferenzieren. Sobald ich dann aber versuche mit ^ zu referenzieren stuerzt mit die echtzeit mit einem page fehler ab. D.h. der pointer pointed nicht richtig.
Was waere das gegenstueck fuer BITADR, oder wie kann ich IO referenzen an einen FB weiter reichen. Oder gibt es ein array mit einem system namen in dem die IOs liegen ?

Vielen Dank fuer die Hilfe!

P.S. TwinCat


----------



## trinitaucher (5 März 2009)

Na wenn du eh TwinCAT nutzt, dann pfeiff doch auf die Adressierung 

Bastel dir den Baustein und mach die Adressierung so:

```
FUNCTION BLOCK FB_Zylinder
VAR
  ndi_on [B]AT%I*[/B]: BOOL;
  ndi_off [B]AT%I*[/B]: BOOL;
...
END_VAR
```
Oder du deklarierst die I/Os noch eine Ebene höher schon in den Strukturen:

```
TYPE T_CYL :
  STRUCT
    ndi_on [B]AT%I*[/B]: BOOL;
    ndi_off [B]AT%I*[/B]: BOOL;
    ndo_on [B]AT%Q*[/B]: BOOL;
    ndo_off [B]AT%Q*[/B]: BOOL;
    pb_on :BOOL;
    pb_off :BOOL;
  END_STRUCT
END_TYPE
```
Später instanzierst du dann soviele FBs wie du willst. Im System Manager tauchen die dann alle als I/Os deiner FBs auf:

```
FB_1.ndi_on
... 
FB_2.ndi_on
...
```
oder tiefer in den Strukturen

```
FB_1.stMyStruct.ndi_on
... 
FB_2.stMyStruct.ndi_on
...
```
und du kannst die schön verlinken.

Mit Pointer arbeiten würde ich dir nicht empfehlen. Wie du schon bemerkt hast, kann da einiges in die Hose gehen.
Da die I/Os ja eh beim Systemstart feststehen, benötigst du doch auch gar keine dynamische Adressierung, oder? Oder ändert sich die elektrische Verschaltung während des Ablaufs? Denke mal eher nicht.


----------



## Ralle (5 März 2009)

@trinitaucher

Genau das meinte ich. Den Beitrag hatte ich nicht mehr gefunden, indem das vor einiger Zeit mal behandelt wurde.


----------



## Ebias (6 März 2009)

Das hoert sich soweit gut an,
gibt mir aber den compiler error:

       ERROR 3278: T_CYL(5) invalid address: '%I*'

Gleiches natuerlich auch fuer die Ausgaenge.


----------



## Gerhard K (6 März 2009)

ich bin hier zwar nicht so gut aber ich denke statt dem'%I*' sollst du deinen Eingang( IX0.0) einfügen.


----------



## Ebias (6 März 2009)

Das setzt sich dann aber bei allen instantzen der structure fort.
Dh. 

cyl1 T_CYL;
cyl2 T_CYL;

Verwenden die gleichen Ein/Ausgaenge.
Das sollte aber nicht sein.

Vielen Dank.


----------



## MarkusP (6 März 2009)

@ Gerhard K:

nein, bitte nicht!

LG


----------



## MarkusP (6 März 2009)

> ERROR 3278: T_CYL(5) invalid address: '%I*'


 
Das muss funktionieren, kannst Du Dein Programm mal einstellen oder mir schicken?

LG


----------



## Gerhard K (6 März 2009)

ok.ich kenn mich da nicht so gut aus.also doch mit sternchen??


----------



## Ebias (6 März 2009)

... heisst das, nicht dies ( IX0.0)  verwenden,
oder die Ausgaengen sollen sich nicht ueber die structuren kopieren?


----------



## MarkusP (6 März 2009)

@Gerhard K
Ja, der Fehler muss irgendwo anders liegen. Ich verwende z.B. in meinen Programmen keine einzige direkt adressierte Variable. Genau das macht für mich eine Hardware unabhängige Programmierung aus.

LG


----------



## Ebias (6 März 2009)

Ja, ich schicke direkt.


----------



## Ebias (6 März 2009)

Hier ist das pro file.


----------



## trinitaucher (6 März 2009)

TwinCAT kann mit indirekten Adresse umgehen. %I* oder %Q* sollte kein Problem sein! ...ich nutz auch nichts anderes.

@ Ebias:
Was fürn Zielsystem verwendest du? Einen PC/CX oder nen BC?


----------



## Ebias (6 März 2009)

Ich verwende einen PC.


----------



## trinitaucher (6 März 2009)

Achso, war vielleicht mein Fehler!

Du kannst die I/Os nicht schon in der Struktur deklarieren, sondern erst in in der jeweiligen Instanz. Da eine Struktur ja quasi ein Variablentyp ist.

Du musst wahrscheinlich eine Struktur nur für Eingänge und eine nur für Ausgänge erstellen und dann bei der Deklaration sagen:

```
VAR
  stMyInStruct AT%I*: stInStruct;
  stMyOutStruct AT%Q*: stOutStruct;
END_VAR
```

Sobald du in deinem Beispiel feste Adressen bei der Struct einträgst funktionierts. Ich glaube hier kann TwinCAT die indirekten Adressen nicht zuordnen.


----------



## MarkusP (6 März 2009)

Ich habe mir Dein Programm angeschaut.


```
TYPE T_CYL :
  STRUCT
    ndi_on AT %I*: BOOL;
    ndi_off AT %I*: BOOL;
    ndo_on AT %Q*: BOOL;
    ndo_off AT %Q*: BOOL;
    pb_on :BOOL;
    pb_off :BOOL;
  END_STRUCT
END_TYPE
```
Soweit ich weiß, darfst Du das mit %I* bzw. %Q* nicht direkt in der Struktur so schreiben, sondern erst, wenn Du die Struktur dann verwendest. Also in der Form:


```
TYPE T_CYL_IN :
  STRUCT
    ndi_on : BOOL;
    ndi_off : BOOL;
......

VAR
  Zylinder1 AT %I*: T_CYL_IN;
END_VAR
```

LG


----------



## MarkusP (6 März 2009)

Ich nutze aber auch noch nach Möglichkeit Funktionsbausteine, und deklariere dort über VAR_INPUT Variablen in der Form %I* bzw. VAR_OUTPUT in der Form %Q*. Jede Instanz legt nun Ein- bzw. Ausgangsvariablen an, die Du nach Belieben verknüpfen kannst. Der Vorteil von Strukturen liegt in der einfachen Erweiterbarkeit, ohne dass Bausteine nachträglich größer oder kleiner werden. In CFC kann das nämlich sehr ungut werden...

LG


----------



## Ebias (6 März 2009)

Okay, habe ich dann auch gemacht.
Die Ein/Ausgaenge statt dessen in dem FB angelegt, mit AT%I*.
Compiled etc.
Dumme Frage, wo findet das "verknuepfen" statt?
Nicht im System Manager, oder? Dort tauchen dann die vars im aus dem FB nicht auf.


----------



## MarkusP (6 März 2009)

Doch, im Systemmanager. Hast Du dort Dein PLC-Projekt angehängt?

LG


----------



## Ebias (6 März 2009)

... aber hatte nicht rescanned, nachdem ich die IOs gaendert habe.
Vielen Dank, es geht zwar nicht ueber die structure, aber dann eben ueber die FB.
Da gehoeren sie ja im Grunde auch hin, das mit der Structure war eh nur ein work-around.
Das hilft mir fuers erste weiter. Vielen dank.


----------



## MarkusP (6 März 2009)

Bitte beachte auch meinen vorherigen Eintrag. Du kannst ja trotzdem Ein- und Ausgangsstrukturen machen, und die dann in den FB's verwenden. Dann bist Du bei Erweiterungen total flexibel und hast für zig Eingangsvariablen aber eben nur einen einzigen Eingangsanschluss. (denn Du nicht verschalten musst, dies geschieht ja dann über den Systemmanager)

LG


----------

