Step 7 16 Chars von Kamera mit DB vergleichen

tommylik

Level-2
Beiträge
130
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Ein Roboter liest über eine Siemens Kamera vom BT den Prägecode ein.

Er wird so im DB gespeichert. Es ist ein Array[1..16] of Char

Anmerkung 2021-12-07 130354.JPG

Mein allererstes Problem ist, dass ich die Input-Variable nicht an parametriert bekomme.

Code:
FUNCTION X_FC2395_Code_suchen : VOID
TITLE = 'Suche'
//
// Baustein-Kommentar ...
//
VERSION : '1.0'
AUTHOR  : author
NAME    : name
FAMILY  : family

// Bausteinparameter
VAR_INPUT
        
    Kamera-Input: ARRAY[1..16] OF CHAR;             
    
END_VAR

Oder geht das nicht, weil das Array in einem UDT ist und das UDT noch mit anderen Arrays verschachtelt ist?

Ich möchte diesen Prägecode mit Codes, die in einem anderen Datenbaustein sind, vergleichen.
Die Struktur sieht so aus:

Anmerkung 2021-12-07 124643.JPG

Es gibt hier z.B. ein bisschen was wo ich drauf aufbauen könnte???

Mein Versuch:

Anmerkung 2021-12-07 125412.JPG

Die Fehlermeldungen unten verwirren. In Zeile 41 ist der Cursor und meckert, will Bool warum?

Kann mir einer von Euch bitte helfen?

Grüße Tommylik
 

Anhänge

  • Anmerkung 2021-12-07 122853.JPG
    Anmerkung 2021-12-07 122853.JPG
    76,2 KB · Aufrufe: 18
  • 1638877768675.png
    1638877768675.png
    32,8 KB · Aufrufe: 11
  • Anmerkung 2021-12-07 130048.JPG
    Anmerkung 2021-12-07 130048.JPG
    114,8 KB · Aufrufe: 16
Hallo Tommy,

probiere mal Char_To_int(X_DB2390...) <> Char_to_int(aArray) und das gleiche für die Zeile 44

Grüß
Jean
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Jean,

Vielen Dank für deine Hilfe.

Habe ich versucht, bekomme folgende neue Fehlermeldung: Ungültiger Datentyp

Screenshot 2021-12-07 163137.jpg

Was könnte es noch sein? Ich denke ich werde mal die Struktur des DB ändern zu Test zwecken.

Grüße Tommylik
 
Ich weiß nicht, was der TIA-Compiler bei einer 400-er so alles auswertet beim Übersetzen, aber Char sollte man schon mit Char vergleichen können.
Beginnen würde ich damit, das Array über die korrekten Grenzen zu iterieren, also von 1 bis 16, nicht von 0 bis 255, denn damit läufst du ohnehin sofort in den SPS-Tod.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Vielen Dank für Eure Antworten.

@ Jean
Hast natürlich Recht so kann das nichts werden.
Es bleiben aber noch 2 Fehler mit dem ungültigen Datentyp.

Screenshot 2021-12-07 182018.jpg


@ Ralle das verstehe ich nicht was du meinst.

Ich möchte doch 255 mal die 16 Chars von der Quelle mit dem Ziel vergleichen.

Ich habe jetzt mal den DB womit verglichen werden soll um ein Array verkleinert.
Also eine Array von 0..255 das ein UDT aufruft wo ein Array[1..16] of Char enthalten ist.

Screenshot 2021-12-07 175547.jpg

Ich muss doch von 0 bis 255 die 16 Chars prüfen das heißt das was ich da habe funktioniert sowieso nicht.
Ich brauche 2 For Schleifen. Die äußere bis 255 und die innere bis 16 oder ist das auch nicht richtig?
Warum muss das so kompliziert sein. Ich wünschte ich hätte Euren SPS Verstand.

Grüße Tommylik
 

Anhänge

  • Screenshot 2021-12-07 175203.jpg
    Screenshot 2021-12-07 175203.jpg
    71,4 KB · Aufrufe: 5
Du hast da zwei LaufVariablen i und l !?
Wie Ralle schon schrieb i von 1 bis 16. Sollte aber eigentlich überflüssig sein - es genügt doch die Arrays "Komplett" zu vergleichen, wenn sie aus denselben Anzahlen Bytes/Char bestehen. "X...".Schicht[l].Teil = Array
Die Fehlermeldungen unten verwirren. In Zeile 41 ist der Cursor und meckert, will Bool warum?
Die If-Abfrage benötigt einen logischen Ausdruck. Aber der Ausdruck ist doch bereits ein solcher. Die Vergleiche liefern doch BOOL und die AND-Verknüpfung von zwei solchen ist ebenfalls BOOL.
Die TypWandlung char_to_int sollte überflüssig sein.
Bin auch total verwirrt.

