TIA Textfile vie Ethernet verschicken

Markus1988

Level-1
Beiträge
13
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

ich stehe vor folgender Aufgabe.

Ich muss mit einer S7-1214 in einem bestimmten Fall eine Textdatei an einen Etikettendrucker schicken, der Zebra-Drucksprache versteht. (Nicht kompliziert, Textfile existiert schon)
Ich habe ein bestehendes Netzwerk, wo CPU, Drucker und Display mit Ethernet kommunizieren.

Nun stellt sich für mich die Frage, mit welchen Bausteinen ich dieses Textfile speichere und wie ich es schaffe, dieses über Ethernet an eine bestimmte Adresse zu schicken.
Hat hier schon jemand Erfahrungen oder konnte dieses Problem schonmal jemand lösen?

Über Unterstützung, Tipps und evtl. Lösungen bedanke ich mich bereits jetzt schon.

Gruß Markus
 
Hi Markus,

ich hoffe ich antworte dir nicht zu spät. Aber ich habe genau das was du machen willst schon häufiger gemacht.

Wir setzen hier auch die S7-1214 ein und senden dabei gelegentlich über RS232 oder eben auch TCP/IP ein Druckfile an ein Zebra PAX-Modul.
Dabei ist es eigentlich egal ob es sich um ein PAX Modul oder ein anderes Zebra Druckmodul handelt. Die Skriptsprache ist immer ZPL (Zebra Programming Language).

Nun weiß ich nicht wie weit du dich im Allgemeinen mit dem Drucker auskennst und welchen Drucker du verwendest. - Vielleicht kannst du hierzu noch eine
Aussage treffen?

Ich habe das jedenfalls so gelöst das ich mir zur Laufzeit aus mehreren Variablen und festen Elementen wie zum Beispiel Header und sonstige Initialisierungs-
sequenzen mein Druckfile zusammensetze und in einem Array in einem Datenbaustein ablege.

Mit dem Baustein TSEND_C kannst du eine TCP Verbindung zu dem Drucker aufbauen, halten und die Daten aus dem Datenbaustein an den Drucker senden.

Wenn du (immer noch) Hilfe brauchst kann ich dir gerne weiter helfen (will mir jetzt hier nur nicht die Finger wund tippen ;) und du hast das Problem schon
selbst gelöst).

Gruß smartie
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Smartie,

das klingt ja schonmal sehr gut.
Als Drucker habe ich einen Eidos Printess Etikettendrucker (versteht aber ZPL Sprache).

Problem konnte ich noch nicht lösen möchte aber morgen mal eine SPS Verbindung mit dem Drucker aufbauen. Hab den Befel T_Send schon gesehen kann aber noch keine IP Adresse auswählen, vermutlich weil ich erst ein Gerät hinzufügen muss.

Was ich noch nicht genau weiß wie ich es löse ist der Inhalt des DB's. Hier muss ich ja das ZPL file ablegen oder? Oder muss ich mein ^CC..... Und so da eintippen?

Für weitere Hilfe bin ich dir im voraus schon dankbar. Falls evtl Bilder hast wäre das ganze noch besser :)

Gruß Markus
 
Hallo Markus,
ich versuche dir morgen Vormittag ein paar Screenshots zu posten, anhand denen
du das eigentlich hinbekommen solltest.
Ist eigentlich recht einfach. In dem DB legst du am besten ein Array of Char an, bei dem
jedes Byte einem Textzeichen deines ZPL Telegrams entspricht. Aber davon werde ich auch
einen Screenshot posten.

Welche Version von TIA setzt du ein?

Gruß smartie
 
Hallo Smartie,

Version von TIA ist Version 11 SP2 Update 3.

Danke dir, spart mir sehr viel Zeit an Gehirnschmalz verbraten und vermutlich auch an Ärger.

Gruß Markus
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen,

ich habe jetzt einmal ein paar Screenshots gemacht:

Wie du auf dem Bild "Druckaufbereitung_DB" siehst habe ich mir einen DB erstellt, der die einzelnen Elemente des Druckauftrags (Löschbefehl, Kopfzeile, Variablen, Fußzeile)
enthält. Diese einzelnen Arrays wandle ich zur Laufzeit in Strings, setze Sie zu einem Druckauftrag zusammen und wandle den String dann wieder in ein Array (Ausgangsspeicher)
welches ich an den Drucker sende.
- Dadurch kann ich flexibel auf die Länge der variablen reagieren.

