# Indirekte Adressierung bei Codesys/TwinCat



## Majestic_1987 (26 März 2009)

Hallo Leute.  Im Zuge meiner Facharbeiterprüfung hab ich in der S7 einen Baustein mit indirekter Adressierung geschrieben. Habe dadurch natürlich den Sinn und Zweck dieser Technik entdeckt.  Jetzt habe ich eine Frage zu der Thematik:  Ich möchte Messwerte in ein Array schreiben.  Bei der S7 geht das so: Über Multipanel kann man bis zu 4 Quell-DB's auswählen, in denen der Messwert steckt (z.b. der Hauptistwert eines FU) Dazu dann noch das Wort, in welchem der Messwert innerhalb des DB steckt.  In einer frei wählbaren Abtastzeit wird dann der erste Wert genommen und vom Quell-DB in den Ziel-DB geschrieben.   Dieser beinhaltet ein Array aus 4000 Integer-Werten. Die ersten 1000 sind für Messwert 1, die zweiten 1000 für Messwert 2 usw.  Das Programm adressiert über das Adressregister den ersten Integer-Wert des Array, schreibt den zur Messzeit aktuellen Messwert dort hinein und die Ziel-Adresse wird um 1 Wort erhöht. Zum nächsten Messzeitpunkt wird der zu diesem Zeitpunkt aktive Messwert in das 2. Wort des Array geschrieben.   Dies wiederholt sich, bis der Bereich für diesen Messwert (sprich die ersten 1000 Worte des Array) voll sind.   Wie kann ich soetwas mit Codesys umsetzen frage ich mich nun, denn ich arbeite mich privat gerade in Codesys ein.  Hoffe mir kann jemand helfen.  Grüße Sven


----------



## Ralle (26 März 2009)

Es gibt zwar auch Pointer etc. in Codesys, aber es geht viel einfacher. Du kannst Arrays erstellen (Wie auch in einem Step7-DB). Aber Codesys kann direkt über die Arrayindizes Daten in die Arrays schreiben. Der Indize darf also eine Variable sein. (Geht bei Step 7 nur mit SCL und wird dann intern von einem Compiler in Befehle mit ind. Adressierung umgesetzt). Das geht auch mit mehrdimensionalen Arrays, so daß du deine 3*1000 Meßwerte bei Bedarf in einem zweidimensionalen Array unterbringen kannst.


----------



## Majestic_1987 (26 März 2009)

Gut, anderer Fall, der Fall, durch den ich auf ind. adressierung kam:

Kunde will einen Betriebsstundenzähler für erstmal 10 Betriebsmittel, der die Betriebsstunden ausfallsicher speichert.

Lösung S7:
1 FC 
Lokale Parameter:
IN: 
DB Nummer: INT
DB Adresse: WORD

plus 1 Datenbaustein mit folgender Struktur
Seconds - INT
Minutes - INT
Hours - DINT
--------------
Das Muster wiederholt sich 100 mal.

Der FC bekommt nen 1Hz-Taktmerker.
Mit jeder steigenden Flanke wird der Sekunden-Wert inkrementiert:

