# SCL und If-Anweisung



## steven001 (17 November 2008)

Hallo,

wir sind z.Z. (vergeblich) dabei eine Variable (bzw zu Testzwecken einen Ausgang) in Abhängigkeit eines Datenbankeintrages zu setzen.

Also wir scannen einen EAN13 Barcode mit einem Scanner ein und schreiben die ASCII-Zeichen in eine Datenbank.

Jetzt soll, wenn die ersten beiden Stellen 00, 10, 11, 20 oder 21 sind, Varablen (Mehrweg, Einweg, ...) auf TRUE gesetzt werden. Also wollten wir eine IF-Anweisung nutzen.


```
FUNCTION_BLOCK FB20

BEGIN

IF DB100.DBD2 = ´10´ then
Mehrweg := True
END_IF

END_FUNCTION_BLOCK
```
Es geht auch zu übersetzen - und im OB1 rufen wir ihn mit CALL FB20, DB20 auch auf...

Nur die Variable wird nicht true? Wo liegt denn da unserer Fehler?

mfg
Steven


----------



## HeizDuese (17 November 2008)

Vielleicht liegt es bereits daran, dass ein Datendoppelwort gelesen wird, und ein Vergleich auf einen 2-Byte String = 1 Wort statt findet.

Setz doch mal einen Haltepunkt (Achtung, dabei geht die CPU in Stopp). Bei Ausführung eines Einzelschrittes werden die Variableninhalte dargestellt.

Geht aber auch einfacher und ohne CPU-STOPP: Zielsystem->Variablen bedienen- und beobachten (oder so), DB100.DBD2  und mal DBD100.DBW2 eintragen, Typ jeweils "Zeichen" - damit kann man sich den Inhalt nach dem Scannen ansehen!


----------



## zotos (17 November 2008)

Und den Code "frisst" der Compiler? Ich bin gerade zu faul zum Testen aber das sieht so aus als wolltest Du ein Doppelwort mit einer Stringkonstante vergleichen.

Auch wenn das Doppelwort an sich reicht um diese Information aufzunehmen:
 1 Byte Gesamtlänge + 1 Byte aktuelle Länge + 1 Byte fürs erste Zeichen + 1 Byte fürs zweite Zeichen.

Vielleicht hilft es auch in der S7 Welt wenn man den Stringcompare FC verwendet (EQ_STRNG).

PS: ich würde auf direkte Adressierungen verzichten und das erst recht wenn es ums Strings geht. Also symbolische Adressierung ist da angesagt.


----------



## steven001 (17 November 2008)

Bin nicht zu 100% sicher ob wir an der Uni genau das geschrieben haben, aber ja es wir übersetzt.

Den Inhalt der DB habe wir schon angeschaut, da stehen tatsächlich die Werte (ASCII-Zeichen). Haben es auch schon mit dem Hexwert versucht.


```
IF DB100.DBW2 = 16#31 THEN
...
```

Funxt auch nicht.
Was meinste mit "Also symbolische Adressierung ist da angesagt."


----------



## zotos (17 November 2008)

der Code macht noch weniger sinn.

Da in dem Wort ja zwei Zeichen sind und wahrscheinlich zeigst Du gerade nicht auf die Zeichen sondern auf die Länge des Strings und zwar auf die aktuelle und die maximale.

Zu dem absoluten Adressieren: Ein String kann ja auch 254 Zeichen lang sein und wenn ein String länger als zwei Zeichen ist dann ist es eh rum mit der absoluten Adressierung da dann eine Doppelwort schon überschritten ist.

Also schreib statt DB100 den symbolischen Namen des DBs und statt DBD2 den symbolischen Namen der Variable die Du im DB angelegt hast.


----------



## Drutbluck (17 November 2008)

"Symbolische Adressierung" bedeutet einfach, normal mit Variablennamen zu arbeiten. Gegensatz "absolute Adressierung", das gab es früher, als es noch kein Assembler gab und kommt heute noch vereinzelt in Bootloadern vor 