Wenn dein Druckauftrag aber immer gleich aussieht brauchst du den ganzen Kram eigentlich nicht. Leg einfach einen DB an, indem du ein Array of CHAR definierst. Jedes Byte des
Array steht dann für ein Zeichen im Druckauftrag. Wichtig ist das du bei den Steuerzeichen (CR bzw 0D/LR bzw 0A) die richtigen verwendest: 0D entspricht $D, 0A entspricht $A.
Ich habe das in dem Datenbaustein mal markiert.

Auf dem Bild "Druckaufbereitung_FC_Param" erkennst du die Parametrierung des CONNECT_DB. Sobald du diese Einstellungen machst sollte der Datenbaustein eigentlich automatisch
generiert werden. Den gibst du dann am Funktionsbaustein "TSEND_C" als CONNECT an (siehe Bild "Druckaufbereitung_FC_Param" --> Verbindungsdaten).
Wichtig ist noch das der Verbindungsaufbau durch die SPS geschieht und das der richtige Port eingestellt ist. Die Zebra Drucker haben hier standardmäßig 9100. Sobald du einen Port
über 2000 eingibst wird die TIA zwar meckern, aber die Eingabe sollte trotzdem akzeptiert werden (wird halt nur gelb markiert).

Auf dem Bild "Druckaufbereitung_FC" erkennst du dann wie ich meinen "TSEND_C" Baustein belegt habe.

Ich hoffe du kommst soweit zurecht. - Wenn nicht schreib einfach, ich schau heute von Zeit zu Zeit mal rein.

Druckaufbereitung_DB.jpgDruckaufbereitung_FC.jpgDruckaufbereitung_FC_Param.jpg

smartie
 
Hallo Smartie,

super, vielen vielen Dank. Werd das heute, spätestens am Freitag mal testen und aufbauen sollte aber mit deiner Anleitung einfach funktionieren.

Gruß Markus
 
Hi

Diese einzelnen Arrays wandle ich zur Laufzeit in Strings, setze Sie zu einem Druckauftrag zusammen und wandle den String dann wieder in ein Array (Ausgangsspeicher) welches ich an den Drucker sende.
- Dadurch kann ich flexibel auf die Länge der variablen reagieren.

Wenn dein Druckauftrag aber immer gleich aussieht brauchst du den ganzen Kram eigentlich nicht. Leg einfach einen DB an, indem du ein Array of CHAR definierst. Jedes Byte des Array steht dann für ein Zeichen im Druckauftrag. Wichtig ist das du bei den Steuerzeichen (CR bzw 0D/LR bzw 0A) die richtigen verwendest: 0D entspricht $D, 0A entspricht $A. Ich habe das in dem Datenbaustein mal markiert.


zum Wandeln der von String nach CharArray und zurück gibt es zwei Systemfunktionen strg_to_chars und chars_to_strg. Die können einen das lästige Gewurstel mit einzelnen Zeichen im char array doch deutlich erleichtern.
Und noch etwas was so offensichtlich nicht im Handbuch steht. Angenommen, mein String in der TEMP heißt dings, dann kann man mit #dings auf die einzelnen Zeichen zugreifen. Liest man hinten raus, dann kommt '$00' zurück. Wenn man schreibt, dann kann man den String um jeweils ein Zeichen verlängern. Also angenommen #dings ist 'haus', dann macht #dings[1]:='H' ein 'Haus' draus. Ein #dings[5]:='!' erzeugt ein 'Haus!' aber ein folgendes #dings[7]:='x' geht nicht. Immer nur ein Zeichen dazu.

Warum ich das erzähle? Wegen der Performance.
Das Verlängern eines Strings um ein einzelnes Zeichen ist schneller als ein CONCAT oder ein + in SCL mit einem einzelen Zeichen. Etwa Faktor 5.
Sowohl das CONCAT als auch das überladene + in SCL sind interne Funktionen (MC7-Strich Befehle -- keine SFC oder FC Aufrufe -- also deutlich schneller als auf einer 317) die sich aber mit jeglicher Kombination von Quell und Zielstrings abmühen müssen. Da wird also erst mal viel geprüft, bevor es zur Sache geht. Das scheint das #dings nicht zu machen. Also nicht so intensiv, denn es ist ja klar, dass Quelle und Ziel der selbe String sind.
Den Faktor 5 hatte ich vor längerem auf einer 1200 vermessen. Bei der 1500 geht die Tendenz in die gleiche Richtung, aber der Faktor schwankt "wie Sau".

