SCL und If-Anweisung

steven001

Level-1
Beiträge
29
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
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.

Code:
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
 
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!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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.
 
Zuletzt bearbeitet:
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.

Code:
IF DB100.DBW2 = 16#31 THEN
...

Funxt auch nicht.
Was meinste mit "Also symbolische Adressierung ist da angesagt."
 
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.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
"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.
 
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:

Code:
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
 

Anhänge

  • OB1.pdf
    5,7 KB · Aufrufe: 25
  • FB100.pdf
    6,6 KB · Aufrufe: 33
  • DB200.pdf
    4,4 KB · Aufrufe: 18
  • Barcode.zip
    34,5 KB · Aufrufe: 18
Und noch zwei Bilder aus der Simulation mit PLCSIM.

Gruß Kai
 

Anhänge

  • VAT_1.jpg
    VAT_1.jpg
    267,7 KB · Aufrufe: 47
  • VAT_2.jpg
    VAT_2.jpg
    268,1 KB · Aufrufe: 43
Zuviel Werbung?
-> Hier kostenlos registrieren
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 :D - 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 :ROFLMAO: :ROFLMAO: :ROFLMAO:

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.
 
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?
 
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 ;-)
 
Das wäre dann hier so ein Fall...

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


dann so ? :
Code:
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?
 
Zuletzt bearbeitet:
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.
 
Zurück
Oben