Step 7 Probleme mit AG_Recv nach Verbindungsausfall

Maxe_3000

Level-1
Beiträge
5
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Servus beisammen,

ich schreibe zur Zeit einen Treiberbausten in SCL für ein elektronisches Vorschaltgerät zum Schalten von UV-Lampen. Die S7-400 CPU kommuniziert über industrial Ethernet (CP 443-1) via Modbus/TCP Protokoll mit dem EVG. Der Baustein ist für die Verwendung im OB32 (1s Weckalarm) vorgesehen.

Grundsätzlich gibt es zwei Datentelegramme: 1. Statusabfrage (12 Byte ans EVG, 47 Byte Antwort vom EVG)
2. Command (49 Byte ans EVG, 12 Byte Antwort vom EVG)

Der Datenaustausch ist folgendermaßen geregelt:
1. Die zu sendenden Daten werden durch Abfrage der Ein- und Ausgänge generiert und in ein entsprechend langes Array geschrieben. AG_Send wird mit diesem Array aufgerufen.
2. Im nächsten Bausteinaufruf wird AG_Send nochmals mit den selben Parametern wie in Schritt eins aufgerufen, diesmal allerdings mit ACT = 0 um die Parameter "Done", "Error" und "Status" zu aktualisieren. Tritt ein Fehler auf, werden die Schritte eins und zwei wiederholt.
3. Wurde nach Schritt zwei durch Auswertung von "Done" bzw "Error" ein abgeschlossener Sendevorgang sichergestellt, wird AG_Recv mit einem entsprechend großen Array (durch Programmflags bekannt) aufgerufen. Die Parameter "LEN" und "Error" werden ausgewertet und ggf. wird Schritt drei wiederholt.

Das alles klappt auch so wie es soll und in der Regel braucht das Programm hierfür 4 Bausteinaufrufe. Um das Verhalten bei Verbindungsfehlern zu analysieren, habe ich das Ethernetkabel am EVG ausgesteckt und nach variierender Zeit wieder eingeteckt. In den meisten Fällen nimmt der Baustein die Kommunikation wieder auf, allerdings nicht wenn der Verbindungsausfall - wie ich annehme - unmittelbar während des Rücksendens (EVG an CP) eintritt.

Meine Annahme ist nun folgende:
Durch den abgebrochenen Rücksendevorgang liegen Daten ungleich der erwarteten Länge im Empfangsdatenpuffer des CP 443-1 wodurch ein undefinierter Offset entsteht. Die Daten können dann von AG_Recv nicht mehr richtig eingelesen werden, da die Datenlänge nicht mehr der Länge des Arrays entspricht.

Ist meine Annahme richtig? Kann das so vorkommen? Gibt es eine Möglichkeit den Empfangsdatenpuffer des CP zu löschen?

Vielen lieben Dank im voraus.

Mit freundlichen Grüßen
Max
 
Normalerweise sollte es bei TCP so sein, dass entweder das gesamte Datenpaket übernommen wird oder überhaupt nichts. Wenn also mitten in der Übertragung die Verbindung abbricht, sollte überhaupt nichts eintreffen.

Woher stammen denn deine Modbus-TCP Funktionen?

Verwendest du wirklich AG_RECV also FC6 in der S7-400? Auf TCP-Verbindungen musst du in der S7-400 FC60 oder FC63 verwenden, siehe Bausteindokumentation.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zunächst einmal vielen Dank für deine schnelle Antwort.

Normalerweise sollte es bei TCP so sein, dass entweder das gesamte Datenpaket übernommen wird oder überhaupt nichts. Wenn also mitten in der Übertragung die Verbindung abbricht, sollte überhaupt nichts eintreffen.

Hm, komisch, in dem Array stehen entweder die richtigen Daten drin, allerdings am falschen Index oder komplett programmfremde Daten. Allerdings ist mir aufgefallen dass sich der Fehler beheben lässt, in dem man das EVG aus- und wieder einschaltet (was leider nur über Stecker ziehen möglich ist).

Woher stammen denn deine Modbus-TCP Funktionen?