Fazit: Lange Strings mit CONCAT und kurze Strings mit Einzelzeichenzugriff verketten.


@Siemens: Warum gibt es den RUNTIME nicht in KOP/FUP?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Und noch etwas was so offensichtlich nicht im Handbuch steht. Angenommen, mein String in der TEMP heißt dings, dann kann man mit #dings auf die einzelnen Zeichen zugreifen. Liest man hinten raus, dann kommt '$00' zurück. Wenn man schreibt, dann kann man den String um jeweils ein Zeichen verlängern. Also angenommen #dings ist 'haus', dann macht #dings[1]:='H' ein 'Haus' draus. Ein #dings[5]:='!' erzeugt ein 'Haus!' aber ein folgendes #dings[7]:='x' geht nicht. Immer nur ein Zeichen dazu.


Scheint aber auch erst seit V12 zu funktionieren, in V11 ist das noch nicht möglich.
 
Hi !

ich muss mal hier einhaken... ich habe eine 300er CPU (315-F PN/DP) da gibts ja den TSEND_C nicht sondern nur den TSEND.
Welches Geraet muss ich anlegen damit ich das genauso verwenden kann ?

Gruss gerd
 
Hallo,

bei der S7-300 Baureihe werden dazu drei Bausteine benötigt.

- TCON: Baut eine Verbindung zum Partner auf.
- TSEND: Versendet bei aufgebauter Verbindung die Daten.
- TDISCON: Baut dei Verbindung zum Partner wieder ab

zusätzlich gibt es noch TRCV zum Empfangen der Daten

Viele Grüße
Klaus
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Smartie,

ich habe nochmal eine Frage. Habe jetzt meinen Baustein programmiert und auch IP Adresse und Port eingestellt. Nun stellt sich für mich die Frage, wie ich mein ZPL-Protokoll im Datenbaustein einstelle, da, sobald ich diesen öffne, schon Informationen drin stehen habe.

Folgender Datenstring soll an den Drucker geschickt werden.

^XA
^MCY
^XZ
^XA
^FWN^CFD,24^PW1299^LH0,0
^CI0^PR2^MNY^MTT^MMT^MD0^JJ0,0^PON^PMN^LRN
^XZ
^XA
^DFR:TEMP_FMT.ZPL
^LRN
^XZ
^XA
^XFR:TEMP_FMT.ZPL
^A0N,1181,1182^FO288,215^FDA^FS
^PQ1,0,1,Y
^XZ
^XA
^IDR:TEMP_FMT.ZPL
^XZ

Leg ich diesen als einzelne Zeile an oder jeden Buchstaben? Und wie wird dieser dann angewählt und an den Drucker geschickt?

Hoffe du kannst mir hier nochmal helfen! Danke schonmal im Vorraus.

Gruß Markus
 
Hallo Markus,

bin gerade im Urlaub und habe daher keinen Zugriff auf meinen Rechner. Daher kann ich dir erst mal nur empfehlen aus dem Post #6, in dem ich die Screenshots gepostet habe, das Bild "Druckaufbereitung_DB.jpg" zu Hilfe zu nehmen.

