Step 7 S7 Programm für Texttransfer zu Textdisplay

Dieter Höger

Level-1
Beiträge
4
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe hier folgendes Protokoll, welches in einem DB eingetragen ist und via Ethernetschnittstelle zu einem LED Textdisplay übertragen werden soll. Wer hat eine Idee (S7 Programmierbeispiel) wie dies zu realisieren ist.

Habe derzeit selbst keine simple Lösung parat. Für eure Hilfe bedanke ich mich im voraus.
Mfg CDH

SendeDaten STRUCT
start0 BYTE B#16#0 Null
start1 BYTE B#16#0 Null
start2 BYTE B#16#0 Null
start3 BYTE B#16#0 Null
start4 BYTE B#16#0 Null
SOH BYTE B#16#1 Start of Head
Sendeadresse STRUCT
a1 CHAR 'F'
a2 CHAR 'F'
END_STRUCT
Empfangsadressse STRUCT
b1 CHAR '0'
b2 CHAR '0'
END_STRUCT
STX BYTE B#16#2 General command codes for transmission
Commandcode0 BYTE B#16#41
Commandcode1 BYTE B#16#30
Commandcode2 BYTE B#16#43
Commandcode3 BYTE B#16#32
Commandcode4 BYTE B#16#32
Commandcode5 BYTE B#16#30
Commandcode6 BYTE B#16#30
Commanfcode7 BYTE B#16#30
Commandcode8 BYTE B#16#30
Commandcode9 BYTE B#16#30
Commandcode10 BYTE B#16#30
Commandcode11 BYTE B#16#32
Commandcode12 BYTE B#16#33
Commandcode13 BYTE B#16#35
Commandcode14 BYTE B#16#39
Commandcode15 BYTE B#16#FF
Commandcode16 BYTE B#16#FF
Commandcode17 BYTE B#16#FF
Commandcode18 BYTE B#16#33
Commandcode19 BYTE B#16#FD
Commandcode20 BYTE B#16#42
Commandcode21 BYTE B#16#7F
Commandcode22 BYTE B#16#FE
Commandcode23 BYTE B#16#45
DataField STRUCT Begin of Text "Gehaeuse bereitstellen"
A0 BYTE B#16#47 G
A1 BYTE B#16#65 e
A2 BYTE B#16#68 h
A3 BYTE B#16#61 a
A4 BYTE B#16#65 e
A5 BYTE B#16#75 u
A6 BYTE B#16#73 s
A7 BYTE B#16#65 e
A8 BYTE B#16#7F Zeilenumbruch
A9 BYTE B#16#62 b
A10 BYTE B#16#65 e
A11 BYTE B#16#72 r
A12 BYTE B#16#65 e
A13 BYTE B#16#69 i
A14 BYTE B#16#74 t
A15 BYTE B#16#73 s
A16 BYTE B#16#74 t
A17 BYTE B#16#65 e
A18 BYTE B#16#6C l
A19 BYTE B#16#6C l
A20 BYTE B#16#65 e
A21 BYTE B#16#6E n
END_STRUCT
ETX STRUCT End of Text
H BYTE B#16#3
END_STRUCT
Checksum STRUCT
J1 BYTE B#16#0
J2 BYTE B#16#39
J3 BYTE B#16#32
J4 BYTE B#16#39
EOT BYTE B#16#4 End of Transmission
END_STRUCT
END_STRUCT
 

Anhänge

  • Protokoll incl.pdf
    34,7 KB · Aufrufe: 10
Und nun?
Du kopierst die Daten einzeln in ein Byte-Array entsprechender Länge um, und schickst das Bytearray dann raus.
Wenn dein Datensatz sich nicht ändert, kannst du die Daten auch direkt als Startwerte im Array hinterlegen. Vom Prinzip her so wie du es jetzt auch mit den Structs gemacht hast, nur liegen mehrere Structs nicht unbedingt direkt hintereinander im Speicher, dort werden ggf. sogenannte Füllbytes eingeschoben die du dann mitverschicken würdest.