Deine ELSIF-Bedingung lässt sich vereinfachen, da der ELSIF-Zweig sowieso nur durchlaufen werden kann, wenn beide Arrays gleich sind.
Der ELSIF-Zweig ist ganz überflüssig.
Gleich := TRUE vor der Schleife und Gleich := FALSE vor dem Exit.

Welchen Wert soll 'Gleich' im Falle Ungleich haben?

Ich möchte doch 255 mal die 16 Chars von der Quelle mit dem Ziel vergleichen.
...
Ich brauche 2 For Schleifen. Die äußere bis 255 und die innere bis 16 oder ist das auch nicht richtig?
Genau, ist richtig!
 
Zuletzt bearbeitet:
Hallo Heinileini,

Vielen Dank für deine Antwort. Deine Antwort ist für mich ein wenig verwirrend aber sie hat geholfen.
Der Fehler ist weg.

Screenshot 2021-12-07 192204.jpg

Meinst du so?

Was ich aber nicht verstehe ist warum das True vor die Schleife soll wenn ich noch nicht begonnen habe und das False vor dem Exit.

Grüße Tommylik
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was ich aber nicht verstehe ist warum das True vor die Schleife soll wenn ich noch nicht begonnen habe und das False vor dem Exit.
Ich bin jetzt etwas verwirrt. Ich dachte, Du wolltest die innere Schleife (den Vergleich der 16 Char) vorzeitig mit EXIT verlassen, sobald Du das erste ungleiche Zeichen findest.
In diesem Fall (Abbruch durch EXIT wenn ungleich) also Gleich := FALSE vor den EXIT, weil ungleich, egal wie viele gleiche Zeichen noch folgen mögen.
Wenn beide Arrays gleich sind, weisst Du das erst, wenn Du alle 16 Char verglichen hast und die Schleife in keinem Durchlauf per EXIT verlassen wurde.
Und darum vor der Schleife Gleich := TRUE, weil, wenn alle 16 Char gleich sind, die Variable Gleich := TRUE sein soll.
In einer Schleife ist es natürlich vorteilhaft, wenn möglichst wenige Rechenschritte (durch die Schleife) mehrfach wiederholt werden müssen.
Besonders Zeit-sparend, wenn eine Schleife vorzeitig per EXIT verlassen werden kann.

Probier doch mal, wie der Compiler mit ...
Code:
IF "X_DB2390_NIOTeile".Teil[i].PraegeCode <> aArray THEN // Edit: sorry, hatte [i] geschlabbert
... zurecht kommt! Eigentlich müssten die beiden Arrays mit den je 16 Chars damit korrekt verglichen werden, ohne dass man die 16 Chars einzeln (per innerer Schleife) vergleichen muss.
 
Zuletzt bearbeitet:
Hallo Heinileini,

Vielen Dank für deine Hilfe.

Ich dachte, Du wolltest die innere Schleife (den Vergleich der 16 Char) vorzeitig mit EXIT verlassen, sobald Du das erste ungleiche Zeichen findest.

Mit deiner neuen Erklärung ja natürlich warum sollte sie mehr Durchläufe machen als notwendig.

Probier doch mal, wie der Compiler mit ...
Code:
IF "X_DB2390_NIOTeile".Teil.PraegeCode <> aArray THEN

Da kommt fehlerhafte Variable.

Anmerkung 2021-12-08 061519.JPG

Ich probiere mal die übersetzte Version mal aus.

Vielen Dank nochmal für deine Hilfe.

Grüße Tommylik
 

Anhänge

  • Anmerkung 2021-12-08 061519.JPG
    Anmerkung 2021-12-08 061519.JPG
    54,6 KB · Aufrufe: 1
Ist das wirklich in einer 400er umzusetzen? Für die 1200/1500 gibts den:
"Chars_TO_Strg: Array of CHAR in Zeichenkette konvertieren (S7-1200, S7-1500)"

Da wäre die Lösung ein 3-Zeiler.
 
Verdammt und sorry! Ich hatte mich vertippt!

Code:
IF "X_DB2390_NIOTeile".Teil[i].PraegeCode <> aArray THEN

... habe ich natürlich gemeint. Der Index i der äusseren Schleife muss natürlich bleiben.
 
Ich denke auch, die 400-er kann die Array nicht komplett miteinander vergleichen, das kann die 1500-er.
Daher sind in diesem Fall 2 Schleifen mit i und j sicher nicht verkehrt.
Sollte das nicht eine Frage des SCL-Compilers sein, ob/wie der einen Array-Vergleich in CPU-spezifische Anweisungen übersetzt?

Harald
 
Ich meine, ob man in SCL direkt Arrays vergleichen kann sollte nicht ein Problem der Fähigkeiten der CPU sein. Nicht die CPU 1500 kann die Arrays vergleichen, sondern der SCL-Compiler zerlegt das Array-Vergleichen in Einzel-Vergleiche. (vermute ich, nicht getestet)

Harald
 