Wenn dieser Aufwand sein soll, würde ich die Bytes einzeln (.DBB2 bis .DBB5) mit Hexwerten vergleichen. Notfalls auch in AWL, da zeigt sich dann schnell mit "Beobachten", was wirklich drin steht.


----------



## Kai (18 November 2008)

steven001 schrieb:


> Also wir scannen einen EAN13 Barcode mit einem Scanner ein und schreiben die ASCII-Zeichen in eine Datenbank.
> 
> Jetzt soll, wenn die ersten beiden Stellen 00, 10, 11, 20 oder 21 sind, Varablen (Mehrweg, Einweg, ...) auf TRUE gesetzt werden.


 
Hier ist einmal ein kurzes Programmbeispiel in S7-SCL:


```
FUNCTION_BLOCK FB100
 
NAME    : BARCODE
FAMILY  : SPSFORUM
AUTHOR  : KAI
VERSION : '1.0'
 
VAR_INPUT
    BARCODE : STRING[10];
END_VAR
 
VAR_OUTPUT
    MEHRWEG : BOOL;   
    EINWEG  : BOOL;
END_VAR
 
VAR_TEMP
    BARCODE_TEMP : STRING[2];
END_VAR
 
BEGIN
 
// Initialisierung von Zeichenketten
 
// Temporäre Variablen vom Datentyp STRING müssen vor 
// ihrer erstmaligen Verwendung mit einer Stringkonstanten 
// beschrieben werden. Hierdurch wird der korrekte 
// Stringaufbau sichergestellt.
 
BARCODE_TEMP := '  ';
 
// LEFT-Funktion
 
// Die LEFT-Funktion liefert die ersten L Zeichen einer 
// Zeichenkette.
 
BARCODE_TEMP := LEFT (IN := BARCODE, L := 2);
 
// Auswertung der ersten L Zeichen der Zeichenkette
 
IF BARCODE_TEMP = '10' THEN
    MEHRWEG := 1;
ELSE
    MEHRWEG := 0;
END_IF;
 
IF BARCODE_TEMP = '20' THEN
    EINWEG := 1;
ELSE
    EINWEG := 0;
END_IF;
 
END_FUNCTION_BLOCK
```
 
Gruß Kai


----------



## Kai (18 November 2008)

Und noch zwei Bilder aus der Simulation mit PLCSIM.

Gruß Kai


----------



## HeizDuese (18 November 2008)

Kai schrieb:


> Hier ist einmal ein kurzes Programmbeispiel in S7-SCL:
> 
> ....
> [/code]Gruß Kai




Ach, das sieht viel zu gut aus und lässt sich zu gut lesen   - Außerdem sind da zu wenige absolute Adressen drin - da könnte man den Baustein ja glatt ein 2. mal gebrauchen - das ist echt nix   

Spaß bei Seite: Aber so (symbolisch - bei Bausteine Eigenschaften auch auswählen- sollte man programmieren. Das macht einige Sachen deutlich einfacher, die Bausteine sind besser lesbar und können wiederverwendet werden.


----------



## steven001 (22 November 2008)

Konnte es jetzt erst testen und es hat mit der "Symbolische Adressierung" geklappt. Danke für eure Hilfe.

mfg


----------



## Peltzerserbe (22 November 2008)

ISt der Zugriff DB6.DBD denn eigentlich korrekt, müßte doch eigentlich DB6.DD heißen.


----------



## Ralle (22 November 2008)

Peltzerserbe schrieb:


> ISt der Zugriff DB6.DBD denn eigentlich korrekt, müßte doch eigentlich DB6.DD heißen.



1. Ja
2. Nein


----------



## Django2012 (8 Juni 2012)

Gehört nicht ganz hier hin.....

Die Funktion  =a8.0  wie in awl.... das gibt´s in scl nicht in der Form oder?     Bei  IF  xy  then  A8.0:= 1  wird ausgang 8.0 zwar gesetzt,  aber das bleibt er auch.    z.b.: u e0.0 u e1.0 = a8.0.....    . Schon klar, sowas macht man nicht in SCl , ist nur ne generelle Frage.   Muss ich das 8.0 wieder 0 wird das als Elsif machen oder geht´s irgendwie einfacher?


----------



## Thomas_v2.1 (8 Juni 2012)

Wie würdest du das denn in AWL umsetzen?


----------



## Django2012 (8 Juni 2012)

```
u e0.0
u e1.0
=A8.0
```
so zum Beispiel


----------



## Thomas_v2.1 (8 Juni 2012)

Das kannst du fast so in SCL schreiben, nur dass bei AWL die Zuweisung zum Schluss, bei SCL am Anfang steht (AWL ist in Postfix-Notation).
Zwei boolsche Variablen (bei dir E0.0 und E1.0) kannst du in SCL mittels "AND" Und-Verknüpfen. Das Verknüpfungsergebnis weist du dann mit := deinem Ausgang zu.

PS:
SCL-Hilfe aufrufen, AND in die Suchmaske eingeben und sich die Beispiele ansehen ;-)


