Step 7 Ethernet Kommunikation Keyence Kamerasystem mit S7-400

Beiträge
622
Reaktionspunkte
67
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

Ich habe hier ein Verständnissproblem, vielleicht könnt ihr mir helfen:
Wir haben hier eine S7-400 die mit einem Keyence CV-X150 System kommuniziert.

Mit dem Baustein "AG send" werden Referenzwerte an die Kamera gesendet (z.b. MHD, EAN Code...)
Das funktioniert auch ohne Probleme.

Die Kamera sendet dann Bestätigungen zurück die mit "AG LRECV" empfangen werden.
Diese werden dann ab DB483.DBB200 geschrieben:

1701256179743.png

Sobald neue Daten ankommen werden die über eine Flanke in einen anderen Datenbereich geschoben und der Empfangsbereich abgelöscht.

1701256260917.png

Die Zeichen die wir Empfangen sind zwar richtig, aber kommen im Empfangsbereich willkürlich "verschoben an"

So sehen die Daten der Kamera aus:
(< kommt von der Kamera)
1701259660461.png


Empfangen wird das ganze aber zb. so, Also das "ER" beginnt irgendwo, statt am Anfang des Empfangsbereichs.
Das verschiebt sich auch bei jedem neuen Datenpaket.
1701260142427.png

Ich habe das nicht selbst programmiert, sehe aber auch keine offensichtlichen Fehler...bin aber auch eher unerfahren was das betrifft.
Hat jemand von euch eine Idee wie wir das beheben können, bzw. wo der Fehler liegen könnte?
Keyence konnte uns da nicht helfen.
Hintergrund ist das wir das Programm der Kamera über die SPS umschalten wollen und die Rückmeldung davon auswerten.

Vielen Dank für eure Zeit!


Beste Grüße
Michael
 
Mal kurz drübergeschaut... Dein NW14 ruft ja den SFC20 also Blockmove auf.
Im DB zeigst Du uns nur den Zielbereich.
Hast Du mal geschaut, wie direkt nach dem Empfang der Quellbereich DB483.DBX202 aussieht? Wird es da schon verschoben empfangen? Oder wird es ggf. dort in dem Bereich aus irgendeinem Grund verschoben/bearbeitet?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mal kurz drübergeschaut... Dein NW14 ruft ja den SFC20 also Blockmove auf.
Im DB zeigst Du uns nur den Zielbereich.
Hast Du mal geschaut, wie direkt nach dem Empfang der Quellbereich DB483.DBX202 aussieht? Wird es da schon verschoben empfangen? Oder wird es ggf. dort in dem Bereich aus irgendeinem Grund verschoben/bearbeitet?
Hallo,

ja der Empfangsbereich ab Byte 202 schaut exakt gleich aus!
 
Ist im Keyence irgendeine Reihenfolge definiert?
Kann es vielleicht auch sein, dass der Keyence die gelesenen Codes anhand der Lesereihenfolge in den Sendepuffer wirft?

p.s.
Bei der Initialisierung des Strings ist der Aktualwert nur geladen, nicht beschrieben.
Hat das einen bestimmten Grund, wieso der Pointer beim AG_LRECV 10 Byte lang ist und der bei den BLKMOV's 100Byte lang ist?
 
Hallo,
Ich kenne dieses Verhalten bei TCP-Verbindungen wenn die Länge der empfangenen Daten nicht mit der Länge des Empfangspuffers übereinstimmt.
Also entweder ein Fehler in der Parametrierung oder aber die Kamera sendet unterschiedlich lange Antworten.

Grüße von HaDi
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Ich kenne dieses Verhalten bei TCP-Verbindungen wenn die Länge der empfangenen Daten nicht mit der Länge des Empfangspuffers übereinstimmt.
Also entweder ein Fehler in der Parametrierung oder aber die Kamera sendet unterschiedlich lange Antworten.

Grüße von HaDi

Ja das mit der Datenlänge ist uns jetzt auch aufgefallen. Und ja, die Kamera sendet unterschiedlich lange Antworten.
Auf jeden Fall ist keine davon 10 Byte lang.

Ich habe mir vorher diese Anleitung zu durchgelesen, da steht am Anfang mehr oder weniger das gleiche:



Jetzt brauchen wir nur noch eine Lösung dafür. :rolleyes:
 
