TIA TCP/IP beliebigen String senden & empfangen S7-1515sp et200sp

RosiBro

Level-1
Beiträge
54
Reaktionspunkte
5
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey ihr Lieben,

ich bräuchte mal eure Hilfe.

Ich möchte mit meiner 1515er SPS, als Client eine TCP/IP Verbindung über OpenUserCommunication mit einem PC aufbauen, wo ein Programm die Daten als Server verarbeitet und auch Daten wieder zurücksendet.

Das Problem: Ich sende Strings beliebiger Länge und auch die Strings, die ich empfange sind unterschiedlich lang, je nachdem, welche Informationen ich abfrage. Ich bekomme auf jeden Fall eine Verbindung hin (die Verbindungsstatus geht auf 7004 und auch der Server zeigt die Verbindung an), allerdings schaffe ich es noch keine Daten zu senden und ich glaube es liegt an meiner Tia Programmierung (der Server zeigt mir zumindest keine gültige Kommunikation an und würde auch entsprechend eine Acknowledge Message senden, was er aber nicht tut). Wenn ich die Verbindung aber resete, bekomme ich ein "C" zurückgesendet, was heißt "Connection completed", also scheinbar kann der Server mir Daten senden, auch wenn vielleicht auch nur einzelne Char (zumindest ist das eine gültige Antwort, andere konnte ich noch nicht triggern), aber immerhin etwas.

Ich habe mir dazu einen TSEND_C FB und einen TRCV_C FB in das Main OB gepackt.

TSEND_C.PNGTRCV_C.PNG

Bei der Umsetzung habe ich mich weitestgehend an das Beispiel aus dem Handbuch gehalten (deswegen auch erstmal die umständlichen Bezeichnungen).
Da auf eine Anfrage meist eine sofortige Antwort in Form einer Acknowledge Message kommt habe ich nach dem erfolgreichen Senden den Client sofort auf RCV gesetzt:
wait_for_Ack.PNG

Mein Sende- und Empfangsdatenbereich sind so definiert, beide jeweils als Standard Datenblöcke (im Handbuch stand, wenn man im AdHoc Modus ist, also Daten unbekannter Länge empfangen möchte, kann man beliebige Datentypen nur dann empfangen, wenn die Datenblöcke nicht in einem optimierten Datenbereich liegen) :
send_rcv_data.PNG

Ich finde aber das Problem nicht? Liegt es an meiner Datenbereichsdefinition? Oder habe ich irgendwo was komplett übersehen?

Besten Dank euch für eure Hilfe!

Edit: geschrieben wurde das ganze in Tia Portal V15.1
 
Zuletzt bearbeitet:
String Datentyp ist hier etwas unpraktisch, weil zu einem S7 String immer ein Header gehört den du immer mitsenden würdest. Wenn die Gegenstelle damit umgehen kann ist das Ok, muss aber beachtet werden.

Wenn du das Protokoll selber gestalten kannst, dann macht es wirklich vieles einfacher wenn du dich auf eine fixe Länge für beide Teilnehmer einigst. TCP ist ein nackter Datenstrom, die Partner wissen nicht wann ein Teil davon beginnt und wann es endet. Entweder musst du das über eine feste Länge fixieren, oder du musst dir zumindest ein kleines Protokoll herum überlegen. Möglich wäre z.B. in den ersten beiden Bytes die folgende Länge der Nutzdaten einzutragen. Will jemand "Hallo" schicken, dann schickt er in den ersten beiden Bytes die 5, und dann die 5 Zeichen.
Dann kannst du in deinem Receive Baustein immer erst 2 Bytes aus dem Puffer lesen, wertest die Länge aus und liest dann mit einem zweiten Aufruf die angegebene Anzahl.

Ich habe das mit dem Adhoc Modus noch nicht verwendet, aber bei TCP ist es nunmal so, dass wenn dir jemand 100 Byte schickt, es nicht gewährleistet ist, dass diese auch in einem Rutsch am Receive Baustein zur Verfügung stehen. Meiner Meinung nach musst du auch beim Adhoc Modus die empfangenen Daten nach jeden Aufruf einzeln verarbeiten und die Daten zu einem kompletten Telegramm zusammensetzen. Der einzige Vorteil beim Adhoc Modus ist, dass du nicht bei jedem Aufruf die Länge umschalten musst.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke dir,