Wie do dort erkennen kanst habe ich ein Array vom Typ Char angelegt, jedes Byte des Array entspricht dabei einem Zeichen deines Datentelegramms.
Das bedeutet, du gibst dein Telegramm als ASCII Zeichen, Zeichen für Zeichen ein.
Wo du in deinem Telegramm Zeilenumbrüche hast erwartet der Drucker die Steuerzeichen CR (Carriage Return) und LF (Line Feed), die du in dem folgenden Format eingibst : $D steht für CR (16#0D), $A steht für LF (16#0A).

Auch das geht aus dem Screenshot hervor. Auf den weiteren Screenshots solltest du erkennen wie du den DB am Baustein TSend_C adressierst.
Theoretisch brauchst du ja nur die Adressen ändern.

Ich hoffe ich konnte dir so weiter helfen. Wenn nicht kannst du ja gerne mal einen Screenshot von dir posten, vielleicht kann ich dir dann gezielter helfen.

Gruß smartie
 
Hallo Smartie,

ok ich werde es mal probieren. Anbei ein Screenshot wie mein Datenbaustein nun aussieht, ohne dass ich was geschrieben habe. Bin mir da jetzt nicht ganz sicher wo nun das Array anlege.

Gruß MarkusDatenbaustein.jpg
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Markus,

Du musst einen neuen Baustein erstellen! In dem legst du dann dein Array an.
Der DB den du gerade als Screenshot gepostet hast ist der Connect DB und enthält die Verbindungsdaten. Da bitte nichts ändern!

Gruß smartie
 
Zuletzt bearbeitet:
Hallo Smartie,

nochmal Danke für den Tip. Hab jetzt meinen DB und so alles angelegt aber hab noch das Problem, dass nichts geschickt wird und ich auch nur am T_SEND Befehl bei Data ein Char eingeben kann. Wie kann ich das ändern?

Gruß Markus

DB.jpgDB_CHAR.jpg
 
Hallo Markus,

das sieht doch schon mal ganz vielversprechend aus. Um dein Array bei DATA am Baustein TSEND_C anzugeben musst du eigentlich nichts weiter machen, als die letzten drei Zeichen also [1] zu löschen. Das sollte das Program auch akzeptieren und nicht bemängeln.

Jetzt solltest du am Baustein TSEND_C auch noch den Fehlerstatus auswerten. Wichtig ist zu wissen das der Status unter Umständen auch nur einen Zyklus lang ansteht, du musst ihn also am besten, ausgelöst durch das Fehlerbit in eine andere Speicherstelle umkopieren.
Dann kannst du gezieltg nach einem eventuell auftretenden Fehler suchen.

Was mir noch aufgefallen ist, ist das du in deinem Datenbaustein statt dem Steuerzeichen ^ ein @ verwendet hast. Ist das Absicht. Ich kene das aus ZPL so nicht.

Probier das mal uns wenns Probleme gibt einfach wieder schreiben.

Gruß smartie
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,

also das @ ist ähnlich wie das ^. Mein Drucker versteht das aber.

Ich Versuch das nochmal mit dem löschen hatte aber glaub nicht funktioniert. Über den M0.0 kann ich das schon starten, wäre soweit richtig oder?

Gruß
 
Hi, also wenn das mit dem @ funktioniert dann ist das soweit gut.

Was mir aber vorhin nicht aufgefallen ist, ist das du den CONT Eingang des Baustein TSEND_C mit FALSE belegt hast. Das ist im wahrsten Sinne des Wortes falsch. :)

Bitte schau dir nochmal genau meine Screenshots aus Post #6 an (speziell Druckaufbereitung_FC.jpg). Erst wenn ein Signal am Eingang CONT anliegt wird überhaupt erst eine Verbindung zu dem am Baustein TSEND_C parametrierten Teilnehmer aufgebaut.
Wenn dann die Verbindung steht (Statusmeldung auswerten!) kann, ausgelöst durch eine Flanke am Eingang REQ das Datentelegramm gesendet werden.

Die detaillierten Beschreibungen zu den Statusmeldungen des Bausteins findest du in der Onlinehilfe des TIA Portals.

Welcher Merker das dann auslöst ist prinzipiell egal, sofern er nicht anderweitig schon verwendet wird natürlich.

Gruß smartie
 
Zuletzt bearbeitet:
Hallo Smartie,

ich bräuchte bitte nochmal deine Hilfe.

Das mit dem [1] löschen hat geklappt, ich hoffe nur dass er mir nun alles rausschickt. Ich habe die den Startwert auf 49 gesetzt, damit sollte er dann auch den kompletten Datensatz verschicken.
Leider klappt es aber nicht, dass er mir was verschickt. Der Status ändert sich von 16#7000 auf 16#7001, bei dir aber steht 16#7004. Ist das trotzdem ok?

Ich erkenne leider noch nicht meinen Fehler, habe deine Bilder eigentlicht komplett überprüft und wüsste nicht, was falsch ist. Wenn ich diesen Datenstring
@XA
@FT193,432@A0N,68,69@FDFAULT LABEL@FS
@XZ

an den Drucker über ein Terminal schicke, funktioniert dieser. Im Datenbaustein habe ich nun ein Array of Char [1...49] angelegt mit jedem Zeichen ein Char. Zeilenumbruch ist mit "$D" und "$A" mit drinnen, wie du es mir gesagt hast. Der Rest würde aber so drin stehen, wie oben im String vorhanden, z.B. 'X'; 'A'; usw. Ist das richtig?

Hoffe du kannst mir nochmal helfen. Bis dahin hast du mir eh schon sehr gut geholfen, wäre ich alleine nie darauf gekommen.

Gruß Markus

Main.jpg
 
Zurück
Oben