AUF DB[#DB_Nummer]

L P##DB_Adresse
LAR1

U Taktmerker
FP Temp_Taktmerker
L DBW[AR1, P#0.0]
+ 1
T DBW[AR1, P#0.0]

Dann folgt der Vergleich des dort liegenden Wertes auf 60.
Ist der Wert gleich 60 wird das Adressregister um P#2.0 erhöht.

Dann dieser Wert (Minuten) um 1 inkrmentiert, Sekundenwert auf 0 gesetzt und Minutenwert auf 60 verglichen.

Adressregister wieder um 1 Wort erhöht und dann die Stunden inkrementiert, Minuten auf 0 gesetzt....usw.

Beim Aufruf des FC übergibt man die DB-Nummer sowie die Adresse, an welcher der Datenbereich des zu überwachenden Betriebsmittels beginnt, z.B. DBW20

Ist auch das in Codesys (einfacher) lösbar?

Zur Array-Struktur in Codesys (habe dort bisher nicht mit Arrays gearbeitet):

Gelten für das Array hier auch die selben Grenzen wie bei Step7? Also max 65535 Werte und maximal 6 Dimensionen?
Und wie lautet der Befehl (AWL, ST) mit dem ich auf ein Datenelement im Array zugreife? Speziell wenn dieses eine Variable ist?


----------



## repök (26 März 2009)

Aus der Codesys Hilfe:


```
Pointer 
 pt:POINTER TO INT;
 var_int1:INT := 5;
 var_int2:INT;
 pt := ADR(var_int1);
 var_int2:= pt^; (* var_int2 ist nun 5 *)
```
Trotzdem würde ich das mit Arrays machen.


----------



## Majestic_1987 (26 März 2009)

Wir lernen also, dass es in Codesys nur speicherindirekte Adressierung gibt.

Mensch, das is das blöde daran, bei Siemens zu lernen: Nur da gibts diese DB-Geschichte....und wenn man daran gewöhnt is fällts schwer, davon weg zu kommen xD


----------



## trinitaucher (26 März 2009)

Ich kenne mich mit Step7 leider nicht so gut aus und mit AWL komm ich auch nicht klar, daher werde ich dir mal kurz erläutern, wie man bei CoDeSys /TwinCAT mit Strukturiertem Text solche Dinge angeht:

DBs sind bei CoDeSys Strukturen.
Deklaration:

```
TYPE myStructType:
    STRUCT 
       bBool1 : BOOL;
       iInteger1: INT;
       sString1: STRING(20);
       arrInteger1: ARRAY [0..10] OF INT;
    END_STRUCT
END_TYPE
```
In deinem Programmteil, sei's ein Programm oder ein Funktionsbaustein, kannst du nun einzelne dieser Strukturen deklarieren oder auch ganze Arrays davon:

```
VAR
     stMyStruct: myStructType;
     arrstMyStruct: ARRAY [0..5] OF myStructType;
     iarrMesswerte: ARRAY [0..10] OF INT;
END_VAR
```
Im Array kann man dann je nach bedarf einzelne Elemente der Struktur behandeln oder z.B. mittels Schleifen ganze Abläufe automatisieren.

```
stMyStruct.bBool1  := TRUE;
stMyStruct.arrInteger1[2] := 32;                  (* Array in der Struktur beschrieben *)
arrstMyStruct[1].stMyStruct.arrInteger1[3] := 64;  (* Array-Element des Arrays beschrieben *)

....

(*Bearbeitung mittels Schleife*)
FOR i:=0 TO 10 DO
    stMyStruct.arrInteger1[i] := iarrMesswerte[i];
END_FOR

...

CASE y OF
1:  stMyStruct.arrInteger1[y] := iMesswert;
     stMyStruct.bBool1  := TRUE;
     stMyStruct.sString1 := 'Messwert im Index 1';
2:  stMyStruct.arrInteger1[y] := iMesswert;
     stMyStruct.bBool1  := FALSE;
     stMyStruct.sString1 := 'Messwert im Index 2';
END_CASE
```
(Du kannst die maximale Array-Größe auch mit einer VAR CONSTANT festlegen)

```
VAR
     arrstMyStruct: ARRAY [0..iMax ] OF myStructType;
END_VAR
VAR CONSTANT
     iMax : INT := 5;
END_VAR
```
So kannst du bei CoDeSys und TwinCAT alles komplett ohne direkte Adressierungen und ohne Pointer erledigen 
... noch Fragen?


----------



## Thomas_v2.1 (26 März 2009)

Majestic_1987 schrieb:


> Mensch, das is das blöde daran, bei Siemens zu lernen: Nur da gibts diese DB-Geschichte....und wenn man daran gewöhnt is fällts schwer, davon weg zu kommen xD


Wenn du bei S symbolisch programmierst interessieren dich (außer evtl. in FUP/AWL) die DBs auch nicht mehr.

Dein Anwendungsfall würde ich in ST lösen.


```
TYPE runtime_t :
STRUCT
    seconds : INT;
    minutes : INT;
    hours    : DINT;
END_STRUCT
END_TYPE
```
Zählfunktion mit so einer Schnittstelle:


```
FUNCTION runtime_counter : BOOL
VAR_INPUT
    running : BOOL; (* Antrieb in Betrieb *)
END_VAR
VAR_IN_OUT
    runtime : runtime_t;
END_VAR
```
Dann kannst du dir ein globales Array in beliebiger Dimension vom Typ runtime_t anlegen, und damit jeden Funktionsaufruf mit z.B. antriebe[1, 9] beschalten.

Die Zähleraufrufe dann im 1 Sekunden Task aufrufen.


----------



## Majestic_1987 (26 März 2009)

Erstmal dankeschön für die fixen Antworten.

Ist halt alles ne Sache der Gewöhnung  Sieht so zwar auf den ersten Blick kompliziert aus (weil ich auch bisher wenig in ST gemacht hab) aber scheint doch recht easy und vor allem durchschaubar zu sein.

Hab in nem anderen Beitrag (wo jemand was ähnliches machen will) den Befehl 


```
TVar[i] := 0
```
entdeckt. Was hats damit auf sich? Versuche mich grad nämlich an soner Schleife in ST.

Ist ST eig. für sämtliche Aufgaben der Steuerungstechnik geeignet oder ist in bestimmten Bereichen FUP oder CFC sinnvoller?

Und an Thomas zum Thema DB's interessieren nicht:

Projekte bei uns (ich denke da z.b. an Hochregallager oder auch an Stahlwerke) bestehen aus mindestens so vielen DB's wie FC's ;-) Also das ist in der Step7-Programmierung, auch wenn sie voll symbolisch erfolgt, standard.
Der unterschied zur IEC ist ja vor allem, dass man in Step7 komplett selber adressiert während man in der IEC komplett mit Variablen arbeitet und sich nicht um adressierung kümmern muss..oder verwendet hier jemand Merker in Codesys?? ;-)


----------



## MSB (26 März 2009)

Hier mal eine Quick and Dirty Lösung für dein Betriebsstundenprob,
jetzt bist du mit Siemens wieder dran ...

Einfach das Txt von der Datei hinten löschen, und in Codesys öffnen.

Mfg
Manuel


----------



## Majestic_1987 (26 März 2009)

Danke schonmal, aber ich versuchs erstmal selber 

In Step7 hab ichs übrigens schon lauffähig, wie gesagt möchte ich aber (stichwort Rundumblick) auch Codesys lernen, und da is dann ohne DB's der Anfang schwer xD


----------



## MSB (26 März 2009)

Zu deinem Siemens-Code Schnipsel,
eine Flankenauswertung in einem Mehrfach aurfrufbaren FC kannst du eh vergessen,
das aber nur ganz am Rande ...


----------



## trinitaucher (26 März 2009)

Majestic_1987 schrieb:


> Hab in nem anderen Beitrag (wo jemand was ähnliches machen will) den Befehl
> 
> 
> ```
> ...


"i" ist eine gewöhnliche Variable. Kannst auch nen anderen Namen nehmen. Hier steht i für den Index eines Array. So kannst du in Schleifen durch manipulation des Index sehr unkompliziert zB ein ganzes Array in einem Rutsch beschreiben.

```
VAR
  iArray: ARRAY [0..iMax] OF INT;
  i : INT;
END_VAR
VAR CONSTANT
  iMax: INT := 999;
END_VAR

----------------------
FOR i:= 0 TO iMax DO
  iArray[i] := (* irgendwas *);
END_FOR
```



Majestic_1987 schrieb:


> Ist ST eig. für sämtliche Aufgaben der Steuerungstechnik geeignet oder ist in bestimmten Bereichen FUP oder CFC sinnvoller?


Wir nutzen bei uns nur ST. Haben bisher auch noch nie irgend eine "Grenze" erkannt.
Vorteil, sofern man sich an das Hochsprachen-ähnliche Programmieren gewöhnt hat, ist für mich, dass du insbesondere solche Schleifen oder Verriegelungen sehr einfach realisieren kannst. Und dann ist der Schritt zur kompletten Datenverwaltung innerhalb der SPS nicht mehr schwer. Insbeondere TwinCAT bietet dir ja bei PC-Systemen zig Möglichkeiten um mit PC-Daten oder Datenbanken zu arbeiten.
Im Gegensatz zu "grafischen" Sprachen ist der Bildschirm nicht so voll. Probier mal größere mathematische Rechungen mit FUP , 
und im Vergleich zu AWL finde ich ist ST-Code leichter lesbar, wenn's ums Debuggen geht.


----------



## Majestic_1987 (26 März 2009)

Naja das ST für Mathe top ist war mir von vorn herein klar, hatte nur immer meine Zweifel in sachen Bit-Logic, wofür ja AWL und FUP prädestiniert sind.

Andere Sache:

Angenommen ich hab 4 Arrays.
Array1 
Array2
Array3
Array4

Ich möchte gerne das Array, auf das mein Baustein zugreifen soll, als Lokalparameter diesem Baustein übergeben...


Wie mach ich das? Welchen Typ muss die IN-Variable haben?

Ziel wäre z.b. dass ich in der Visualisierung für ne Kurve oder sowas mittels Drop-Down das Array auswählen kann, in das mein Baustein Daten schreibt.

@Trinitaucher:

Das i war mir klar, das TVar nicht. Mir is dann grad auch mal aufgefallen, dass es sich bei TVar um ein Array handelt, auf dessen i-tes Element zugegriffen wird.


----------



## zotos (26 März 2009)

Majestic_1987 schrieb:


> Wir lernen also, dass es in Codesys nur speicherindirekte Adressierung gibt.
> 
> Mensch, das is das blöde daran, bei Siemens zu lernen: Nur da gibts diese DB-Geschichte....und wenn man daran gewöhnt is fällts schwer, davon weg zu kommen xD



DBs sind IMHO Rotz. Die Pointerei auf der S7 ist 1. auch Rotz und 2. auch "speicherindirekt" (wie Du es getauft hast). Man bildet einen Pointer von einer Variable und manipuliert diesen dann mit Byteoffsets. Das kann man in CoDeSys zwar auch tun aber oft ist dies nicht notwendig da man auch von einem Pointer aus Symbolisch weiteradressieren kann. 
Dies bringt mich zu Deiner Frage mit den Arrays:


Majestic_1987 schrieb:


> ...
> Angenommen ich hab 4 Arrays.
> Array1
> Array2
> ...



Obligatorische Gegenfrage wie würdest Du das bei der S7 machen?

Ich gehe davon aus das Du nun keine Kopie des Arrays anlegen willst da kann man dann zu einem Pointer greifen.

Ich geh mal davon auf das Du die Arrays irgend wo global definiert hast:

```
VAR_GLOBAL
  Array1 : ARRAY[0..MAXCHART] OF INT;
  Array2 : ARRAY[0..MAXCHART] OF INT;
  Array3 : ARRAY[0..MAXCHART] OF INT;
  Array4 : ARRAY[0..MAXCHART] OF INT;
  (* MAXCHART ist eine globale Konstante damit man das nicht immer von Hand anpassen muss *)
END_VAR
```
Nun zum Eingang der Funktion:

```
VAR_INPUT
     Chart : POINTER TO ARRAY[0..MAXCHART] OF INT;
END_VAR
```
In der Funktion kann man dann auf das Array so Zugreifen:

```
Chart^[2] := 99; (* fester INDEX*)

FOR i := 0 TO MAXCHART DO
  Chart^[i] := 0; (* variabler INDEX*)
END_FOR
```
Nun ist bei dem Aufruf der Funktion noch zu beachten das man einen Pointer versorgen muss:

```
RetVal := MyFunction(Chart:=ADR(Chart1));
```
---

Diese Anwendung eigent sich auch für Strukturen (Benutzerdefinierte Datentypen). Da man halt im Baustein dann weiterhin Symbolisch zugreifen kann.

PS: Man könnte es auch ganz schnöde mit einem FB und einem IN_OUT lösen den gibt es aber im FC nun mal nicht. 
PPS: Es gibt immer für und wider


----------



## Majestic_1987 (26 März 2009)

zotos schrieb:


> [/code]Nun ist bei dem Aufruf der Funktion noch zu beachten das man einen Pointer versorgen muss:
> 
> ```
> RetVal := MyFunction(Chart:=ADR(Chart1));
> ...



1. Frage:

Wo trägst du denn jetzt den Namen des Array (Array1) ein?
RevVal ist doch der Rückgabewert der Funktion welche du weiter oben geschrieben hast. Aber irgendwo muss ich dem Pointer ja sagen "Adressiere Array1" So dass dessen interne Adresse dann im FC zur Verfügung steht.

2. Frage:

Wie hätte man das per IN_OUT gelöst?
IN_OUT vom Typ Array of Int oder wie?


----------



## zotos (26 März 2009)

Majestic_1987 schrieb:


> 1. Frage:
> 
> Wo trägst du denn jetzt den Namen des Array (Array1) ein?


Ähm ja Schreibfehler ich wollte die Variablen Array1 bis 4 eigentlich Chart1 bis 4 nennen und habe das in der globalen Deklaration dann doch verschnarcht.



Majestic_1987 schrieb:


> RevVal ist doch der Rückgabewert der Funktion...



Der RetVal hat nichts mit dem Thema zu tun das habe ich einfach reflexartig beim Funktionsaufruf verwendet.



Majestic_1987 schrieb:


> 2. Frage:
> 
> Wie hätte man das per IN_OUT gelöst?
> IN_OUT vom Typ Array of Int oder wie?



IN_OUT nur bei PRGs und FBs erlaubt und dann einfach:


```
VAR_IN_OUT
    Chart : ARRAY[0..MAXCHART] OF INT;
END_VAR
```


----------



## Majestic_1987 (26 März 2009)

Hallo Leute....

wo ist hier der Fehler?? Das schreiben der Werte in das Array soll stoppen, sobald Start = False ist...aber egal welchen Zustand Start hat, das Array wird weiter beschrieben 


```
VAR_INPUT
    Start: BOOL;
    Array_Nummer: INT :=0; (*Werte schreiben ab diesem Element*)
    Array_Elements: INT; (*Gesamtheit der Elemente im Array*)
END_VAR
VAR_OUTPUT
    Error: BOOL;
END_VAR
VAR
    timer1:TP;
    timer2:TP;
    ft1: R_TRIG;
    Zaehl: INT;

----------------------------------------------------------------------

Timer1 (IN:=Start AND NOT Timer2.Q,PT:=T#100ms);
Timer2 (IN:=Start AND NOT Timer1.Q,PT:=T#100ms);
ft1 (CLK:=Timer1.Q);

IF Array_Elements > 1000 THEN
    Error := TRUE;
         RETURN;
END_IF

IF Start AND ft1.Q THEN
        Messwerte[Zaehl] := Analogwert;
        Zaehl := Zaehl + 1;

            IF Zaehl > Array_Elements THEN
            Zaehl := 0;
            END_IF

END_IF
```


----------



## Thomas_v2.1 (26 März 2009)

zotos schrieb:


> IN_OUT nur bei PRGs und FBs erlaubt und dann einfach:



Bei TwinCat gehen IN_OUT auch bei FCs, oder worauf bezieht sich diese Beschränkung?


----------



## RobiHerb (26 März 2009)

*Defensiv*



Majestic_1987 schrieb:


> Hallo Leute....
> 
> wo ist hier der Fehler?? Das schreiben der Werte in das Array soll stoppen, sobald Start = False ist...aber egal welchen Zustand Start hat, das Array wird weiter beschrieben
> 
> ...



Ich sehe den Fehler nicht direkt und es ist auch unvollständig.

Ich würde es etwas defensiver angehen und die Eingangsparameter alle oder gar keinen vorbelegen.



Majestic_1987 schrieb:


> ```
> IF Start AND ft1.Q THEN
> Messwerte[Zaehl] := Analogwert;
> ```


 
Dann würde ich hier so ansetzen:

IF ((Start <> FALSE) AND (ft1.Q <> FALSE)) THEN

So bin ich zumindest sicher, dass keine Auswerte Prioritäten durcheiander geraten.

Wenn es immer noch nicht hilft:

BOOL bTest := (Start <> FALSE) AND (ft1.Q <> FALSE);

und im Debugger anschauen, was daraus wird. Ansonsten erst mal Wochenende ausschlafen.


----------



## Majestic_1987 (26 März 2009)

Oha, ich bin überzeugt. 
Habe jetzt ne richtig schicke Messwertspeicher-Funktion. In Kombination mit dem "CASE" Befehl wirklich praktisch  Also ich mag Codesys 

Hier mal mein geistiger Erguss, ich bitte um Kommentierung:

*Variablen:*

```
FUNCTION_BLOCK Test_Adress
VAR_INPUT
    Start: BOOL; (*Start-Bit für Messwertspeicherung*)         
    Array_Nummer: INT :=0; (Array-Element ab welchem Speicherung erfolgen soll*)
    Array_Elements: INT; (*Gesamtmenge der Elemente im Array, die beschrieben werden sollen*)
    Delete_Array: BOOL; (*Aktives Array löschen*)
    Array_Name: POINTER TO ARRAY [0..MaxChart] OF INT; (*Parameter Pointer auf nächstes Array*)
END_VAR

VAR_IN_OUT
END_VAR

VAR_OUTPUT
    Error: BOOL;
    Delete_Run: BOOL;
    Array_Full: BOOL;
END_VAR
VAR
    Active_Array: POINTER TO ARRAY [0..MaxChart] OF INT; (*aktives Array*)
    timer1:TP;
    timer2:TP;
    Zaehl: INT;
    ft1: R_TRIG;
    ft2: R_TRIG;
END_VAR
```
Programmcode:


```
Timer1 (IN:=Start AND NOT Timer2.Q,PT:=T#125ms);
Timer2 (IN:=NOT Timer1.Q,PT:=T#125ms);
ft1 (CLK:=Timer1.Q);

(* Neues Array nur akzeptieren, wenn altes voll oder leer*)
IF Array_Full OR Zaehl = 0 THEN
    Active_Array := Array_Name;
END_IF

(*Wenn Array-Elementzahl größer als Maximalwert -> Fehler*)
IF Array_Elements > 1000 THEN
    Error := TRUE;
    RETURN;
ELSE
    Error := FALSE;
END_IF

(*Wenn Start und Abtastzeit starte Werttransfer*)
IF Start AND ft1.Q THEN
        Active_Array^[Zaehl] := Analogwert;
        Zaehl := Zaehl + 1;
        Array_Full := FALSE;

            IF Zaehl > Array_Elements THEN
                Array_Full := TRUE;
                Zaehl := 0;
            END_IF

END_IF

(*Bei Flanke am Lösch-Bit aktives Array mit 0 beschreiben*)

ft2 (CLK:=Delete_Array);

IF ft2.Q THEN
    FOR Zaehl := 0 TO Array_Elements DO
    Active_Array^[Zaehl] := 0;
    Delete_Run := TRUE;
    END_FOR
    Zaehl := 0;
ELSE
    Delete_Run := FALSE;
END_IF
```


----------



## Majestic_1987 (26 März 2009)

RobiHerb schrieb:


> Ich sehe den Fehler nicht direkt und es ist auch unvollständig.



Der Fehler lag nur darin, dass ich aussen nur "True" und "False" dran hatte und mir das meine Force-Befehle verhagelt hat. Nachdem ich Variablen an den Baustein parametriert hatte, und diese geforced habe, funktionierte es problemlos.


----------



## zotos (27 März 2009)

Thomas_v2.1 schrieb:


> Bei TwinCat gehen IN_OUT auch bei FCs, oder worauf bezieht sich diese Beschränkung?



Ich habe es nun extra noch mal getestet. Du hast recht auch CoDeSys/TwinCAT unterstützen beim einem FC VAR_IN_OUT. Ich vermute mal das dies nicht schon immer so war wenn man bei einem FC nämlich einen Bereich VAR_OUTPUT hinzufügt kommt bei CoDeSys diese Meldung:



> Fehler 3820: TEST (4): 'VAR_OUTPUT' und 'VAR_IN_OUT' ist in Funktionen nicht erlaubt.



Diese Fehlermeldung muss ich mir wohl verinnerlicht haben ;o)