----------



## Django2012 (8 Juni 2012)

Merci!  Habs erst mit IF ... probiert... Naja, war nicht so der Hit


----------



## Thomas_v2.1 (8 Juni 2012)

Django2012 schrieb:


> Merci!  Habs erst mit IF ... probiert... Naja, war nicht so der Hit


Es geht ja auch mit IF/THEN, kannst du ja mal als Übung damit umsetzen. Kleiner Tip: ELSE


----------



## Django2012 (8 Juni 2012)

Das wäre dann hier so ein Fall...


```
IF  WORD_TO_INT(mw3) > 5 THEN
    a8.2 :=1;
 END_IF;
```


dann so ? :

```
IF  WORD_TO_INT(mw3) > 5 THEN
    a8.2 :=1;
ELSE
    A8.2:=0;
 END_IF;
```

Bisschen umständlich? Oder einfach nicht richtig gemacht von mir?


----------



## Thomas_v2.1 (8 Juni 2012)

Klar ist das umständlicher als die direkte Zuweisung. Das Ergebnis in A8.2 ist aber das gleiche. Wobei der erzeugte AWL-Code von der IF/THEN/ELSE Lösung größer ist, weil er mit Sprüngen umgesetzt wird.
Ein weiterer Vorteil bei der direkten Zuweisung ist, dass du A8.2 nur einmal in der Querverweisliste hast.


----------



## Django2012 (8 Juni 2012)

Naja, wie gesagt, denke nicht das man sowas unbedingt in SCL machen soll. ... Aber zum Anfangen in der Programmiersprache geh ichs hald mal klein an 
Was aber ne super sache ist , ist die FOR..... Funktion.... Also da brauchst mit Loop in AWL nicht anfangen. Meine pers. Meinung. Auch das die AWL Pointer Sache in SCL quasi rausfällt... I like


----------



## Django2012 (8 Juni 2012)

noch ein kleiner Einwurf.... wir haben in der Firma oft awl netzwerke die nur aus und / oder bestehen, mit 1000 Klammern und über 2 Bildschirmseiten...  ohne Worte eigentlich, aber sowas find ich in SCL dann schon besser lesbar... 

bspl.: 

```
a8.0:= e10.1 & E10.2 OR e10.3 & e10.4 &NOT E10.6 OR e12.5 OR e13.5;
```
.... auch nicht schön, aber besser wie in AWL


----------



## Tigerente1974 (8 Juni 2012)

Sowas gehört in KOP!


----------



## Django2012 (8 Juni 2012)

Auf alle Fälle 

hier jetzt nun meine 100 Punkte Frage...... 


```
FOR index:= 1 TO 5 BY 1 DO
    IF Meins.meins[index] = 2 THEN
        m100.0:=1;
       END_IF;
END_FOR;
```

wie krieg ich m100.0  automatisch wieder auf 0 ?    Also meins.meins ist ein Array of Dint...   wenn ich irgendwo testweise 2 reinschreibe wird 100.0 gesetzt.... aber bleibt dann da für immer...  
Wenn ich    Else  oder Elseif  benutze  wird er nicht mehr gesetzt..... Das ist mir jetzt abschließend echt zu viel...


