Step 7 STEP7 SCL - Telegrammlänge auswerten

bmwled

Level-2
Beiträge
62
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen,

folgende Situation: Eine Kamera liest einen DMC Code von einem Aufkleber ein, wertet diesen aus und schickt ein Telegramm an die SPS.
Der FB empfängt die Daten und gibt einen Wert "Empfangslänge" aus. Dieser sollte wenn alles mit dem DMC Code i.O. ist 47 BYTE betragen.
Im Fehlerfall könnte der DMC Code kürzer bzw länger sein. Die Qualitätsauswertung bleibt unberührt.
Nun frage ich mich, wo im FB die Abfrage der "Endekennung CR" vom Telegramm statt finden müsste, damit der korrekte Wert "47" und nicht wie aktuell "239" ausgegeben wird...



FB161:

Code:
FUNCTION_BLOCK "FB161 VS TRIGGER DATA"


//AUTHOR : DV
//FAMILY : BAUMER
//VERSION : 1.0
   VAR_INPUT 
      START : Bool;
   END_VAR


   VAR_OUTPUT 
      FINISHED : Bool;
      EMPFANGSLAENGE : Int;
      DATEN : ARRAY[1..254] OF Char;
   END_VAR


   VAR_IN_OUT 
      SendReceiveTelegramm : "udtSendReceiveTelegramm";
   END_VAR


   VAR 
      FHM_Flanke : Bool;
   END_VAR


   VAR_TEMP 
      tmp_Laenge_Endezeichen : Int;
      RET_VAL_WORD : Word;
      tmp_WORD : Word;
      tmp_Zaehler : Int;
      tmp_DATEN : BYTE;
   END_VAR