----------



## Majestic_1987 (31 März 2009)

Neues Problem:

Wenn ich folgendes ausführe bekomme ich einen "Page Fault" und das Programm steigt aus.

WAS kann das sein?

Funktion ist wie folgt:

Ich habe einen Baustein, welcher, in diesem Fall, eine Lampe steuert.
Darüber hinaus 2 eigentlich identische, welche in Abhängigkeit von externen Bedingungen die Bits in einem mit Scene_Nr bzw. Switch_Nr bezeichneten Element des Array In_Scenes bzw. In_Switches setzen oder Rücksetzen.

Der folgende Code stammt aus dem Baustein, welcher die Lampe steuert. Ziel ist, dass der Baustein seine Daten aus eben jenem Array bezieht, dessen "Steuerungsbaustein" gerade über das Steuerbit 0 eingeschaltet ist.

Ziel ist, für eine Lampe über die Visualisierung im laufenden Betrieb den ansteuernden Schalter sowie die Lichtszene, zu welcher die Lampe gehört, einstellen zu können. Die jeweils aktuelle Befehlsquelle, also z.b. In_Scene[5].Steuerbit[1] oder In_Switch[2].Steuerbit[1] soll dann die Steuerung übernehmen.

Es wäre prinipiell zwar möglich, den kompletten Code im Baustein 2 mal zu schreiben mit unterschiedlichen Parametern, das wäre aber suboptimal.