Wenn es dynamisch sein soll, würde ich das Ganze in eine Funktion packen die ein String als Parameter übergeben bekommt. Dort übergibst du dann z.B. einen String mit "Gehaeuse bereitstellen". Dann baust du in dem Array den Kopf zusammen (oder hinterlegst sie als Startwerte), kopierst du einzelnen Zeichen des Strings in den Datenteil, und hängst hinten das EOT an.

Wenn du eine S7-1500 verwendest, gibt es noch eine Möglichkeit mit einem Anwenderdatentyp.
 
Hallo Thomas_V2.1

Die SPS ist eine 319F
Habe mit den zugetragenen Ideen lange versucht, bin aber zu keinem brauchbarem Ergebnis gekommen.
Es sollen auch variable Texte aus einem DB versendet werden, Die variablen Texte werden aus einem Touch in dem DB abgelegt, ich lese die DB aus dessen Text-Datenbereiche aus.
Der Bereich von start0 BYTE bis zum Commandocode23 (bezeichnet als Kopf) und auch das Protokollende (Bezeichnet als EOT) muß mit jedem variablem Text, welcher zwischen Protokollkopf und Protokollende liegt übertragen werden. D.h., dass bei jedem Text das Übertragungsprotokoll an die Textanzeige neu zusammengesetzt werden muß, bzw. der vorhandene Text gegen einen neuen getauscht werden muß.
Die Textlänge kann von 0 bis 50 Zeichen varieren. Die Übertragung ans Display aus dem DB will ich mit dem AG-SEND (FC5) durchführen.
Da mir zum Zusammensetzen von Strings die praktische Erfahrung fehlt meine Frage, hat evtl. jemand ein Beispielprogramm welches ich hierfür verwenden kann.
 
Vorsicht, Dein STRUCT kannst Du so nicht senden, weil da noch einige versteckte Füllbytes enthalten sind: zwischen Commandcode23 und dem Struct DataField, nach ETX.H und nach Checksum.EOT. STRUCTs und ARRAYs mit ungerader Anzahl Bytes werden mit einem Füllbyte auf gerade Byteanzahl aufgefüllt.