Der Empfangsbereich DB483.DBX202 wird ja vermutlich auch 100 Byte lang sein.
Also kannst Du den RECV-Pointer auch auf 100 setzen und schauen, ob dann der Empfang besser klappt.
Am Ausgang LEN erfährst Du dann, wie viele Byte davon gültig sind.
 
Entweder
- Die Kamera dazu bringen immer gleich lange Antworten zu senden
Oder
- Die Daten byteweise empfangen bis nix mehr kommt
Oder
- Die Verbindung auf ISOonTCP umstellen

Grüße von HaDi
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Jetzt brauchen wir nur noch eine Lösung dafür. :rolleyes:
Alle Bytes lesen die ihr für die Schnittstelle vorgesehen habt, sauber ablöschen nach dem die Daten geschoben worden sind, so viele Bytes aus dem Empfang- in den Arbeitsbereich schieben wie #RecLen anstehen, alles in einen String packen was die Ergebnisdaten angeht (ist $r immer gleich als erstes Zeichen?).

Und dann mal in der Keyence Software schauen ob die Daten übereinstimmen mit dem, wie der String aufgebaut ist
 
Alle Bytes lesen die ihr für die Schnittstelle vorgesehen habt, sauber ablöschen nach dem die Daten geschoben worden sind, so viele Bytes aus dem Empfang- in den Arbeitsbereich schieben wie #RecLen anstehen, alles in einen String packen was die Ergebnisdaten angeht (ist $r immer gleich als erstes Zeichen?).

Und dann mal in der Keyence Software schauen ob die Daten übereinstimmen mit dem, wie der String aufgebaut ist


Hallo,

Bei RecLen steht immer exakt die Größe vom RECV ...also wenn wir den auf zb. 100 erhöhen, steht dort auch 100. Es werden die empfangen Strings scheinbar angesammelt bis 100Bytes empfangen wurden und dann alle gleichzeitig in den Empfangsbereich geschrieben.

Soll das so sein?

$r steht immer am Ende eines Strings.
 
Hallo,

Bei RecLen steht immer exakt die Größe vom RECV ...also wenn wir den auf zb. 100 erhöhen, steht dort auch 100. Es werden die empfangen Strings scheinbar angesammelt bis 100Bytes empfangen wurden und dann alle gleichzeitig in den Empfangsbereich geschrieben.

Soll das so sein?

$r steht immer am Ende eines Strings.
Dann müßtest Du im Empfangsbereich aber ja auch sehen, daß da mehrere Strings enthalten sind. Siehst Du das?
Oder ist der empfangene Datensatz größer als 100 Byte?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also, ich hab das so in Erinnerung (bei TCP-Verbindung):
-maßgeblich ist die Länge des parametrierten Empfangspuffers
-wenn die entsprechende Anzahl an Bytes (oder mehr!) empfangen wird dann wird der Empfangspuffer in der S7 gefüllt und NDR für einen Zyklus gesetzt
-kommen weniger Daten passiert auf S7-Seite nix, auch im Empfangspuffer kann man m.M.n. nichts sehen
-kommen mehr Daten dann wird trotzdem nur die parametrierte Länge an Daten übertragen, die zusätzlichen Daten werden anschließend an den Anfang des Puffers gestellt und neue Daten dahinter gesetzt, so entsteht der Versatz den du beobachtet hast

Grüße von HaDi
 
Das ist jetzt schon ewig her (2011), dass ich dafür einen Baustein geschrieben habe.
Die Daten von der Keyence-Kamera waren immer unterschiedlich lang. Wenn Daten empfangen wurden, habe ich die rauskopiert und mir gemerkt, wo das Ende war. Beim nächsten Empfang ging es da weiter und natürlich dann das, was nicht in den Buffer bis zum Ende hineinpaßte, stand ab Bufferanfang. Das rollierte sozusagen.

Hier mal der Teil-Code von Damals in SCL, vielleicht nützt dir das etwas:

Code:
//Datemempfang mit AG_RECV-Baustein
IF Send.ACT = True THEN
  Recv.Daten_receive := False;