Sollte das nicht eine Frage des SCL-Compilers sein, ob/wie der einen Array-Vergleich in CPU-spezifische Anweisungen übersetzt?
Das sehe ich aber auch so! Warum sollte der Compiler "sparsamer" sein, nur weil die Hardware "sparsamer" ist, für die er das Programm "mundgerecht" aufarbeitet? Die "Intelligenz" steckt doch im Compiler, der nicht auf der "sparsameren" Hardware läuft/laufen muss.
Ja genau. Und die (Compiler) sind bei 400-er und 1500-er nicht identisch oder?
Anscheinend "ParallelEntwicklungen", die recht unabhängig voneinander stattgefunden haben.
Das erinnert mich irgendwie an die 840C und die "nachgeschobene" 840D.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Anscheinend "ParallelEntwicklungen", die recht unabhängig voneinander stattgefunden haben.
Das erinnert mich irgendwie an die 840C und die "nachgeschobene" 840D.
Mir gegenüber hat ein Siemens-Mann mal gesagt, die hätten absichtlich die Step7-Classic-Entwickler außen vor gelassen, weil TIA komplett neu und toll werden soll. Ich dachte damals, "So blöd kann doch niemand sein!", aber doch, es geht. Ursprünglich sollten auch die 300/400-er gar nicht ins TIA, das Marketing wollte das unbedingt. Sicher auch ein Fehler, denke ich.

Mit Simotion hatten die schon ein geiles System, nahe an Codes, aber das war wohl zu nah.
 
Hallo,

Ich habe mit einem alten Kollegen gesprochen. Der hat mir heute auch gesagt das SCL im Simatic Manager
das gleichzeitigen vergleichen von Array of Char nicht unterstützt.

Code:
IF "X_DB2390_NIOTeile".Teil[i].PraegeCode <> aArray THEN
Ich habe dann in einer anderen Anlage wo wir TIA mit einer 1500er einsetzen deinen Code kompilieren können.

Aber egal ich habe eine jetzt eine laufende Version.

Code:
FUNCTION X_FC2395_Code_suchen : VOID
TITLE = 'PrCode_suchen'
//
// Baustein-Kommentar ...
//
VERSION : '1.0'
AUTHOR  : author
NAME    : name
FAMILY  : family

// Bausteinparameter
VAR_INPUT       
    Start_suchen            : BOOL;                 // Prägecode im DB suchen   
    PrCode                  : ARRAY[1..11] OF CHAR; // Prägecode von Lesestelle 
END_VAR

VAR_IN_OUT
    // Durchgangsparameter       
END_VAR

VAR_OUTPUT
    // Ausgangsparameter
    PrCode_gefunden         : BOOL; // Prägecode im DB gefunden.
    Done                    : BOOL; // DB durchsucht kein Prägecode gefunden.
END_VAR

VAR_TEMP
    // temporäre Variablen
    i                       : INT;     
END_VAR

BEGIN

PrCode_gefunden := False;

FOR i := 0 TO 255 DO     
    IF "X_DB2390_NIOTeile".Teil[i].PraegeCode[1] = PrCode[1]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[2] = PrCode[2]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[3] = PrCode[3]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[4] = PrCode[4]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[5] = PrCode[5]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[6] = PrCode[6]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[7] = PrCode[7]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[8] = PrCode[8]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[9] = PrCode[9]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[10] = PrCode[10]
       AND "X_DB2390_NIOTeile".Teil[i].PraegeCode[11] = PrCode[11] THEN
       PrCode_gefunden := True;
       EXIT;
    END_IF;
    Done := True;   
END_FOR;

END_FUNCTION

Vielen Dank nochmal für Eure Hilfe.

Gruß Tommylik
 
... Aber egal ich habe eine jetzt eine laufende Version.
Hauptsache, es funktioniert!
Schade, dass die CPU den Vergleich von 2 "gleichen" Arrays nicht so kann, wie erhofft.

Vielen Dank nochmal für Eure Hilfe.
Gerne, Tommylik!

Habe es noch mal auf 2 geschachtelte FOR-Schleifen umgestrickt.
Code:
VAR_TEMP
    // zusätzliche temporäre Variablen
    j                       : INT;   
    Gleich                  : BOOL;
END_VAR

BEGIN

PrCode_gefunden := False;
FOR i := 0 TO 255 DO   

    Gleich := TRUE ;
    FOR j := 1 TO 11 DO // nur bis 11 statt 16 ?   
        IF "X_DB2390_NIOTeile".Teil.PraegeCode[j] <> PrCode[j] THEN Gleich := FALSE; EXIT; END_IF;
    END_FOR;

    IF Gleich THEN PrCode_gefunden := True; EXIT; END_IF;
END_FOR;

Done := NOT PrCode_gefunden; // ?

END_FUNCTION
In den Deklarationen habe ich nur die zwei zusätzlichen TempVariablen aufgeführt.
 
Zuletzt bearbeitet:
Zurück
Oben