Lieder bin ich, was die Protokollgestaltung angeht nicht ganz frei. Der Server ist vorimplementiert und ich konnte den Datenblättern und Handbüchern nicht entnehmen, wie er die Daten verarbeitet. Aber du hattest Recht und er kommt mit dem Header nicht zurecht.
Der Server entnimmt die Befehlslänge aus einem Bestätigungszeichen, woran er erkannt hat, dass die Zeichenkette zu ende ist (sonst macht er einfach gar nichts).

Umgesetzt habe ich das Ganze jetzt mit einem String welcher für den Versand mit StringToChar in ein Array of Byte konvertiert wird - da gibt es die Länge gleich mit dazu, die ich dann an TSEND_C übergeben kann, um mir den Header zu sparen.
Für den Empfang einfach andersherum.
Funktioniert super.

Danke dir noch einmal für deine Hilfe!
 
Ohne eine Kennung wann dein String beginnt oder endet, kann das mit TCP nicht funktionieren. Du musst damit rechnen, dass wenn du von deinem Programm aus zwei Strings mit zwei Aufrufen verschickst, dass der Partner dieses in einem Stück liest. Woher soll er wissen, dass das zwei sind?
TCP ist ein Datenstrom, und kein Datenblock wie z.B. bei UDP.
 
Außer du würdest bevor du jeden String sendest, die Verbindung neu aufbauen und danach wieder abbauen. Dann könnte der Partner daraus ableiten, dass alles was dazwischen empfangen wurde zu einem Block gehört.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja, habe ich hier gerade nicht beschrieben, weil mein Problem ein bisschen mehr der Server war, der überhaupt nicht reagiert hat.
Der wiederum scheint die Strings direkt auszuwerten und anhand eines Zeilenumbruchs zu erkennen, dass ein neuer Befehl auftaucht (sende ich das nicht mit, hat er genau das gleiche Problem: er weiß nicht wo die Nachricht endet).
Aber du hast Recht - auf der Client-Seite bekomme ich solange keinen String heraus, bis ich die Verbindung nicht resette und dann packt er mir das trotz Adhoc alles in einen String, was er mir jetzt als letztes gesendet hat. Aber ja - woher soll er es auch anders wissen.
Ich frage mich noch ein bisschen, was der Mehrwert des Adhoc-Modus ist, aber vielleicht würde er mir die Sachen auch instant ausgeben, wenn ich das ENO mit der obigen Implementierung nicht solange blockieren würde, bis er mir ein "Done" ausgibt, was er aber nicht ausgibt, weil er ja nicht weiß, wann das ist. Ich werde das dann mal testen.

Mein aktueller Alternativ-Plan ist, die Strings in Paketen mit der kleinsten zu erwartenden Stringlänge auszuwerten und auf das obige Symbol zu untersuchen (das sendet der Server nach jeder kompletten Nachricht auch noch mit), sie dann wieder zusammenzubasteln und dann als einzelne Strings auszugeben.
 
Wenn du jeden String mit einem Zeilenumbruch abschließt, dann wäre das auch schon ausreichend (wenn in einem String sonst kein Zeilenumbruch als gültiges Zeichen erlaubt ist).

Wie der Adhoc Modus funktioniert weiß ich auch nicht. Den gibt es auch noch nicht so lange. Ich weiß nicht ob ich mich darauf verlassen würde, dass dort etwas sinnvolles herauskommt.

Ansonsten wie du sagst, wenn es eine Mindestlänge gibt, in Schritt 1 diese in einen Zwischenpuffer lesen. Wenn kein Zeilenumbruch empfangen, Byteweise weiterlesen und in den Zwischenpuffer anhängen, bis entweder ein Zeilenumbruch kommt, oder Timeout wenn zu lange kein Zeichen mehr empfangen wurde (dann Zwischenpuffer leeren). Das ist dann zwar etwas tröpfchenweise und mit einem Längenheader ginge es flotter, aber funktionieren tut es so auch.
 
Ich habe mal vor 4 Jahren Mini-Anlagen (1200er) mit TCP Verbindung zu einem PC mit ADHOC-Modus gemacht. Das funktionierte eigentlich recht gut + einfach. Da kommt einfach ein Empfangsblock, der bei kleinen Datenmengen wohl dann auch automatisch "alles" ist. Wird dann wohl über Timeout oder auf Protokollebene als "Block fertig" = Neue Daten gemeldet.
Da ist es aber Applikationsbedingt so, das nicht schnell hintereinander Daten kommen. Aber ich hatte vorher auch Angst ...
Im Zweifelsfall muss jeder Sender eine Mindestpause zwischen 2 Sendeanstößen machen...
 
Zuletzt bearbeitet:
Zurück
Oben