END_IF;


         AG_RECV (
           ID                       := 1,
           LADDR                    := LADDR,
           RECV                     := Recv.Data,
           NDR                      := Recv.NDR,
           ERROR                    := Recv.Error,
           STATUS                   := Recv.Status,
           LEN                      := Recv.Len);


    //Prüfen auf Überlauf des Buffer
    //Achtung, die empfangenen Daten sind unterschiedlich lang daher muß auf jeden Fall '$r' als Endekennung des Strings angehängt sein,
    //sonst kann nicht entschieden werden, ob der Buffer übergelaufen ist oder der String genau hineingepaßt hat
   
    IF ((RECV.LEN <> NextReceiveStartPos) AND (Recv.LEN <> 0) AND (Recv.LEN <> 100)) OR (Recv.NDR AND ((Recv.LEN <> 100) OR (Recv.Data[100] = '$r'))) THEN    
        Recv.Daten_receive := True;
        LastReceiveStartPos := NextReceiveStartPos;
        NextReceiveStartPos := Recv.LEN;


        //Daten werden immer rollierend in den Buffer eingetragen und müssen nun
        //dementsprechend dort herauskopiert werden.      


        //Daten im Buffer erst einmal löschen
        Code_Len := 0;
        FOR I := 1 TO 100 DO
            Code_Data[I] := INT_TO_CHAR(0);
            Error_Code[I] := INT_TO_CHAR(0);
        END_FOR;


        //Normalfall --> die Daten haben in den Buffer gepaßt
        IF NextReceiveStartPos >= LastReceiveStartPos THEN
            Rest_Len := 0;
            Receive_Len := NextReceiveStartPos - LastReceiveStartPos;
            IF Receive_Len > 100 THEN
                Receive_Error := True;
                Receive_Len := 0;
                NextReceiveStartPos := LastReceiveStartPos;
            END_IF;
                   
            //Code mit den empfangenen Daten füllen
            FOR I := 1 TO Receive_Len DO
                Code_Data[I] := Recv.Data[LastReceiveStartPos + I];
                Code_Len := Receive_Len;
            END_FOR;
           
        ELSE;
        //Sonderfall --> die Daten haben nicht in den Buffer gepaßt
            Rest_Len := 101 - LastReceiveStartPos;
            Receive_Len := NextReceiveStartPos + 100 - LastReceiveStartPos;
            IF Receive_Len > 100 THEN
                Receive_Error := True;
                Receive_Len := 0;
                Rest_Len := 0;
                NextReceiveStartPos := LastReceiveStartPos;
            END_IF;
                   
            IF Rest_Len <= Receive_Len THEN
                //Code mit den empfangenen Daten bis Ende Buffer füllen
                FOR I := 1 TO Rest_Len DO
                  Code_Data[I] := Recv.Data[LastReceiveStartPos + I];
                END_FOR;
                //Code mit den empfangenen Daten ab Anfang Buffer füllen
                FOR I := Rest_Len TO Receive_Len DO
                   Code_Data[I] := Recv.Data[I - Rest_Len + 1];
                   Code_Len := Receive_Len;
                END_FOR;  
            END_IF;    
        END_IF;
        //Die Evaluation kommt unabhängig von einem Sendeereignis an
        //Daher hier auswerten, welche Auswertung angekommen ist und die entsprechende
        //Nachricht an die Schrittketten erzeugen
        IF Code_Data[1] = 'A' AND
           Code_Data[2] = '1' AND
           Code_Data[3] = ',' THEN
            Evaluation_1_Received := True;
        END_IF;
        IF Code_Data[1] = 'A' AND
           Code_Data[2] = '2' AND
           Code_Data[3] = ',' THEN
            Evaluation_2_Received := True;
        END_IF;
        IF Code_Data[1] = 'A' AND
           Code_Data[2] = '4' AND
           Code_Data[3] = ',' THEN
            Evaluation_3_Received := True;
        END_IF;
        IF Code_Data[1] = 'A' AND
           Code_Data[2] = '5' AND
           Code_Data[3] = ',' THEN
            Evaluation_4_Received := True;
        END_IF;
    END_IF;
 
Hallo Ralle!

Vielen Dank für den Code, ich habe das erst heute gesehen!
Wir hatten das Projekt wegen anderer Dinge verschoben.
Gut zu wissen dass es ein Keyence Feature ist und kein Bug...

Wenn wir weiter an dem Projekt arbeiten werde ich mich melden wie wir weiter vorgegangen sind.

Danke noch mal an alle die sich bis jetzt beteiligt haben! :D
Beste Grüße
Michael
 
Zurück
Oben