----------



## Thomas_v2.1 (8 Juni 2012)

Was soll denn in M100.0 gekennzeichnet werden? Dass in dem Array eine Variable den Wert 2 hat? 
Dann passt es doch so. Nur machst du die Suche nach der 2 doch hoffentlich nicht aus Spaß, sondern wirst an anderer Stelle die Information doch irgendwie weiterverarbeiten (IF M100.0 = true THEN ...) Und wenn du darauf reagiert hast setzt du das Bit (bei dir den Merker) wieder zurück.


----------



## Django2012 (9 Juni 2012)

So wie du jetzt geschrieben hast, habe ich das schon hinbekommen. 
Aber es muss doch auch ne möglichkeit die Suche "immer" laufen zu lassen, und sobald sich etwas ändert, also keine 2 mehr findbar ist, muss der M100.0 wieder 0 werden??  Z.b. Ne Typdatenverwaltung, es ist jetzt nicht mehr Typ 2 angewählt sonder Typ 3 .  Ja, blödes Beispiel, aber vom Prinzip her muss das doch irgendwie gehen???  Wahhh das SCL macht mich noch verrückt.
Mir gehts mehr um das "wie geht das... " als um "macht man das auch??".... zumindest jetzt noch.


----------



## Thomas_v2.1 (9 Juni 2012)

Dann setzt du einfach den Merker vor der Schleife zurück.


----------



## Django2012 (9 Juni 2012)

Ok, Versuch ich.  Also es gibt keine andere lösung, bzw. meine FOr  If  Anweisung ist korrekt?  Dachte ich hab in der Anweisung nen Fehler drin?


----------



## Thomas_v2.1 (9 Juni 2012)

Um zu beurteilen ob das richtig ist braucht man eine konkrete Aufgabenstellung.
Man kann nur sagen was dein Stück Programm macht: Wenn in einem der 5 Elemente im Array Meins.meins eine 2 enthalten ist, dann wird M100.0 auf true gesetzt. Wenn nicht, dann behält M100.0 seinen alten Wert.


----------



## Django2012 (9 Juni 2012)

Auf jeden Fall bist du  "Sir" SCL .  Du hast es voll drauf. Mein Held.  bisschen witz, aber ist ernstgemeint. Danke für die Hilfe!. Wie lange machst du schon SCL ?


----------



## Django2012 (9 Juni 2012)

Soory Thomas, dein Tip mit dem Merker zurücksetzten funktioniert nicht. Hier das etwas modifizierte Beispiel. 


```
Data_Ar.w:=0;
    ;
    IF m2.0 THEN
        FOR index:= 1 TO 25 BY 1 DO
            IF Data_Ar.MeinArray[index] = 5 THEN
               Data_Ar.w:=100;
            END_IF;
        END_FOR;
   END_IF;
```
 So bleibt  Data_Ar.w  immer 0  . Da setzt sich nichts .      Data_Ar.W  ist ein word..   HIIILLFEEE!!!

Und das geht auch nicht : 

```
IF m2.0 THEN
        FOR index:= 1 TO 25 BY 1 DO
            IF Data_Ar.MeinArray[index] = 5 THEN
               A8.0:=1;
            END_IF;
        END_FOR;
   END_IF;
```
  A8.0  wird nie 1 wenn ich in VAT beobachte.  Ich steig echt nicht mehr durch, was ist der Fehler?


----------



## Thomas_v2.1 (9 Juni 2012)

Hat denn eine Array-Variable überhaupt den Wert 5?


----------



## Django2012 (9 Juni 2012)

Ja. Den Setzt ich auf über die VAT.  Ich dreh jetzt hier gleich durch.


----------



## Django2012 (9 Juni 2012)

Jetzt gehts.  Sorry, ich hör jetzt auf und lass es gut sein fürs Wochenende. Wird einfach zu viel und die "Leichtsinnsfehler" werden immer mehr. 
Ob1 sollte den FC auch aufrufen. Trotzdem Danke "Sir" SCL!!!


----------