Die Funktionen die an das EVG gesendet werden, werden vom S7-Programm gemäß des Datenblattes vom EVG generiert. Ich benutze nur die Funktionen FC3 "Read multiple Registers" und FC16 "Write multiple Registers". In den Nutzdaten stehen dann pro Lampe ein Byte für Commands (16#10 = Lampe ein, 16#40 = Lampe aus, 16#30 = Lampe dimmen) und ein Byte für Daten (Strom auf den gedimmt werden soll, sonst 16#00). Das alles funktioniert problemlos und die Lampen machen was sie tun sollen.

Verwendest du wirklich AG_RECV also FC6 in der S7-400? Auf TCP-Verbindungen musst du in der S7-400 FC60 oder FC63 verwenden, siehe Bausteindokumentation.

Aber muss ich die Funktionen AG_LSEND und AG_LRECV nicht erst dann verwenden wenn die Datenlänge 250 Byte übersteigt? Die eigentliche Kommunikation funktioniert mit AG_SEND und AG_RECV ja bisher problemlos.

Vielen Dank im Voraus.

Mit freundlichen Grüßen
Max
 
Das mit dem FC6 habe ich eben auch das erste mal so bewusst gelesen. Ich weiß nicht ob ich das in einer S7-400 schonmal verwendet habe. Dort steht zumindest:
für S7-400 gilt:

- Bei den Programmbausteinen AG_SEND / AG_RECV ist die Datenlänge pro Auftrag auf <=240 Byte beschränkt.
Längere Datensätze (bis zu 8192 Byte) können mit Hilfe der FCs AG_LSEND oder AG_LRECV übertragen werden.
- Die Programmbausteine AG_SSEND und AG_SRECV dienen der beschleunigten Übertragung von Daten, indem eine optimierte Bausteinkommunikation zwischen CPU und CP in der S7-Station verwendet wird. Die schnelle Kommunikation bleibt ohne Auswirkung auf die LAN-Kommunikation.

- In der S7-400 kann auf TCP-Verbindungen der FC6 nicht verwendet werden, sondern nur der FC60 oder der FC63.

Bekommst du denn nach dem Abbruch überhaupt keine Daten mehr? Oder nur versetzt?

Wie ist der Verbindungszustand zu diesem Zeitpunkt in NetPro, und welchen Statuswert bekommst du an AG_(L)Recv?

Es gibt noch den FC10 AG_CNTRL mit dem du Verbindungen diagnostizieren und ggf. zurücksetzen kannst. Eigentlich sollte das nicht notwendig sein.

Du musst daran denken, dass es bei einer TCP-Verbindung keine Verbindungs(Zustands-)überwachung gibt. D.h. wenn der CP Link hat und du das Netzwerkkabel am Partner abziehst (z.B. mit Switch dazwischen), dann bekommt das der CP überhaupt nicht mit. Erst wenn du Daten senden willst und das TCP Paket wird nicht bestätigt (nach entsprechender Anzahl an Retries) wird die Verbindung neu aufgebaut. Das kann aber schon mal 30s und mehr dauern nach meiner Erfahrung bis der CP das erkennt und dann versucht die Verbindung neu aufzubauen. Ich meine der AG_SEND bestätigt dir beim Senden auch nur, dass der CP die Daten übernommen hat und nicht dass diese auch beim Partner angekommen sind. Glaub da gabs mal einen Thread zu hier im Forum.
 
Bekommst du denn nach dem Abbruch überhaupt keine Daten mehr? Oder nur versetzt?

Hab mir gestern Nachmittag mal ne Lizenz für Wireshark aus dem Rechenzentrum geholt und mir mal angeschaut was da so alles auf der Leitung unterwegs ist, nachdem ich die Verbindung wieder hergestellt hab. Dabei ist mir ein Telegramm vom EVG an die S7 aufgefallen, was zu den mir unbekannten Daten führen könnte. Allerdings ist dieses weit größer als 47 Byte, sodas die Funktion AG_Recv die Daten ja auch garnicht richtig in das von mir zugewiesene Array einleisen dürfte, oder? Oder hab ich da bzgl. AG_Recv noch was falsch verstanden?
Ich vermute dass dieses Telegramm für den Datenmüll auf der Netzwerkkarte verantwortlich ist. Blöd ist allerdings dass dieses Telegramm in relativ unregelmäßigen Abständen immer wieder mal gesendet wird und die eigentlich angeforderten Daten unterdrückt werden und nur hin und wieder durchkommen.

Wie ist der Verbindungszustand zu diesem Zeitpunkt in NetPro, und welchen Statuswert bekommst du an AG_(L)Recv?

In NetPro bleibt der Zustand von "aktiver Verbindungsaufbau" auf ja, die Statusmeldung von AG_Recv ist wie erwartet 8304 während die Verbindung getrennt ist und danach wechselt diese zwischen 0 und 8181. LEN gibt mir 47 zurück, wie aber bereits gesagt dürfte dies doch garnicht funktionieren oder?

Es gibt noch den FC10 AG_CNTRL mit dem du Verbindungen diagnostizieren und ggf. zurücksetzen kannst. Eigentlich sollte das nicht notwendig sein.

Ich les mich mal durch die Bausteindokumentation aber grundsätzlich könnte dies für meinen Fall ja auch ganz nützlich sein, oder? Wenn ich feststelle dass in dem Array Daten stehen die dort nicht hingehören, einfach mal die Verbindung zurücksetzen. Aber wie ist das dann mit dem Datenpuffer der Netzwerkkarte?

Freundliche Grüße
Max
 
Ich habs mir vom Rechenzentrum auf meinen Arbeits-PC installieren lassen, da wir laut Betriebsverordnung keine Programme aus dem Internet laden dürfen sondern diese von der IT installiert werden müssen. Hab mich wohl bisschen falsch ausgedrückt, aber ich wollte den Satz kurz halten.
 
Warum schickt dir das Gerät denn unaufgefordert irgendwelche Daten zu? Das entspricht dann nicht Modbus TCP. Du stellst eine Anfrage, das Gerät antwortet gemäß Protokoll. Wenn das Gerät sich anderes verhält, sag dem Hersteller er soll das korrigieren oder dieses seltsame Verhalten wenigstens dokumentieren damit man zur Not damit etwas anfangen kann (ich würde mich dann eher nach einem anderen Gerät umsehen).

Wenn wenigstens der Modbus-Header passt und immer vorhanden ist, dann könntest du erst die 7 Bytes des Modbus-Headers lesen, entnimmst die Längenangabe daraus und liest dann diese Anzahl an Bytes-1. Wenn du feststellst, das ist keine Antwort auf deine Anfrage, dann verwirfst du das Paket. Eigentlich solltest du das immer so machen, denn falls auf deine Anfrage einmal keine erfolgreiche Antwort kommt, kommst du mit dem Lesen der festen Längen spätestens dann aus dem Tritt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Warum schickt dir das Gerät denn unaufgefordert irgendwelche Daten zu? Das entspricht dann nicht Modbus TCP. Du stellst eine Anfrage, das Gerät antwortet gemäß Protokoll.

Bei den Daten die mir das EVG unaufgefordert sendet, handelt es sich nicht um Modbus Daten, zumindest konnte ich keinen entsprechenden Header finden. Auch Wireshark zeigt mir die Daten nicht als Modbus an sondern nur als TCP.

Wenn wenigstens der Modbus-Header passt und immer vorhanden ist, dann könntest du erst die 7 Bytes des Modbus-Headers lesen, entnimmst die Längenangabe daraus und liest dann diese Anzahl an Bytes-1. Wenn du feststellst, das ist keine Antwort auf deine Anfrage, dann verwirfst du das Paket. Eigentlich solltest du das immer so machen, denn falls auf deine Anfrage einmal keine erfolgreiche Antwort kommt, kommst du mit dem Lesen der festen Längen spätestens dann aus dem Tritt.

Ok, aber spätestens dann brauche ich irgendeinen dynamischen Puffer in den ich die jeweilige Antwort einlesen kann. Wie könnte ich das umsetzen?

Mit freundlichen Grüßen
Max
 
Ok, aber spätestens dann brauche ich irgendeinen dynamischen Puffer in den ich die jeweilige Antwort einlesen kann. Wie könnte ich das umsetzen?

Ich weiß ja nicht wie du jetzt das Modbus-Protokoll auswertest. Sinnvollerweise solltest du auch jetzt schon den Modbus-Header auf Korrektheit auf deine Anfrage prüfen, und ggf. das Telegramm verwerfen wenn es nicht korrekt ist. Das wäre das minimale was du für Modbus benötigst. Einfach so ohne Prüfung die Daten zu verwenden ist zu fehleranfällig (vielleicht solltet ihr euch überlegen die Modbus-Bausteine von Siemens zu erwerben).

Du benötigst einen Puffer der mindestens so groß ist wie die Daten die du maximal erwartest. Wenn dein Partner dir aber völligen Unfug schickt, dann weißt du auch nicht was dich erwartet. Wenn das wirklich so sein sollte wie du schreibst, dann bekommst du das nicht stabil ans Laufen. Wenn man sich auf die "Sprache" Modbus-TCP geeinigt hat, dann hat man sich daran zu halten und nicht zwischendurch Chinesisch zu sprechen.

In deinem Fall würde ich darum einen Puffer von z.B. 100 Bytes anlegen, und einen Bereich für den Modbus-TCP Header. Dann liest du zuerst den Header ein, und wenn dieser überhaupt nicht mit deinen angefragten Daten zusammenpasst (Transaction/Protocol identifier falsch, Unit identifier falsch, Länge zu groß), dann würde ich die Verbindung mit AG_CNTRL zurücksetzen. Denn dann weißt du mangels Header auch nicht wie viele Bytes dir überhaupt geschickt wurden. Du könntest dann höchstens solange AG_Recv aufrufen bis der Puffer leer ist und die Daten einfach wegwerfen. Aber wer weiß wie lange er mit den Spielchen weitermacht.

Hier gibt es ein Beispiel von Siemens wie du variable Längen verarbeiten könntest:
https://support.industry.siemens.com/cs/ww/de/view/8707570
 
Zurück
Oben