Der hier abgedruckte Code ist NUR ein Auszug, die ersten 21 Zeilen des Bausteins plus Variablendeklarationen.


```
VAR_INPUT
    Scene_Nr: INT := 0;
    In_Scenes: ARRAY[1..10] OF Scene_Data;

    Switch_Nr: INT := 0;
    In_Switches: ARRAY[1..10] OF Scene_Data;

END_VAR

VAR
    Active_Date: POINTER TO ARRAY[0..10] OF Scene_Data;
    Active_Nr: INT;
END_VAR
```


```
IF In_Scenes[Scene_Nr].Statusbits[0] = FALSE AND In_Switches[Switch_Nr].Statusbits[0] = TRUE THEN

    Active_Date := ADR(In_Switches);
    Active_Nr := Switch_Nr;

ELSIF In_Scenes[Scene_Nr].Statusbits[0] = TRUE AND In_Switches[Switch_Nr].Statusbits[0] = FALSE THEN

    Active_Date := ADR(In_Scenes);
    Active_Nr := Scene_Nr;

ELSE

    Active_Date := ADR(In_Switches);
    Active_Nr := Switch_Nr;

END_IF

IF Active_Date^[Active_Nr].Statusbits[0] = FALSE THEN                            (*Zustand Szene deaktiviert*)

    (*Status := 1;*)
    RETURN;

...
```