Strings verketten kann man mit FC2 CONCAT. Doch da Dein Nachrichten-Kopf und -Ende viele nicht-druckbare Zeichen enthält (16#0 .. 16#1F und 16#7F .. 16#FF) und für variable Zieladressen indirekte Adressierung oder selbstgebastelte ANY-Pointer nötig sind, würde ich die Nachricht nicht aus Strings in dem BYTE-Array zusammenbauen. Lediglich für bessere Lesbarkeit würde ich die eigentlichen Nachrichtentexte als STRING deklarieren und kopieren (danach muß man noch die mitkopierten 2 Byte Stringheader entfernen/überschreiben). Die Zieladressen und Zeichenanzahlen kann man einfach beim Programmieren abzählen (kann man aber auch aus den Stringheadern auslesen und berechnen).

AG_SEND kannst Du nur verwenden, wenn Du über einen CP343-1 sendest. Falls Deine 319F eine integrierte PN-Schnittstelle hat und Du darüber senden willst, dann mußt Du TSEND verwenden.

Das Zusammenstellen kann man so machen:
Code:
//SendMsg zusammenstellen, Byte 0..34 sind vorinitialisiert
//Adressen in Kopf eintragen
      L     'F'
      T     "DB_Send".SendeDaten.Sendeadresse.a1
      L     'F'
      T     "DB_Send".SendeDaten.Sendeadresse.a2
      L     '0'
      T     "DB_Send".SendeDaten.Empfangsadressse.b1
      L     '0'
      T     "DB_Send".SendeDaten.Empfangsadressse.b2

//Text 'Gehaeuse bereitstellen' an Kopf anhängen (Text1, 22 Zeichen)
      CALL  "BLKMOV"
       SRCBLK :="DB_Send".Text1         //STRING[22] ab DB43.DBX100.0
       RET_VAL:=#temp_Int
       DSTBLK :=P#DB43.DBX33.0 BYTE 24  //(ab Commandcode22) 24 = 22 Zeichen + 2 Byte Stringheader

//BLKMOV hat der Einfachheit halber einen String mit Stringheader kopiert,
//nun in die überschriebenen Bytes DBB33 und DBB34 den richtigen Wert eintragen
      L     B#16#FE
      T     "DB_Send".SendeDaten.Commandcode22
      L     B#16#45
      T     "DB_Send".SendeDaten.Commandcode23

//Checksumme eintragen ...
      L     B#16#0
      T     "DB_Send".End.Checksum1
      L     B#16#39
      T     "DB_Send".End.Checksum2
      L     B#16#32
      T     "DB_Send".End.Checksum3
      L     B#16#39
      T     "DB_Send".End.Checksum4
//... und anhängen
      CALL  "BLKMOV"
       SRCBLK :="DB_Send".End           //P#DB43.DBX94.0 BYTE 6
       RET_VAL:=#temp_Int
       DSTBLK :=P#DB43.DBX57.0 BYTE 6   //Startadresse DBX57.0 abhängig Textlänge (z.B. abzählen)

      L     63                          //Gesamtlänge der Msg (Kopf + Text + End)
      T     "DB_Send".MsgLen

//...

      CALL  "AG_SEND"
       ACT   :="AG_SEND_ACT"
       ID    :=1
       LADDR :=W#16#100
       SEND  :="DB_Send".SendeDaten     //P#DB43.DBX0.0 BYTE 92
       LEN   :="DB_Send".MsgLen         //63
       DONE  :="AG_SEND_DONE"
       ERROR :="AG_SEND_ERROR"
       STATUS:="AG_SEND_STATUS"

Der DB43 "DB_Send" dazu:
Code:
DATA_BLOCK "DB_Send"
TITLE =
VERSION : 0.1

  STRUCT
   SendeDaten : STRUCT                 // +0.0
    start0 : BYTE := B#16#0;
    start1 : BYTE := B#16#0;
    start2 : BYTE := B#16#0;
    start3 : BYTE := B#16#0;
    start4 : BYTE := B#16#0;
    SOH    : BYTE := B#16#1;
    Sendeadresse : STRUCT              // +6.0
     a1 : CHAR  := 'F';
     a2 : CHAR  := 'F';
    END_STRUCT ;
    Empfangsadressse : STRUCT          // +8.0
     b1 : CHAR  := '0';
     b2 : CHAR  := '0';
    END_STRUCT ;
    STX : BYTE  := B#16#2;             // +10.0
    Commandcode0 : BYTE  := B#16#41;
    Commandcode1 : BYTE  := B#16#30;
    Commandcode2 : BYTE  := B#16#43;
    Commandcode3 : BYTE  := B#16#32;
    Commandcode4 : BYTE  := B#16#32;
    Commandcode5 : BYTE  := B#16#30;
    Commandcode6 : BYTE  := B#16#30;
    Commandcode7 : BYTE  := B#16#30;
    Commandcode8 : BYTE  := B#16#30;
    Commandcode9 : BYTE  := B#16#30;
    Commandcode10 : BYTE := B#16#30;
    Commandcode11 : BYTE := B#16#32;
    Commandcode12 : BYTE := B#16#33;
    Commandcode13 : BYTE := B#16#35;
    Commandcode14 : BYTE := B#16#39;
    Commandcode15 : BYTE := B#16#FF;
    Commandcode16 : BYTE := B#16#FF;
    Commandcode17 : BYTE := B#16#FF;
    Commandcode18 : BYTE := B#16#33;
    Commandcode19 : BYTE := B#16#FD;
    Commandcode20 : BYTE := B#16#42;
    Commandcode21 : BYTE := B#16#7F;
    Commandcode22 : BYTE := B#16#FE;   // +33.0
    Commandcode23 : BYTE := B#16#45;   // +34.0
    TextStart : BYTE := B#16#0;        // +35.0
    DataField : STRUCT                 // +36.0
     A : ARRAY  [0 .. 55 ] OF //max 50 Zeichen Text + 6 Zeichen End
     CHAR  := ' ';
    END_STRUCT ;
   END_STRUCT ;
   MsgLen : INT ; //41..92             // +92.0
   End : STRUCT                        // +94.0
    ETX : BYTE  := B#16#3;
    Checksum1 : BYTE := B#16#0;
    Checksum2 : BYTE := B#16#39;
    Checksum3 : BYTE := B#16#32;
    Checksum4 : BYTE := B#16#39;
    EOT : BYTE  := B#16#4;
   END_STRUCT ;
   Text1 : STRING  [22 ] := 'Gehaeuse bereitstellen'; // +100.0
   Text2 : STRING  [13 ] := 'Noch ein Text';          // +124.0
  END_STRUCT ;
BEGIN
   SendeDaten.start0 := B#16#0; 
   SendeDaten.start1 := B#16#0; 
   SendeDaten.start2 := B#16#0; 
   SendeDaten.start3 := B#16#0; 
   SendeDaten.start4 := B#16#0; 
   SendeDaten.SOH := B#16#1; 
   SendeDaten.Sendeadresse.a1 := 'F'; 
   SendeDaten.Sendeadresse.a2 := 'F'; 
   SendeDaten.Empfangsadressse.b1 := '0'; 
   SendeDaten.Empfangsadressse.b2 := '0'; 
   SendeDaten.STX := B#16#2; 
   SendeDaten.Commandcode0 := B#16#41; 
   SendeDaten.Commandcode1 := B#16#30; 
   SendeDaten.Commandcode2 := B#16#43; 
   SendeDaten.Commandcode3 := B#16#32; 
   SendeDaten.Commandcode4 := B#16#32; 
   SendeDaten.Commandcode5 := B#16#30; 
   SendeDaten.Commandcode6 := B#16#30; 
   SendeDaten.Commandcode7 := B#16#30; 
   SendeDaten.Commandcode8 := B#16#30; 
   SendeDaten.Commandcode9 := B#16#30; 
   SendeDaten.Commandcode10 := B#16#30; 
   SendeDaten.Commandcode11 := B#16#32; 
   SendeDaten.Commandcode12 := B#16#33; 
   SendeDaten.Commandcode13 := B#16#35; 
   SendeDaten.Commandcode14 := B#16#39; 
   SendeDaten.Commandcode15 := B#16#FF; 
   SendeDaten.Commandcode16 := B#16#FF; 
   SendeDaten.Commandcode17 := B#16#FF; 
   SendeDaten.Commandcode18 := B#16#33; 
   SendeDaten.Commandcode19 := B#16#FD; 
   SendeDaten.Commandcode20 := B#16#42; 
   SendeDaten.Commandcode21 := B#16#7F; 
   SendeDaten.Commandcode22 := B#16#FE; 
   SendeDaten.Commandcode23 := B#16#45; 
   SendeDaten.TextStart := B#16#0; 
   SendeDaten.DataField.A[0] := ' '; 
   SendeDaten.DataField.A[1] := ' '; 
   SendeDaten.DataField.A[2] := ' '; 
   SendeDaten.DataField.A[3] := ' '; 
   SendeDaten.DataField.A[4] := ' '; 
   SendeDaten.DataField.A[5] := ' '; 
   SendeDaten.DataField.A[6] := ' '; 
   SendeDaten.DataField.A[7] := ' '; 
   SendeDaten.DataField.A[8] := ' '; 
   SendeDaten.DataField.A[9] := ' '; 
   SendeDaten.DataField.A[10] := ' '; 
   SendeDaten.DataField.A[11] := ' '; 
   SendeDaten.DataField.A[12] := ' '; 
   SendeDaten.DataField.A[13] := ' '; 
   SendeDaten.DataField.A[14] := ' '; 
   SendeDaten.DataField.A[15] := ' '; 
   SendeDaten.DataField.A[16] := ' '; 
   SendeDaten.DataField.A[17] := ' '; 
   SendeDaten.DataField.A[18] := ' '; 
   SendeDaten.DataField.A[19] := ' '; 
   SendeDaten.DataField.A[20] := ' '; 
   SendeDaten.DataField.A[21] := ' '; 
   SendeDaten.DataField.A[22] := ' '; 
   SendeDaten.DataField.A[23] := ' '; 
   SendeDaten.DataField.A[24] := ' '; 
   SendeDaten.DataField.A[25] := ' '; 
   SendeDaten.DataField.A[26] := ' '; 
   SendeDaten.DataField.A[27] := ' '; 
   SendeDaten.DataField.A[28] := ' '; 
   SendeDaten.DataField.A[29] := ' '; 
   SendeDaten.DataField.A[30] := ' '; 
   SendeDaten.DataField.A[31] := ' '; 
   SendeDaten.DataField.A[32] := ' '; 
   SendeDaten.DataField.A[33] := ' '; 
   SendeDaten.DataField.A[34] := ' '; 
   SendeDaten.DataField.A[35] := ' '; 
   SendeDaten.DataField.A[36] := ' '; 
   SendeDaten.DataField.A[37] := ' '; 
   SendeDaten.DataField.A[38] := ' '; 
   SendeDaten.DataField.A[39] := ' '; 
   SendeDaten.DataField.A[40] := ' '; 
   SendeDaten.DataField.A[41] := ' '; 
   SendeDaten.DataField.A[42] := ' '; 
   SendeDaten.DataField.A[43] := ' '; 
   SendeDaten.DataField.A[44] := ' '; 
   SendeDaten.DataField.A[45] := ' '; 
   SendeDaten.DataField.A[46] := ' '; 
   SendeDaten.DataField.A[47] := ' '; 
   SendeDaten.DataField.A[48] := ' '; 
   SendeDaten.DataField.A[49] := ' '; 
   SendeDaten.DataField.A[50] := ' '; 
   SendeDaten.DataField.A[51] := ' '; 
   SendeDaten.DataField.A[52] := ' '; 
   SendeDaten.DataField.A[53] := ' '; 
   SendeDaten.DataField.A[54] := ' '; 
   SendeDaten.DataField.A[55] := ' '; 
   MsgLen := 0; 
   End.ETX := B#16#3; 
   End.Checksum1 := B#16#0; 
   End.Checksum2 := B#16#39; 
   End.Checksum3 := B#16#32; 
   End.Checksum4 := B#16#39; 
   End.EOT := B#16#4; 
   Text1 := 'Gehaeuse bereitstellen'; 
   Text2 := 'Noch ein Text'; 
END_DATA_BLOCK

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank für die Anregung und den Code, habe es probiert und es funkt ! Jetzt geht es aber weiter. Das zu beschreibende Textdisplay hat 4 Zeilen, die 1ste und 2te Zeile fassen max je 13 Zeichen. Die 3te und 4te Zeile fassen je max 50 Zeichen und werden im Textdisplay zur Laufschrift sobald die Zeichenfolge >13 Zeichen wird, arrangiert das Textdisplay jedoch selbst.
Es sollen variable Texte in die 4 Zeilen gesendet werden, heisst, trifft ein neuer Text ein, müssen die anderen Texte erhalten bleiben und der neue Text muß überschrieben werden. Dies hat zur Folge das die zu erhaltenen Texte zwischengespeichert werden müssen, der neue Text für entweder Zeile 1, 2, 3, oder 4 ins Protokoll eingetragen werden muß, wie auch die unverändert gebliebenen Texte. Nun kann aber die Textlänge des neu eingetroffenen Textes kürzer oder länger sein als der zu überschreibende Text, was bedeutet, daß das neu zu übertragende Protokoll entsprechend automatisch angepasst werden muß. Es kann kürzer oder länger werden, je nach Anzahl der Zeichenfolge. Habe jedoch keine Ahnung wie dies realisiert werden könnte. Kann mir vorstellen das dies in SCL einfacher zu machen ist als in AWL, jedoch reichen meine Kenntnisse in beiden Fällen nicht aus um diese Herausforderung zu meistern. Kann mir jemand einen Code hierfür zur Verfügung stellen ?
Habe eine 319F mit CP zur Verfügung, Kommunikation erfolgt via Ethernet zum Textdisplay. Für die hilfreichen Antworten edanke ich mich schon im voraus.
Mfg Dieter
 
Zurück
Oben