BEGIN
    //----------------------------------------------------
    //                PROTOKOLL Versionen
    //
    // | PROTOKOLL |              VERSION                |
    // |-----------|-------------------------------------|
    // |    10     | ETHERNET: Without end identifier    |
    // |    11     | ETHERNET: End identifier <CR>       |
    // |    12     | ETHERNET: End identifier <LF>       |
    // |    13     | ETHERNET: End identifier <CR><LF>   |
    // |           |                                     |
    //
    //----------------------------------------------------
    
    IF NOT START THEN
        
        FINISHED   := FALSE;
        FHM_Flanke := FALSE;
        
    END_IF;
    
    // ***************************************************
    // *****          Telegramm zusammenbauen        *****
    // ***************************************************
    
    // Befehl TR für Trigger setzen
    
    SendReceiveTelegramm.SEND.Zeichen[1] := 'T';
    SendReceiveTelegramm.SEND.Zeichen[2] := 'R';
    
    // Protokoll / Endezeichen 
    
    IF SendReceiveTelegramm.PROTOKOLL = 11 THEN
        
        SendReceiveTelegramm.SEND.Zeichen[3] := BYTE_TO_CHAR(b#16#D);
        SendReceiveTelegramm.SEND.Zeichen[4] := BYTE_TO_CHAR(b#16#0);
        SendReceiveTelegramm.SEND.Laenge     := 3;
        tmp_Laenge_Endezeichen               := 1;
        
    ELSIF SendReceiveTelegramm.PROTOKOLL = 12 THEN
        
        SendReceiveTelegramm.SEND.Zeichen[3] := BYTE_TO_CHAR(b#16#A);
        SendReceiveTelegramm.SEND.Zeichen[4] := BYTE_TO_CHAR(b#16#0);
        SendReceiveTelegramm.SEND.Laenge     := 3;
        tmp_Laenge_Endezeichen               := 1;
        
    ELSIF SendReceiveTelegramm.PROTOKOLL = 13 THEN
        
        SendReceiveTelegramm.SEND.Zeichen[3] := BYTE_TO_CHAR(b#16#D);
        SendReceiveTelegramm.SEND.Zeichen[4] := BYTE_TO_CHAR(b#16#A);
        SendReceiveTelegramm.SEND.Laenge     := 4;
        tmp_Laenge_Endezeichen               := 2;
        
    ELSE
        
        SendReceiveTelegramm.SEND.Zeichen[3] := BYTE_TO_CHAR(b#16#0);
        SendReceiveTelegramm.SEND.Zeichen[4] := BYTE_TO_CHAR(b#16#0);
        SendReceiveTelegramm.SEND.Laenge     := 2;
        tmp_Laenge_Endezeichen               := 0;
        
    END_IF;
    
    // ***************************************************
    // *****             Telegramm senden            *****
    // ***************************************************
    
    SendReceiveTelegramm.SEND.Start := START;
    
    IF START AND NOT FHM_Flanke THEN
        
        FOR tmp_Zaehler := 1 TO 254 DO
            
            // Daten ablöschen 
            EMPFANGSLAENGE := 0;
            DATEN[tmp_Zaehler] := ' ';
            
            FHM_Flanke := TRUE;
            
        END_FOR;
        
    END_IF;
    
    // ***************************************************
    // *****            Telegramm empfangen          *****
    // ***************************************************
    
    IF (SendReceiveTelegramm.SEND.Start AND
        SendReceiveTelegramm.SEND.Gesendet AND
        SendReceiveTelegramm.RECEIVE.NDR AND
        SendReceiveTelegramm.RECEIVE.Zeichen[1] = 'R' AND
        SendReceiveTelegramm.RECEIVE.Zeichen[2] = 'D') THEN
        
        FOR tmp_Zaehler := 1 TO 4 DO
            
            // Daten von ASCII Zeichen in Hexadezimal umwandeln und kopieren 
             tmp_WORD := SHL(IN:= tmp_WORD, N := 4); 
             tmp_DATEN := CHAR_TO_BYTE(SendReceiveTelegramm.RECEIVE.Zeichen[tmp_Zaehler + 2]);
             tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 48);
                 
             IF BYTE_TO_INT(tmp_DATEN) >= 10 THEN
                    
                tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 7);
                    
                IF BYTE_TO_INT(tmp_DATEN) >= 6 THEN
                        
                    tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 32);  
                END_IF;
             END_IF;
             
             tmp_WORD := tmp_WORD OR BYTE_TO_WORD(tmp_DATEN); 
                      
        END_FOR;
        
        EMPFANGSLAENGE := WORD_TO_INT(tmp_WORD);
                               
        FOR tmp_Zaehler := 1 TO EMPFANGSLAENGE DO
                
            // Daten kopieren 
            DATEN[tmp_Zaehler] := SendReceiveTelegramm.RECEIVE.Zeichen[6 + tmp_Zaehler];
                
        END_FOR;
                                
        FINISHED := TRUE;
            
    END_IF;
        
    SendReceiveTelegramm.RECEIVE.NDR := FALSE;
    
END_FUNCTION_BLOCK
 

Anhänge

  • Überprüfung_Länge.jpg
    Überprüfung_Länge.jpg
    112 KB · Aufrufe: 27
Zuletzt bearbeitet:
Wer hat das bitte geschrieben, sieht ja schrecklich aus.

Da wird irgendwie aus den ersten bytes des empfangenen die Länge ausgelesen. Stehen die da als Ascii im Telegram?

edit: Byte 2 bis 6 ?

Man kann natürlich auch jedes für sich wandeln und entsprechend multiplizieren und addieren ohne viel schieben und verknüpfen.
 
Zuletzt bearbeitet:
BYTE 1 und 2 ist nur das Read-Kommando deshalb auch RD. Ab BYTE 3 beginnt das Wesentliche bzw. das was auch unter "DATEN" zur Verfügung gestellt wird.
 
DATEN[tmp_Zaehler] := SendReceiveTelegramm.RECEIVE.Zeichen[6 + tmp_Zaehler];

Da wird ja umkopiert, in dem Eingangspuffer muss also vorher noch mehr drin stehen. Da würd ich mal gucken.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Code:
    // ***************************************************
    // *****            Telegramm empfangen          *****
    // ***************************************************
    
    IF (SendReceiveTelegramm.SEND.Start AND
        SendReceiveTelegramm.SEND.Gesendet AND
        SendReceiveTelegramm.RECEIVE.NDR AND
        SendReceiveTelegramm.RECEIVE.Zeichen[1] = 'R' AND
        SendReceiveTelegramm.RECEIVE.Zeichen[2] = 'D') THEN
        
        FOR tmp_Zaehler := 1 TO 4 DO
            
            // Daten von ASCII Zeichen in Hexadezimal umwandeln und kopieren 
             tmp_WORD := SHL(IN:= tmp_WORD, N := 4); 
             tmp_DATEN := CHAR_TO_BYTE(SendReceiveTelegramm.RECEIVE.Zeichen[tmp_Zaehler + 2]);
             tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 48);
                 
             IF BYTE_TO_INT(tmp_DATEN) >= 10 THEN
                    
                tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 7);
                    
                IF BYTE_TO_INT(tmp_DATEN) >= [COLOR=#ff0000]1[/COLOR]6 THEN
                        
                    tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 32);  
                END_IF;
             END_IF;
             
             tmp_WORD := tmp_WORD OR BYTE_TO_WORD(tmp_DATEN); 
                      
        END_FOR;

Die fehlende 1 ist der Fehler.

Ohne wird bei einem großem A tmp_DATEN negativ.

Gruß
 
Zuletzt bearbeitet:
Code:
    // ***************************************************
    // *****            Telegramm empfangen          *****
    // ***************************************************
[...]
                IF BYTE_TO_INT(tmp_DATEN) >= [COLOR="#FF0000"]6[/COLOR] THEN    [COLOR="#0000FF"]<--- muß ">= 16" heißen[/COLOR]

und hier die blauen Codezeilen aus der FOR-Schleife herausnehmen:
Code:
    // ***************************************************
    // *****             Telegramm senden            *****
    // ***************************************************
    
    SendReceiveTelegramm.SEND.Start := START;
    
    IF START AND NOT FHM_Flanke THEN
        
[COLOR="#0000FF"]        // Daten ablöschen 
        EMPFANGSLAENGE := 0;
        FHM_Flanke := TRUE;[/COLOR]

        FOR tmp_Zaehler := 1 TO 254 DO
            DATEN[tmp_Zaehler] := ' ';
        END_FOR;
        
    END_IF;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
und hier die blauen Codezeilen aus der FOR-Schleife herausnehmen:
Code:
    // ***************************************************
    // *****             Telegramm senden            *****
    // ***************************************************
    
    SendReceiveTelegramm.SEND.Start := START;
    
    IF START AND NOT FHM_Flanke THEN
        
[COLOR=#0000FF]        // Daten ablöschen 
        EMPFANGSLAENGE := 0;
        FHM_Flanke := TRUE;[/COLOR]

        FOR tmp_Zaehler := 1 TO 254 DO
            DATEN[tmp_Zaehler] := ' ';
        END_FOR;
        
    END_IF;

Was bewirken die blauen Zeilen bzw. warum sollten diese besser entfernt werden?
Mit der Schleife soll ja vermutlich nur der DATEN-Speicher abgelöscht werden...
 
Zuletzt bearbeitet:
Was bewirken die blauen Zeilen bzw. warum sollten diese besser entfernt werden?
Die Programmzeilen sollen aus der FOR-Schleife herausgenommen werden, weil es reicht, den Variablen EMPFANGSLAENGE und FHM_Flanke nur einmal einen Wert zuzuweisen anstatt in der Schleife 254 mal den selben Wert. (Performance)

So sieht der original Code aus:
Code:
    // ***************************************************
    // *****             Telegramm senden            *****
    // ***************************************************
    
    SendReceiveTelegramm.SEND.Start := START;
    
    IF START AND NOT FHM_Flanke THEN
        
        FOR tmp_Zaehler := 1 TO 254 DO
            
            [COLOR="#FF0000"]// Daten ablöschen [/COLOR]
            [COLOR="#FF0000"]EMPFANGSLAENGE := 0;[/COLOR]
            DATEN[tmp_Zaehler] := ' ';
            
            [COLOR="#FF0000"]FHM_Flanke := TRUE;[/COLOR]
            
        END_FOR;
        
    END_IF;
und so sieht mein Verbesserungsvorschlag aus:
und hier die blauen Codezeilen aus der FOR-Schleife herausnehmen:
Code:
    // ***************************************************
    // *****             Telegramm senden            *****
    // ***************************************************
    
    SendReceiveTelegramm.SEND.Start := START;
    
    IF START AND NOT FHM_Flanke THEN
        
[COLOR="#0000FF"]        // Daten ablöschen 
        EMPFANGSLAENGE := 0;
        FHM_Flanke := TRUE;[/COLOR]

        FOR tmp_Zaehler := 1 TO 254 DO
            DATEN[tmp_Zaehler] := ' ';
        END_FOR;
        
    END_IF;

Harald
 
Nach der Änderung hat es funktioniert! Perfekt!!
So weit waren wir doch gestern schon:
Code:
        FOR tmp_Zaehler := 1 TO 4 DO
             // Daten von ASCII Zeichen in Hexadezimal umwandeln und kopieren // "Hexadezimal" ist hier irreführend
             tmp_WORD := SHL(IN:= tmp_WORD, N := 4); 
             tmp_DATEN := CHAR_TO_BYTE(SendReceiveTelegramm.RECEIVE.Zeichen[tmp_Zaehler + 2]);
             tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 48);
             IF BYTE_TO_INT(tmp_DATEN) >= 10 THEN // war keine ASCII-Ziffer, also noch 7 subtrahieren (wg. GrossBuchstaben)
                tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 7);
                IF BYTE_TO_INT(tmp_DATEN) >= [COLOR=#ff0000][B]6[/B][/COLOR] THEN // Unsinn! Wenn > 32, dann noch 32 subtrahieren, um KleinBuchstaben zu verarbeiten
                    tmp_DATEN := INT_TO_BYTE(BYTE_TO_INT(tmp_DATEN) - 32); 
                END_IF;    
             END_IF;
             tmp_WORD := tmp_WORD OR BYTE_TO_WORD(tmp_DATEN); 
        END_FOR;
In Deinem FB wird falsch abgefragt. >=6 ist Unsinn - vergleich hier mal mit 32.
 
Zurück
Oben