----------



## zotos (31 März 2009)

Deine Arrays beginnen mal bei 1 und ein andermal bei 0.

Im Code Greifst Du bei einem Array das bei 1 beginnt auf die Zelle 0 zu. Das nimmt Dir das Teil einfach übel.


----------



## Majestic_1987 (31 März 2009)

Das sind die Tippfehler, die einem nicht auffallen xD 
Ich versuchs mal xD


----------



## zotos (31 März 2009)

Da ich mal vermute das es nur ein Codefragment ist, kann meine Vermutung zutreffen.
Diese Variablendeklaration:

```
Scene_Nr: INT := 0;
    In_Scenes: ARRAY[1..10] OF Scene_Data;
```

Beißt sich mit dem Code:

```
IF In_Scenes[Scene_Nr].Statusbits[0] = FALSE THEN
```

Wenn Du Scenes_Nr nicht größer 0 und kleiner-gleich 10 hast geht der Aufruf schief.


----------



## Majestic_1987 (31 März 2009)

Nene, keine Sorge,

den Fall In_Scenes = 0 decke ich in einem anderen Baustein ab und der resultiert in einem Return aus der zugehörigen schleife nachdem ein Statuswort gesetzt wurde, dass den Zustand bemeckert.

Nach der Korrektur der Array-Definitionen läufts jetzt. 

ABER 

Wenn ich 1 mal zwischen Schalter und Szene gewechselt habe tut das Programm nix mehr...da muss ich wohl nochmal suchen...aber nicht mehr heute xD


----------

