# Zugriff auf einen UDT / Array mit Variablen?



## MSP (26 August 2005)

Hallo,

für unser Regallager speichern wir alle Daten in einem Array innerhalb eines UDT's ab.

Array[1..3,1..5] zB
Belegt bool
Frei bool

Dadurch können wir jedes Fach im Regal eindeutig definieren im Array.

Soweit so gut.

Nur wie prüfe ich jetzt am besten ab das ein Fach belegt ist?

Der Bediener soll ein Fach auswählen, zB Fach 1.2
Das bedeutet das das Array [1,2] abgefragt werden soll auf Belegt oder Frei.

Nur wie kann ich es jetzt in Step7 programmieren, das diese beiden Variablen X und Y an eine Vergleichsfunktion übergeben werden?

Am liebsten wäre mir natürlich wie aus C etc bekannt, das ganze so aufzurufen:

U "Fach".Fach[x,y].Belegt
= #Frei

Das ich also die beiden Variablen X und Y mit den Werten 'füttern' kann die der Benutzer durch seine Fachauswahl bestimmt hat.

Wenn das so nicht geht, wie dann? Muss man dann jedes Fach in einer Schleife einzeln prüfen? Und wie zählt man dann in der Schleife hoch bzw Runter?

In C / C++ geht das ganz einfach, nur in Step7 ist das irgendwie ein Buch mit 7 Siegeln   

Gruss,
Michael


----------



## volker (26 August 2005)

1. mir ist nicht verständlich warum du frei und belegt als 2 variablen benutzt. wenn das fach nicht frei ist, ist es belegt.

2. du kannst das array folgendermassen ansprechen
rechte maustaste, symbol einfügen, bei dem db das + anklicken und das array wählen.
in deinen code wird dann eingefügt  DB1.fach[..]  .. ersetzt du z.b. durch 1,2. s7 macht dann daraus die absolute adresse.

du kannst natürlich auch direkt u db1.fach[1,2] schreiben.


----------



## MSP (26 August 2005)

Hallo Volker,

das mit dem Ansprechen schaffe ich ja, aber nur wenn ich die Koordinaten direkt vorgebe.

Ich möchte aber anstatt fester Werte in der Abfrage Variablen haben, in welche ich dann meine Werte lade und die dann dort genommen werden.

Nur leider will das nicht klappen wenn ich zB sage:

"Fach".Fach[#Variable1,#Variable2].Belegt

Ich möchte halt eine einfache Abfrage haben ob das entsprechende Fach belegt oder frei ist, und dafür am besten nur einen Befehl nutzen, den obigen.
Im Moment müsste ich jedes Fach einzeln abfragen, was ich mir nicht vorstellen kann das dies so gemacht wird in der Praxis, denn ein Lager mit mehreren Tausend Fächern so abzufragen ist alles andere als schnell und logisch 

Michael


----------



## volker (26 August 2005)

da muss ich dich leider entäuschen.

der index ist ein fester wert und kann zur laufzeit nicht verändert werden (keine variable indizierung möglich).

die einzige möglichkeit ist, dass du mit einem eindimensionalen array arbeitest.

also 
fach oben = 1-3 
fach mitte = 4-6
usw.

dann könntest du die indirket ansprechen.


----------



## MSP (26 August 2005)

Hallo,

hmm schade eigendlich das das nicht möglich ist 
Wie wird denn in 'realen' Regallägern die Fachbestimmung getätigt?
Irgendwie muss das RBG ja wissen wohin es fahren muss.. und das in einer schnellen und speichersparenden Art?

Gruss,
Michael


----------



## sps-concept (26 August 2005)

*Regal*

Hallo,

mit indirekter Adressierung.

MfG
André Räppel


----------



## SPSKILLER (26 August 2005)

hi,

wenn ich das richtig verstanden habe, dann brauchst du nur 2 EA-Felder im Visu-System und n Bit.

1. EA-Feld: Regal Nr.
2. EA-Feld: Fach Nr.
Bit: Anfrage starten

D.h. der Bediener wählt Regal und Fach-Nummer vor und bestätigt die Anfrage. Das Bit wird gespeichert, und von deinem S7-FB nach dem Bearbeiten der Anfrage rückgesetzt.

Mit Hilfe der 2 Werte, die du bei gestarteter Anfrage auswertest ist es relativ einfach die Werte im ARRAY indirekt auszuwerten.

Schöne WE

Micha


----------



## volker (26 August 2005)

*Re: Regal*



			
				sps-concept schrieb:
			
		

> Hallo,
> 
> mit indirekter Adressierung.
> 
> ...



klar, aber ich kann das fach nicht direkt über zeile, spalte ansprechen, da es sich um ein mehrdimensionales array handelt.

ich denke ich würde das so machen.
ich sehe 100 spalten und 10 zeilen vor.
mein db würde dann von dw 1-100 die spalten der 1sten zeile enthalten. 101-200 die spalten der 2ten zeile, usw.
evtl auch mehr als ein int je fach. kommt eben drauf an wieviel daten ich ablegen will. 

dann kann ich ohne probleme die adresse des faches ermitteln.


----------



## 0815prog (26 August 2005)

*Vielleicht mit SCL ???*

Hallo,

kleiner Tip am Rande,

in SCL kann man Arrays variabel adressieren. Vielleicht kann die Abfrage ja in SCL geschrieben werden.

Gruss


----------



## volker (26 August 2005)

ich kenne mich mit scl nicht so gut aus.

schreib sowas mal in scl. (aber nur ein paar anweisungen) und poste den code mal hier.

ich würde mir das dann gerne mal in awl ansehen wie das übersetzt worden ist.


----------



## Anonymous (26 August 2005)

*SCL wäre wirklich besser !*

Hallo MSP,

Andre hat leider recht: mit indirekter Adressierung, 
weil beim Design von S7 die indizierte Adressierung
leider verschlafen wurde!

Nur: indirekte Adressierung heist: Arbeiten mit den
Adressregistern und Zeigern.

Wenn du dein Programm in 2 Wochen noch verstehen
möchtest, bist du mit SCL wirklich besser beraten, da 
kannst du genauso arbeiten wie in C/C++.

Kleines Beispiel (quick und dirty!) für den Einstieg
(noch unbedingt Symbolik ergänzen!):

//============================================
TYPE UDT99
  STRUCT
    Lager :  ARRAY [1..20,1..20] OF BOOL;
  END_STRUCT
END_TYPE

//============================================
DATA_BLOCK DB99  UDT99
BEGIN
END_DATA_BLOCK

//============================================
FUNCTION_BLOCK FB99

VAR_TEMP
  iRow : INT;   //Zeile
  iCol : INT;   //Spalte

END_VAR

VAR_IN_OUT
  Hochregal : UDT99; // Durchgangsparameter !
END_VAR

// ein paar Teile einlagern ...
FOR iCol := 5 TO 10 DO
    FOR iRow := 11 TO 15 DO
        Hochregal.Lager[iCol,iRow] := TRUE;
    END_FOR;
END_FOR;

END_FUNCTION_BLOCK

//============================================

Ach ja: man kann natürlich auch Arrays Of UDTs erstellen,
so kannst du z.B. nicht nur leer / belegt (dafür braucht man
übrigens wirklich nur EIN Bit) festhalten, sondern auch eine 
Teilenummer oder den Zeitpunkt der Einlagerung.

Gruß G.


----------



## Anonymous (26 August 2005)

*Nachtrag zu SCL !*

Hallo zusammen,

grade sind mir noch Zweifel gekommen, ob ich
nicht Zeile und Spalte vertauscht habe:

Evtl. auch mal so herum testen:

Hochregal.Lager[iRow,iCol] := TRUE;

Gruß G.


----------



## MSP (27 August 2005)

Hallo G.,

das mit SCl klingt soweit gut und für uns recht naheliegend, nur SCL ist doch nach dem kompilieren ein wenig zu groß und langsam gegenüber den anderen Varianten, oder?

Gruss und schönes Wochenende allen,
Michael


----------



## volker (27 August 2005)

grösse kommt immer auf den code an.
im endefekt liegt sowieso alles als awl (MC5) vor. beim übersetzen wird aber viel mit den ar's gearbeitet.

und über die geschwindigkeit braucht man sich nicht allzuviel gedanken machen. die s7 ist schon schnell.

ich werde ogigen code am montag mal testen.


----------



## Anonymous (29 August 2005)

*SCL und Geschwindigkeit*



			
				MSP schrieb:
			
		

> Hallo G.,
> 
> das mit SCl klingt soweit gut und für uns recht naheliegend, nur SCL ist doch nach dem kompilieren ein wenig zu groß und langsam gegenüber den anderen Varianten, oder?
> 
> ...



Hallo Michael,

da es in S7 (AWL) keine indizierte Adressierung gibt,
müsstest du auch in AWL relativ komplizeirten Code
schreiben!

Du kannst auch auf dem PC Assembler-Programme
schreiben, wenn du das letzte aus deinem Code 
herausholen willst, aber das geht natürlich auch auf 
Kosten der Wartungsfreundlichkeit.

Wie bei jedem Compiler gibt es übrigens auch 
in SCL Compilerschalter, mit dem man auf den
erzeugten Code Einfluss nehmen kann. Z.B. ist
es bei Arrayoperationen hilfreich, die Eingangs-
parameter EINMAL auf Bereichsgrenzen zu prüfen
und die Bereichsüberprüfung des Compilers auszu-
schalten, denn das erzeugt Unmengen von Code.

Gleiches gilt für das ENO-Flag. Wenn dein Programm
getestet ist, kannst du auch die Debug-Infos ab-
schalten, dann kannst du den SCL-Code nicht mehr
Online testen, aber er wird DEUTLICH schneller.

Gruß G.


----------



## volker (29 August 2005)

so hab hier mal ein wenig getestet. klappt nicht wirklich richtig.

für folgendes gilt: 

hochregal: 10 zeilen, 10 spalten.

belegt werden soll fach: zeile 2, spalte 4


```
//============================================ 
TYPE UDT80 
STRUCT 
Lager : ARRAY [1..10,1..10] OF BOOL; 
END_STRUCT 
END_TYPE 

//============================================ 
FUNCTION_BLOCK FB80

VAR_INPUT
zeile : INT;  
spalte : INT; 
END_VAR 

VAR_IN_OUT
Hochregal : UDT80; // Durchgangsparameter ! 
END_VAR 

// ein paar Teile einlagern ... 
Hochregal.Lager[zeile,spalte] := TRUE; 

END_FUNCTION_BLOCK 
//============================================
```


daraus erzeugt s7 diesen code

```
SET   
      SAVE  
      =     L      0.1
      L     #zeile
      ITD   
      L     L#1
      -D    
      L     L#16                        //16 da für jede zeile 16 bit bereitgestellt werden
      *D    
      L     #spalte
      ITD   
      TAK   
      T     LD     2
      TAK   
      L     L#1
      -D    
      L     LD     2
      +D    
      L     DIW [AR2,P#4.0]
      T     LW     2
      TAK   
      AUF   DB [LW     2]
      L     DID [AR2,P#6.0]
      +D    
      LAR1  
      =      [AR1,P#0.0]
      SAVE  
      BE
```

ein bisschen entzerrt sieht das so aus

```
L     #zeile
      ITD   
      L     L#1                         // -1 da zeile 1 bei byte 0 beginnt
      -D    
      L     L#16                        // 16 da für jede zeile 16 bit bereitgestellt werden
      *D    
      T     LD     2

      L     #spalte
      ITD   
      L     L#1                         // -1 da spalte bei bit 0 beginnt
      -D    
      L     LD     2
      +D    
      L     DIW [AR2,P#4.0]
      T     LW     2
      TAK   
      AUF   DB [LW     2]
      L     DID [AR2,P#6.0]
      +D    
      LAR1  
      =      [AR1,P#0.0]                //erzeugt stop
      SAVE  
      BE
```

wenn ich den baustein beobachten will, bekomme ich folgenden fehler.

*(D05F) Kodierungsfehler: Fehler im Datenteil (z.B. Reservebyte ungleich NULL, ...).*

nun füge ich diese zeile ein, übertrage den fb und lösche diese zeilen wieder.
      L     2
      T     #zeile
      L     4
      T     #spalte
jetzt kann ich beobachten und die im ob1 übergebenen parameter werden im fb übernommen.


cpu geht ohne ob121 in stop bis ich dieses ändere.
      =      [AR1,P#0.0]   ==>  =  DIX [AR1,P#0.0]


an dieser stelle ist das AR1 = 2.3 (was auch korrekt wäre)


beobachte ich nun db83
0 in	zeile		INT	0	2		
2 in	spalte		INT	0	4		
4 in_out hochregal	struct		P#P 0.0 (sollte hier jetzt nicht eigentlich 2.3 stehen? )

die einzelnen bits lassen sich so nicht betrachten.

erzeuge ich mit dem udt80 einen gobal-db, so belegt jede zeile 2byte, von denen bit 0-9 gebraucht werden.
letztes dbx ist also 19.1

schaue ich mir nun db83 in einer vat an so ist dort dbx 1.1 = true (zeile 1,spalte 10) und dbx 3.2 = true (zeile 2,spalte 11) 
alle anderen bits sind false.
??????????????

ausserdem ist das letzte bit welches sich beobachten lässt dbx9.7


also mir ist das alles ein bisschen rätselhaft.


----------



## volker (29 August 2005)

ok der korrekte dix wurde nicht gesetzt weil ein set fehlt

SET
=     DIX [AR1,P#0.0] 

dann wird schon mal das richtige bit gesetzt.
aber warum kommen auch noch andere bits ?


----------



## SPSKILLER (29 August 2005)

Hi,

ich hab das mal in AWL programmiert. Ist nicht viel.

Hier der Quellcode für ein kleines S7-Programm:

```
DATA_BLOCK "DB_Regaldaten"
TITLE =
AUTHOR : MICHA
VERSION : 1.0


  STRUCT 	
   Belegung : ARRAY  [1 .. 3, 1 .. 5 ] OF //Belegung der Regalfächer
   STRUCT 	
    FREI : BOOL ;	//Fach ist Frei
    BELEGT : BOOL ;	//Fach ist Belegt
   END_STRUCT ;	
  END_STRUCT ;	
BEGIN
   Belegung[1, 1].FREI := FALSE; 
   Belegung[1, 1].BELEGT := FALSE; 
   Belegung[1, 2].FREI := FALSE; 
   Belegung[1, 2].BELEGT := FALSE; 
   Belegung[1, 3].FREI := FALSE; 
   Belegung[1, 3].BELEGT := FALSE; 
   Belegung[1, 4].FREI := FALSE; 
   Belegung[1, 4].BELEGT := FALSE; 
   Belegung[1, 5].FREI := FALSE; 
   Belegung[1, 5].BELEGT := FALSE; 
   Belegung[2, 1].FREI := FALSE; 
   Belegung[2, 1].BELEGT := FALSE; 
   Belegung[2, 2].FREI := FALSE; 
   Belegung[2, 2].BELEGT := FALSE; 
   Belegung[2, 3].FREI := FALSE; 
   Belegung[2, 3].BELEGT := FALSE; 
   Belegung[2, 4].FREI := FALSE; 
   Belegung[2, 4].BELEGT := FALSE; 
   Belegung[2, 5].FREI := FALSE; 
   Belegung[2, 5].BELEGT := FALSE; 
   Belegung[3, 1].FREI := FALSE; 
   Belegung[3, 1].BELEGT := FALSE; 
   Belegung[3, 2].FREI := FALSE; 
   Belegung[3, 2].BELEGT := FALSE; 
   Belegung[3, 3].FREI := FALSE; 
   Belegung[3, 3].BELEGT := FALSE; 
   Belegung[3, 4].FREI := FALSE; 
   Belegung[3, 4].BELEGT := FALSE; 
   Belegung[3, 5].FREI := FALSE; 
   Belegung[3, 5].BELEGT := FALSE; 
END_DATA_BLOCK

FUNCTION_BLOCK "Regalprüfung"
TITLE =Status der Fächer in den Regalen
AUTHOR : MICHA
VERSION : 1.0


VAR_INPUT
  DB_NR : BLOCK_DB ;	//DB-Nr. Regaldaten
  OFFSET : INT ;	//Offset [BYTE] des Arrays im Regaldaten-DB
END_VAR
VAR_OUTPUT
  QFREI : BOOL ;	//Ausgewähltes Fach ist Frei
  QBELEGT : BOOL ;	//Ausgewähltes Fach ist Belegt
END_VAR
VAR
  siREGAL_NR : INT ;	//Gewünschte Regal-Nr.
  siFACH_NR : INT ;	//Gewünschte Fach-Nr.
  sbANFRAGE : BOOL ; //=1: Auswertung starten	
END_VAR
VAR_TEMP
  tiSPEICHER : INT ;	//Zwischenspeicher
END_VAR
BEGIN
NETWORK
TITLE =Anfrage?

      UN    #sbANFRAGE; 
//     R     #QFREI
//   R     #QBELEGT
      BEB   ; 
      R     #sbANFRAGE; 
NETWORK
TITLE =Pointer setzen

      L     #siREGAL_NR; 
      L     10; 
      *I    ; 
      L     10; 
      -I    ; 
      T     #tiSPEICHER; 

      L     #siFACH_NR; 
      L     2; 
      *I    ; 
      L     2; 
      -I    ; 
      L     #OFFSET; 
      +I    ; 
      L     #tiSPEICHER; 
      +I    ; 
      SLW   3; 
      TAR2  ; 
      +D    ; 
      LAR1  ; 

      AUF   #DB_NR; 
      U     DBX [AR1,P#0.0]; 
      =     #QFREI; 
      U     DBX [AR1,P#0.1]; 
      =     #QBELEGT; 
END_FUNCTION_BLOCK

DATA_BLOCK "INDB_Regalprüfung"
TITLE =
AUTHOR : MICHA
VERSION : 1.0

"Regalprüfung"
BEGIN
   DB_NR := DB 1; 
   OFFSET := 0; 
   QFREI := FALSE; 
   QBELEGT := FALSE; 
   siREGAL_NR := 0; 
   siFACH_NR := 0; 
   sbANFRAGE := FALSE; 
END_DATA_BLOCK

ORGANIZATION_BLOCK OB 1
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 "Regalprüfung" , "INDB_Regalprüfung" (
           DB_NR                    := "DB_Regaldaten",
           OFFSET                   := 0,
           QFREI                    := M    100.0,
           QBELEGT                  := M    100.1);

END_ORGANIZATION_BLOCK
```

Bedienung wie in meinem anderen Posting. Alles in den Instanz DB schreiben.
Momentan wird der FB bei jeder Anfrage einmal abgearbeitet.
Soll die Auswertung zyklisch erfolgen, dann einfach NW1 im FB1 löschen...

Es fehlt noch eine Plausibilitätskontrolle der Auswahl.

Schöne Grüße

Micha


----------



## volker (30 August 2005)

*FC: 2-dimensionales Array über Zeile / Spalte ansprechen*

Hallo

Ich habe mal eine FC geschrieben.

*

2D-Array V1.0 --- August 2005 von: www.Lischis-Home.de
Mit diesem Baustein ist es möglich ein 2-dimensionales Array über Zeile / Spalte anzusprechen.
Die Zelle kann gelesen und beschrieben werden.
Der Typ der Zelle darf folgendes Format haben: Bool, Byte, Word(INT), DWord(DINT,Real)
Das Array MUSS am Anfang des benutzten DB's liegen (also ab DBX0.0)
*
Findet ihr auf meiner Homepage unter S7 / 2d-array.zip


----------



## Ralle (1 September 2005)

Noch kurz ein Wort zu SCL:

Der Code den SCL erzeugt ist ziemlich kompakt (habs mir mal angesehen).
Per Hand kann man das manchmal etwas optimaler machen, aber mehr als 10% sind wohl nicht drin (Spezialfälle mit 1 Mill. Schleifendurchläufen mal weggelassen  :lol: ).
Ich würde für solche Dinge in jedem Fall SCL verwenden, da man so die Übersicht behält und sich nicht zu tief in "indirekter Adressierung" verstrickt, die Fehler nicht so leicht verzeiht. In einem Baustein (wie von Volker gezeigt) untergebracht geht es aber auch ganz gut, aber bei einem Regallager fällt sicher noch mehr solcher "Verwaltungskram" an der mehr "Datenbank-Funktionalität" als reine SPS-Steuerung verlangt.


----------



## Wolflesch (25 April 2008)

*mehrdimansionales array*

Hallo ich wollte fragen ob man ein 3-dimensionales array ein ein 2-dimensionales umwandeln kann, oder ein 2- in ein 1-dimensionales.


----------



## Machtnix (28 April 2008)

*Warum zweidimensionale Arrays ?*

Warum muß es denn unbedingt ein 2-dimensionales Array sein, wenn Step 7 damit so schlecht umgehen kann? Ich würde vielleicht für jede Zeile einen DB nehmen und dann für die Spalte mit einfachen Arrays arbeiten. Oder ein einfaches durchgehendes Array aller Fächer nehmen und den Index berechnen aus x und y. (x*Zeilenanzahl + y)


----------



## kiestumpe (29 April 2008)

Hallo,

was möchtest du machen?

Alle Werte einer Matrix in eine Liste schreiben?
Einen Vektor aus einer Matrix ausmaskieren?
Oder willst du einen neuen Datenbaustein erzeugen?


Eine Standard-Konvertierungsfunktion, wie FELD3D_TO_FELD2D oder ähnliches gibts nicht, die müßtest du selber stricken, wenn der Aufwand lohnt.

hth


----------



## Wolflesch (29 April 2008)

*2-Dimensionales Array*

Ja das Umwandeln von eimem 2- in ein 1-dimensionales Array hab ich jetzt mit
2 in einander geschachtelten For Schleifen gemacht,und das Maskieren mit einem AND, wie kann man nun das Array in einen anderen DB-kopieren ,kann man dann die Liste irgendwo sichtbar machen.


----------



## kiestumpe (30 April 2008)

Die Werte kannst du ohne Probleme vom Array in eine Liste kopieren, wenn die Größer der Liste >= Zeilen * Spalten deines Arrays ist und die Typen übereinstimmen.


----------



## Wolflesch (1 Mai 2008)

*Matrix*

Hallo, was ist  an diesem Schiebefehl zur Vekorisierung einer Matrix falsch:
Matrix[index1,index2]:=DWORD_TOD_INT(SHR(IN:index1, N:=16) AND
SHR(IN:index2,N:=24));
nach der Bearbeitung haben die Matrix Fächer den Wert 0 .


----------



## Larry Laffer (1 Mai 2008)

... du möchtest warscheinlich nicht ...
	
	



```
Matrix[index1,index2] := DWORD_TO_DINT (SHR(IN:index1, N:=16) [B][COLOR=red]AND [/COLOR][/B]SHR(IN:index2,N:=24)) ;
```
schreiben ... sondern :
	
	



```
Matrix[index1,index2] := DWORD_TO_DINT (SHR(IN:index1, N:=16) [B][COLOR=red]OR[/COLOR][/B] SHR(IN:index2,N:=24)) ;
```
 
Ansonsten wäre es interessant zu wissen was du damit bewirken willst ...


----------



## Wolflesch (1 Mai 2008)

Ja gut danke,  das war wohl ein  Anfängerfehler ich prorammiere mit SCL erst
eine Woche.


----------



## vierlagig (1 Mai 2008)

jetz lass den larry mal nicht im dunkeln tappen (mich würde es auch interessieren): WAS MACHST DU DA


----------



## Wolflesch (2 Mai 2008)

mit der Matrix will ich die Zufälligkeit eines Zufallgenerators bestimmen,also die
Zahlenfolge, ich mache auf der Technikerschule(2.Semester) ein Referat über SPS 
und da will ich ein SPS Programm Lampenspiel vorstellen, mit 7 Lampen, wo man sich die 
Folge merken und mit Tasten eingeben muß, und da hab ich mir gedacht das das mit der Matrix eine gute Idee wäre ein SCL Programm vorzustellen.
Wir haben erst im 2.Jahr SPS Programmieren.


----------



## Wolflesch (2 Mai 2008)

kann mir jemand helfen, immer wenn ich diesen Code mit dem Schalter aray dazu schalte bleibt das Programm im Simulator(PLCSIM) stehen:

WHILE aray = false DO
IF Matrizze[index1,index2] < 10000000 THEN
    shrhilf1:=INT_TO_DWORD(index1);
    shrhilf2:=INT_TO_DWORD(index2) ;
    Matrizze[index1,index2]:=DWORD_TO_DINT(SHR(in:=shrhilf1, N:=16) 
    OR SHR(in:=shrhilf2, N:=24));
END_IF;
END_WHILE;
 Matrizze[index1,index2]:=Matrizze[index1,index2] +1;


----------



## Larry Laffer (2 Mai 2008)

Frage:
Woher kommt index1 und index2 ...

Bist du sicher, dass du deine Matrix nicht über-Indexierst (index > Deklaration) ?


----------



## Ralle (2 Mai 2008)

Schaltest du aray auch mal wieder aus? Das Programm geht doch in die Schleife und bleibt darin hängen? Nimm mal statt der While-Schleife eine IF ... then... end if, dann sollte es auch gehen.

Ich denke mal der Simulator bleibt nicht nur stehen sondern geht wegen Zykluszeitüberschreitung in Stop.


----------



## Wolflesch (3 Mai 2008)

als der Computer ausgeschaltet war ist mir das selber eingefallen,
trotzdem danke, jetzt läuft das Programm, gibt es  irgend eine Liste wo man 
das ARRAY anschauen kann.
index1 und index2 werden mit der Zufallszahl (1 bis 7) abwechselnd indiziert.


----------



## Ralle (3 Mai 2008)

Als was ist Matrize denn definiert, wenn es eine Stat in einem FB ist kannst du die zugehörigen Var aus dem IDB in der Variablentabelle beobachten.


----------



## Wolflesch (4 Mai 2008)

Jetzt geht PLCSIM in Stop wenn ich diesen Code dazuschalte:
index3:=0;
    REPEAT  
    FOR index1 := 6 TO 0 BY -1 DO          
    FOR index2 := 6 TO 0 BY -1 DO  
              index3 := index3+1;   
              sortierpuffer[index3]:= Matrizze[index1,index2]; 
          END_FOR;
        END_FOR;
    UNTIL index3>=49
    END_REPEAT; 
im Diagnosepuffer steht:
Bereichslängenfehler beim Lesen,InstanzDB,Doppelwortzugriff,Zugriffsadresse 0,

die Arraybereiche müßten schon stimmen:
Matrizze: ARRAY[0..6,0..6] of DINT;
Sortierpuffer: ARRAY[1..49] of DINT;


----------



## Larry Laffer (4 Mai 2008)

Zu deinem Code fällt mir folgendes auf :
- den "Repeat ... Until" kannst du dir eigentlich sparen, da nach einem Durchlauf der beiden "FOR ..TO"-Schleifen index3 sowieso auf 49 ist ... und wenn nicht du sicherlich etwas über-adressierst ...
- Das Script ist sonst m.E. in Ordnung - hast du den zugehörigen I-DB auch ins PLCSim übertragen ? Manchmal vergisst man das schonmal ...
- Beinhaltet der Baustein noch weitere Funktionen ?

Gruß
LL


----------



## Ralle (4 Mai 2008)

Evtl. hast du im Programm Änderungen vorgenommen und keinen neuen IDB erzeugt, arbeitest lso mit dem alten IDB weiter. Dann ist mit allerdings die Zugriffsadresse 0 nicht ganz plausibel, könnt schon sein, daß Larry eher Recht hat  .


----------



## Wolflesch (4 Mai 2008)

Es liegt an diesem Programmteil:
IF sort=true then   
REPEAT 
    tauschen:= false;
         FOR index3:=49 TO 0 BY -1 DO
           puffer1:=DINT_TO_DWORD(sortierpuffer[index3]);
           puffer2:=DINT_TO_DWORD(sortierpuffer[index3-1]); 
           sortierpuffer[index3]:=    DWORD_TO_DINT(puffer1 AND 16#0000FFFF);
           sortierpuffer[index3-1]:=  DWORD_TO_DINT(puffer2 AND 16#0000FFFF);
            IF sortierpuffer[index3-1] > sortierpuffer[index3] THEN
                sortierpuffer[index3-1]:=DWORD_TO_DINT(puffer1);
                sortierpuffer[index3]:=  DWORD_TO_DINT(puffer2);
                tauschen:= true;
            ELSE sortierpuffer[index3]:=  DWORD_TO_DINT(puffer1);
                 sortierpuffer[index3-1]:=DWORD_TO_DINT(puffer2);   
            END_IF;
        END_FOR;
        UNTIL NOT tauschen
END_REPEAT;
END_IF;
puffer1,puffer2WORD;


----------



## Larry Laffer (4 Mai 2008)

die markierten Zeile erhalten einen negativen Wert im index3 :
	
	



```
[SIZE=1]IF sort=true then 
REPEAT 
tauschen:= false;
FOR index3:=49 TO 0 BY -1 DO
puffer1:=DINT_TO_DWORD(sortierpuffer[index3]);
puffer2:=DINT_TO_DWORD(sortierpuffer[COLOR=red][B][index3-1]); [/B][/COLOR]
sortierpuffer[index3]:= DWORD_TO_DINT(puffer1 AND 16#0000FFFF);
sortierpuffer[COLOR=red][B][index3-1]:=[/B][/COLOR] DWORD_TO_DINT(puffer2 AND 16#0000FFFF);
IF sortierpuffer[COLOR=red][B][index3-1][/B][/COLOR] > sortierpuffer[index3] THEN
sortierpuffer[COLOR=red][B][index3-1]:=[/B][/COLOR]DWORD_TO_DINT(puffer1);
sortierpuffer[index3]:= DWORD_TO_DINT(puffer2);
tauschen:= true;
ELSE sortierpuffer[index3]:= DWORD_TO_DINT(puffer1);
sortierpuffer[COLOR=red][B][index3-1]:=[/B][/COLOR]DWORD_TO_DINT(puffer2); 
END_IF;
END_FOR;
UNTIL NOT tauschen
END_REPEAT;
END_IF;[/SIZE]
```
Schleife läuft bis "0" - Arrayindex = index3-1  also -1 !!!

Gruß
LL


----------



## Wolflesch (5 Mai 2008)

Ja danke, jetzt läuft der Simulator, aber die beiden For-Schleifen werden jetzt 
nicht mehr bearbeitet
     REPEAT  
    FOR index1 := 6 TO 0 BY -1 DO          
    FOR index2 := 6 TO 0 BY -1 DO  
              index3 := index3+1;   
              sortierpuffer[index3]:= Matrizze[index1,index2];    
          END_FOR;
        END_FOR;
    UNTIL index3>=49
    END_REPEAT;
und die Matrizzenwerte bewegen sich nach kurzer Zeit so um die 50 bis 100 (Zufallszahl bei jedem Zyklus)
aber müssten die durch die Vektorisierung nicht deutlich höher sein.


----------



## Larry Laffer (6 Mai 2008)

Ich denke schon, dass die "FOR..TO"-Schleifen bearbeitet werden ...

Meinst du nicht, dass ich es mittlerweile verdient hätte, mal dein ganzes SCL-Script zu sehen ? Vielleicht hast du ja noch irgendwo eine nette kleien Gemeinheit versteckt ... 

Gruß
LL


----------



## Wolflesch (6 Mai 2008)

Hallo, die Forschleifen wurden nicht abgezählt, 
jetzt habe ich die erste Forschleife durch eine While-Schleife ersetzt
jetzt geht der Simulator wieder un Stopp (Bereichslängenfehler)

FUNCTION_BLOCK FB1
var_input
zahl : DINT;
Takt,Sortieren,sort : BOOL; 
END_VAR
VAR_TEMP
shrhilf1: DWORD;
shrhilf2: DWORD;
index3 : INT;
index4 : DINT;
index5 : DINT;
hilfs: DINT;
tauschen:BOOL;
puffer1,puffer2WORD;
END_VAR    
 VAR
 Matrizze : ARRAY[0..6,0..6] OF DINT;
 sortierpuffer : ARRAY[0..48]OF DINT;
 index1 : INT;
 index2 : INT;
 hilf: BOOL:=false  ;
 flanke:BOOL:=false;
END_VAR
BEGIN
IF Takt=true then
      IF hilf = false THEN
     hilf:= true;
    ELSE
    hilf:=false;
    END_IF;
     IF hilf = true THEN
      index1:=DINT_TO_INT(zahl);
    ELSE
       index2:=DINT_TO_INT(zahl);
           IF Matrizze[index1,index2] = 0 THEN
                   index4:=INT_TO_DINT(index1);
                   index5:=INT_TO_DINT(index2);
                   shrhilf1:=DINT_TO_DWORD(index4);
                   shrhilf2:=DINT_TO_DWORD(index5) ;
                   Matrizze[index1,index2]:=DWORD_TO_DINT(SHR(in:=shrhilf1, N:=16) 
                   OR SHR(in:=shrhilf2, N:=24));
                   END_IF;
           Matrizze[index1,index2]:=Matrizze[index1,index2] +1;
           index1:=index2;
           hilf:=true;
           END_IF;
END_IF; 
IF Sortieren=true then 
    index3:=49;
    index1:= 7;
WHILE index1 >= 0 DO
    index1:=index1-1;
              FOR index2 := 6 TO 1 BY -1 DO  
              index3 := index3-1;   
              sortierpuffer[index3]:= Matrizze[index1,index2]; 
          END_FOR;
END_WHILE;
END_IF;        
IF sort=true THEN   
REPEAT 
    tauschen:= false;
         FOR index3:=48 TO 1 BY -1 DO
           puffer1:=DINT_TO_DWORD(sortierpuffer[index3]);
           puffer2:=DINT_TO_DWORD(sortierpuffer[index3-1]); 
           sortierpuffer[index3]:=    DWORD_TO_DINT(puffer1 AND 16#0000FFFF);
           sortierpuffer[index3-1]:=  DWORD_TO_DINT(puffer2 AND 16#0000FFFF);
            IF sortierpuffer[index3-1] > sortierpuffer[index3] THEN
                sortierpuffer[index3-1]:=DWORD_TO_DINT(puffer1);
                sortierpuffer[index3]:=  DWORD_TO_DINT(puffer2);
                tauschen:= true;
            ELSE sortierpuffer[index3]:=  DWORD_TO_DINT(puffer1);
                 sortierpuffer[index3-1]:=DWORD_TO_DINT(puffer2);   
            END_IF;
        END_FOR;
        UNTIL NOT tauschen
END_REPEAT;
END_IF;

End_function_block


----------



## Larry Laffer (6 Mai 2008)

... ich mußte ein bißchen suchen ... aber wieder der gleiche Fehler :

```
WHILE index1 [B][COLOR=red]>= 0[/COLOR][/B] DO
[COLOR=red][B]index1:=index1-1[/B][/COLOR];
FOR index2 := 6 TO 1 BY -1 DO 
index3 := index3-1; 
sortierpuffer[index3]:= Matrizze[index1,index2]; 
END_FOR;
END_WHILE;
```
index1 kann kleiner als "0" werden ...
Das ist in deinem ARRAY nicht definiert ...

Ich würde hier aber auf jeden Fall bei Schleifen bleiben und die indexe nicht einfach nur inkrementieren oder dekrementieren, sondern ausrechnen :
	
	



```
Index3 := Index2 + Index1 * 7 ;
```
Ist aber nur ein Vorschlag ...

Gruß
LL


----------



## Ralle (6 Mai 2008)

Außerdem wären Einrückungen in deinem Code und Codetags hier im Forum nicht schlecht, das sieht dann so aus:


```
FUNCTION_BLOCK FB1

var_input
  zahl: DINT;
  Takt,Sortieren,sort: BOOL;
END_VAR

VAR_TEMP
  shrhilf1: DWORD;
  shrhilf2: DWORD;
  index3: INT;
  index4: DINT;
  index5: DINT;
  hilfs: DINT;
  tauschen: BOOL;
  puffer1,puffer2: WORD;
END_VAR

VAR
  Matrizze: ARRAY[0..6,0..6] OF DINT;
  sortierpuffer: ARRAY[0..48]OF DINT;
  index1: INT;
  index2: INT;
  hilf: BOOL:=false ;
  flanke: BOOL:=false;
END_VAR

BEGIN

IF Takt=true then
  IF hilf = false THEN
    hilf:= true;
  ELSE
    hilf:=false;
  END_IF;
  IF hilf = true THEN
    index1:=DINT_TO_INT(zahl);
  ELSE
    index2:=DINT_TO_INT(zahl);
    IF Matrizze[index1,index2] = 0 THEN
      index4:=INT_TO_DINT(index1);
      index5:=INT_TO_DINT(index2);
      shrhilf1:=DINT_TO_DWORD(index4); 
      shrhilf2:=DINT_TO_DWORD(index5) ;
      Matrizze[index1,index2]:=DWORD_TO_DINT(SHR(in:=shrhilf1, N:=16) OR SHR(in:=shrhilf2, N:=24));
    END_IF;
    Matrizze[index1,index2]:=Matrizze[index1,index2] + 1;
    index1:=index2;
    hilf:=true;
  END_IF;
END_IF;

IF Sortieren=true then
  index3:=49;
  index1:= 7;
  WHILE index1 >= 0 DO
    index1:=index1-1;
    FOR index2 := 6 TO 1 BY -1 DO
      index3 := index3-1;
      sortierpuffer[index3]:= Matrizze[index1,index2];
    END_FOR;
  END_WHILE;
END_IF;

IF sort=true THEN
  REPEAT
    tauschen:= false;
    FOR index3:=48 TO 1 BY -1 DO
      puffer1:=DINT_TO_DWORD(sortierpuffer[index3]);
      puffer2:=DINT_TO_DWORD(sortierpuffer[index3-1]);
      sortierpuffer[index3]:= DWORD_TO_DINT(puffer1 AND 16#0000FFFF);
      sortierpuffer[index3-1]:= DWORD_TO_DINT(puffer2 AND 16#0000FFFF);
      IF sortierpuffer[index3-1] > sortierpuffer[index3] THEN
        sortierpuffer[index3-1]:=DWORD_TO_DINT(puffer1);
        sortierpuffer[index3]:= DWORD_TO_DINT(puffer2);
        tauschen:= true;
      ELSE 
        sortierpuffer[index3]:= DWORD_TO_DINT(puffer1);
        sortierpuffer[index3-1]:=DWORD_TO_DINT(puffer2);
      END_IF;
    END_FOR;
  UNTIL NOT tauschen
  END_REPEAT;
END_IF;

End_function_block
```


----------



## Wolflesch (6 Mai 2008)

danke, ich wollte noch fragen wie man einen DB in der Variablentabelle beobachtet bei mir zeigt es immer nur ungültiger Operand an.
Kann man einen ARRAY Wert auch auf ein MW oder AW legen.


----------



## Larry Laffer (7 Mai 2008)

DB beobachten geht genauso wie bei den anderen Variablen ...
Du schreibst in das Variablen-Feld z.B. "DB100.DBW10" ... geht auch bei einem I-DB ...


----------



## Wolflesch (22 Mai 2008)

Hallo ich habe nochmal ein Problem, jetzt habe ich das Programm noch etwas umgeändert, Ausrechnen der prozentzualen  Abweichung vom  Mittelwert,  und  schreiben in einen  DB,  es  zeigt jetzt wieder Bereichslängenfehler an
kann das mit den Negativen Werten zusammenhängen.


IF zaehler=5000 THEN
mittelwert:=5000/49;
index3:=0;
  FOR index1 := 7 TO 2 BY -1 DO          
    FOR index2 := 7 TO 2 BY -1 DO  
        index3 := index3+1; 
        sortierpuffer1[index3]:=DINT_TO_DWORD(matrizze[index1,index2]);
        sortierpuffer[index3]:=DWORD_TO_DINT(sortierpuffer1[index3] AND 16#0000FFFF);
        sortierpuffer[index3]:=REAL_TO_DINT((DINT_TO_REAL(sortierpuffer[index3])-mittelwert/mittelwert)*100);
        sortierpuffer[index3]:=DWORD_TO_DINT(SHR(IN:=((DINT_TO_DWORD(sortierpuffer[index3]))AND 16#F0000000),N:=16)
                                OR  sortierpuffer1[index3] AND 16#FF000000);      
        WORD_TO_BLOCK_DB(5).DD[index3*4]:=DINT_TO_DWORD(sortierpuffer[index3]);      
    END_FOR;
  END_FOR;
zaehler:=0;        
END_IF;

END_FUNCTION_BLOCK​


----------



## Larry Laffer (22 Mai 2008)

...an welcher Stelle in deinem Konstrukt entsteht den der Bereichslängenfehler ...? Das wäre vielleicht interessant zu wissen ...

Ansonsten ... wie groß sind denn die ARRAY's dimensioniert ? Das sollte man bei so etwas IMMER mit angeben. Einen negativen Index sehe ich erstmal nicht ...

Gruß
LL


----------



## Wolflesch (22 Mai 2008)

danke für die schnelle Antwort, Bausteinadresse 148,instanz-DB Doppelwort- Zugriff , Zugriffsadresse 0.
Wie zählt man denn die Bausteinadresse, ist das Schieben des Vorzeichenbits
richtig


----------



## Larry Laffer (22 Mai 2008)

Hallo,
die Diagnose bringt dich auf Wunsch genau in die richtige Zeile (Baustein öffnen). In dem Fall würde ich aufgrund der Fehlermeldung aber auf die folgende Zeile tippen :
	
	



```
WORD_TO_BLOCK_DB(5).DD[index3*4]:=DINT_TO_DWORD(sortierpuffer[index3]);
```
Ist der DB5 den groß genug dimensioniert ? Gibt es darin mindestens 49 Doppelworte ? Das ist aber Spekulation (Meldung Instanz-DB ...).

Bitte teile doch noch die Deklaration deiner ARRAY's mit ...

Gruß
LL


----------



## Ralle (22 Mai 2008)

Ist deine Variable Matrizze immer noch so definiert?


```
Matrizze : ARRAY[0..6,0..6] OF DINT;
```

In der Hilfe steht: 



> Beim Start der Schleife wird die Laufvariable auf den Startwert (Anfangszuweisung) gesetzt und *nach* jedem Schleifendurchlauf um die angegebene Schrittweite erhöht (positive Schrittweite) oder erniedrigt (negative Schrittweite), solange bis der Endwert erreicht ist.



Das würde dann heißen, beim ersten Schleifendurchlauf könnte es schon krachen, da Index1 und Index2 da auf 7 stehen.


----------



## Ralle (22 Mai 2008)

Larry Laffer schrieb:


> Hallo,
> die Diagnose bringt dich auf Wunsch genau in die richtige Zeile (Baustein öffnen). In dem Fall würde ich aufgrund der Fehlermeldung aber auf die folgende Zeile tippen :
> 
> 
> ...



Und ist dein DB5 etwa dein Instanz-DB oder was ist das für einer? Die Fehlermeldung moniert ja den Zugriff auf den Instanz-DB.


----------



## Wolflesch (22 Mai 2008)

da war ein Zeitstempel Konflikt mit dem IB, die ARRAYS habe ich umgeändert die stimmen, die Prozentberechnung geht nicht, es kommt 0 raus
also im sortierpuffer1 stehen nur die Vektoren, wie dimensioniert man einen
DB (global) muß man da die 100 Werte von Hand eingeben,
vielen Dank


----------



## Ralle (22 Mai 2008)

Was genau, soll das bewirken?


```
sortierpuffer[index3]:=DWORD_TO_DINT(SHR(IN:=((DINT_TO_DWORD(sortierpuffer[index3]))AND 16#F0000000),N:=16)
```

Global-DB:

1. von Hand
2. Array[1..100] of DInt
3. Array[1..100] of UDT1, wobei UDT1 eine Struktur oder eine beliebige Anordnung von Daten enthalten kann.


----------



## Wolflesch (23 Mai 2008)

Das Verschieben des Vorzeichenbits, da ja nur die die ersten beiden Bytes
den Zahlenwert angeben und die oberen Bytes je ein Byte ein Vektor.


----------



## Ralle (23 Mai 2008)

Aber dieser Teil hier: 

```
((DINT_TO_DWORD(sortierpuffer[index3]))AND 16#F0000000)
```

sorgt doch dafür, daß nur noch 4 Bit da sind, die schiebst du dann 16 nach rechts. Ist das so gewollt?


----------



## Wolflesch (23 Mai 2008)

Ja weil ich verknüpfe ja diesen Teil noch zweimal mit ODER( mit den Vektorenwerten und dem Zahlenwert)
und das war der Fehler ich habe wieder AND mit OR verwechselt und den Zahlenwert ganz vergessen,
die oberen 4 Bit sind doch nur mit dem Vorzeichenbit besetzt.
na ja, jetzt hab ich solange rumgebastelt bis mir die Geduld abhanden gekommen ist, aber wer suchet der findet


----------



## Larry Laffer (24 Mai 2008)

ist dein Problem denn nun gelößt ...?


----------



## Wolflesch (24 Mai 2008)

Ja danke der Nachfrage, ich habe jetzt die negativen Zahlen mit der 2er-komplementärbildung und dem Setzen des Vorzeichen Bits hinbekommen,
nun wollte ich noch fragen ob man ein Array auch  Löschen kann, denn ich will alle 5000 Zyklen auswerten:

modul:=zaehler MOD 5000;
IF modul= 0 THEN
    hilf3:=DINT_TO_REAL(zaehler);    
    mittelwert:=hilf3/49;
    index3:=0;
         FOR index1 := 7 TO 2 BY -1 DO          
                  FOR index2 := 7 TO 2 BY -1 DO  
                      index3 := index3+1; 
                      hilf1:=DINT_TO_DWORD(matrizze[index1,index2]);
              hilf2:=(hilf1 AND 16#0000FFFF);
              hilf4:=DWORD_TO_DINT(hilf2);
                      hilf3:=DINT_TO_REAL(hilf4);
                      IF hilf3<mittelwert THEN
                       v_zeichen:=true;
                       hilf4:=REAL_TO_DINT(((mittelwert-hilf3)/mittelwert)*100);
                       hilf2:=DINT_TO_DWORD(hilf4+1);  // +1 zur Ergänzung des 2er komplements
                       hilf2:=(NOT hilf2) AND  16#0000FFFF;  //Komplementärbildung
                       sortierpuffer[index3]:=DWORD_TO_DINT(hilf2 OR (hilf1 AND 16#FFFF0000)
                       OR 2#1000000000000000);  //setzen des Vorzeichenbits
                       puffer1:=hilf4;                       
                   ELSE
                       v_zeichen:=false;
                       hilf4:=REAL_TO_DINT(((hilf3-mittelwert)/mittelwert)*100);
                       hilf2:=DINT_TO_DWORD(hilf4);
                       sortierpuffer[index3]:=DWORD_TO_DINT(hilf2 OR hilf1 AND 16#FFFF0000);
                       puffer2:=hilf4;
               END_IF;

               WORD_TO_BLOCK_DB(5).DD[index3*4]:=DINT_TO_DWORD(sortierpuffer[index3]);  
         END_FOR;
     END_FOR;
     zaehler:=0;        
END_IF;

END_FUNCTION_BLOCK


----------



## Larry Laffer (24 Mai 2008)

Wolflesch schrieb:


> ... nun wollte ich noch fragen ob man ein Array auch Löschen kann...


 
Löschen im Sinne von entfernen - Nein ...
Löschen im Sinne von "auf 0 setzen" - kein Problem :
	
	



```
FOR I := 1 to 50 BY 1 DO   // Beispiel-Schleife für Löschen eines Beispiel-ARRAY's
   Array_Variable[i] := 0 ;
END_FOR ;
```
 
Gruß
LL


----------



## Larry Laffer (24 Mai 2008)

Wolflesch schrieb:


> ich habe jetzt die negativen Zahlen mit der 2er-komplementärbildung und dem Setzen des Vorzeichen Bits hinbekommen


 
Würdest du mir das näher erklären ...?
Den Sinn dieser Maßnahme kann ich nicht so ganz nachvollziehen ...

Gruß
LL


----------



## Wolflesch (25 Mai 2008)

um aus einer positiven Zahl eine negative Zahl des gleichen Betrags zu machen(+255*(-1)= 1111111100000001 = -255),so wird doch in der Informationstechnik subtrahiert (in Wirklichkeit addiert), achso die negative Zahl wird automatisch erzeugt,ich habe da ein bischen rumprobiert weil ich dachte da würde der Fehler liegen.


----------



## Larry Laffer (25 Mai 2008)

... das mit den positiven und negativen Zahlen selbst ist mir schon klar. Mich hat interessiert, warum du das in deinem Programm ausmaskierst ...?


----------



## Wolflesch (13 Juni 2008)

Hallo ich bins schon wieder, ich habe jetzt ein Programm geschrieben, welches
die Periodenlänge des Kongruenz Zufallgenerators bestimmt(ab wieviel Zyklen
sich die Folge wiederholt) es werden die ersten 10 Zahlen gespeichert in
Merker 1, und jeweils die Anzahl der Zyklen in Period geschrieben, es hat schon einmal funktioniert (Zyklenanzahl 313) aber ich habe ein wenig verändert und jetzt funktioniert es nicht mehr,es zeigt immer schon bei 12
Zyklen Wiederholung an,

```
[INDENT][SIZE=2]FUNCTION_BLOCK fb10
[/SIZE] [SIZE=2]VAR_INPUT
[/SIZE] [SIZE=2]    zahl:DINT;
[/SIZE] [SIZE=2]END_VAR
[/SIZE] [SIZE=2]VAR_OUTPUT
[/SIZE] [SIZE=2]    zyklus:BOOL;
[/SIZE] [SIZE=2]END_VAR    
[/SIZE] [SIZE=2]VAR
[/SIZE] [SIZE=2]    merker1:ARRAY[1..10]OF INT;
[/SIZE] [SIZE=2]    merker2:ARRAY[1..10]OF INT;
[/SIZE] [SIZE=2]    period:ARRAY[1..10]OF INT;
[/SIZE] [SIZE=2]    zaehler1:INT:=1;
[/SIZE] [SIZE=2]    zaehler2:INT:=0;
[/SIZE] [SIZE=2]    break:BOOL:=false;  
[/SIZE] [SIZE=2]END_VAR
[/SIZE] [SIZE=2]VAR_TEMP
[/SIZE] [SIZE=2]    index:INT;
[/SIZE] [SIZE=2]    index1:INT;
[/SIZE] [SIZE=2]    index2:INT;
[/SIZE] [SIZE=2]END_VAR
[/SIZE] [SIZE=2]///////////////////////////////////////////////////////////////////////////////////////////////    
[/SIZE] [SIZE=2]BEGIN
[/SIZE] [SIZE=2]index:=DINT_TO_INT(zahl);
[/SIZE] [SIZE=2]IF break=true AND zaehler2<11 THEN
[/SIZE] [SIZE=2]   zaehler2:=zaehler2+1; 
[/SIZE] [SIZE=2]   period[zaehler2]:=zaehler1;
[/SIZE] [SIZE=2]   zaehler1:=1;
[/SIZE] [SIZE=2]   break:=false;
[/SIZE] [SIZE=2]END_IF;
[/SIZE] [SIZE=2]zaehler1:=zaehler1+1;
[/SIZE] [SIZE=2]IF zaehler1 <=11 THEN
[/SIZE] [SIZE=2]merker1[zaehler1-1]:=index;
[/SIZE] [SIZE=2]merker2[zaehler1-1]:=index;
[/SIZE] [SIZE=2]ELSE 
[/SIZE] [SIZE=2]   FOR index2:= 2 TO 10 BY +1 DO
[/SIZE] [SIZE=2]   merker2[index2-1]:=merker2[index2];  
[/SIZE] [SIZE=2]   END_FOR;
[/SIZE] [SIZE=2]merker2[10]:=index;
[/SIZE] [SIZE=2]END_IF;   
[/SIZE] [SIZE=2]  IF zaehler1> 11 THEN
[/SIZE] [SIZE=2]    FOR index1:=1 TO 10 BY +1 DO
[/SIZE] [SIZE=2]            IF merker1[index1] = merker2[index1] THEN
[/SIZE] [SIZE=2]               break:=true;
[/SIZE] [SIZE=2]               zyklus:=true;
[/SIZE] [SIZE=2]            ELSE break:=false;
[/SIZE] [SIZE=2]               zyklus:=false;
[/SIZE] [SIZE=2]               EXIT;
[/SIZE] [SIZE=2]            END_IF;
[/SIZE] [SIZE=2]     END_FOR;       
[/SIZE] [SIZE=2]  END_IF;
[/SIZE] [SIZE=2]END_FUNCTION_BLOCK[/SIZE]
[/INDENT]
```


----------



## vierlagig (13 Juni 2008)

1. die code-tags sind immer noch nicht bei dir angekommen - das nervt!
2. dann mach die änderungen rückgängig - dann funktioniert es wieder!
3. vergleiche die funktionierende version mit der, die nicht funktioniert ... das kannst nur du, weil uns die andere nicht vorliegt!


----------



## Larry Laffer (13 Juni 2008)

Wolflesch schrieb:


> zaehler1:=1;
> 
> merker1[zaehler1-1]:=index;


 
Das ist ein Auszug aus deinem Code ...
Beim ersten Durchlauf ist Zaehler1 = 1 - das bedeutet, dass du den merker1[0] indizierst. Die merker1 und auch merker2 sind aber von 1..10 deklariert ...

Mit dem Indizieren hast du es aber ...


----------



## Wolflesch (13 Juni 2008)

Danke für die schnelle Antwort, jetzt habe ich endlich kapiert wie das mit dem Code geht, leider habe ich vor dem Ändern nicht gespeichert, zaehler1 hat doch den Anfangswert 1 also wird nie niedriger als 2 , das habe ich so gemacht weil die erste zahl noch nicht belegt war,


----------



## Wolflesch (13 Juni 2008)

Jetzt funktioniert es, ich hatte immer den OB121 in die Simulation geladen,
ohne ihn funktioniert es,danke für die Antworten.


----------

