Step 7 TCP erbindung mit SCL

emilio20

Level-1
Beiträge
835
Reaktionspunkte
20
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo
ich habe Arduino mit dem ich eine TCP Verbindung aufbauen möchte.
Mit dem Siemens Beispiel funktioniert die Verbindung .
http://support.automation.siemens.c...objaction=csview&extranet=standard&viewreg=WW

Nun wollte ich in SCL eine Programm mit TCP Verbindung erstellen. Hierzu habe ich das vorhandnen NET_IO Programm abgeändert.
Leifer Funktioniert die Verbindung hiermit nicht. Kann mir jemand sagen was ich falsch mache ?
Code:
TYPE UDT_ARDUINO_IO 
NAME    : Arduino
FAMILY  : ''
AUTHOR  : xxx
VERSION : 1.0
   
 STRUCT
  VALVE :ARRAY[1..19] OF INT;
             
 END_STRUCT
END_TYPE


//**********************************************FB ARDUINO*******************************************************************************
FUNCTION_BLOCK ARDUINO
TITLE = 'Arduino'
NAME    : Arduino
FAMILY  : ''
AUTHOR  : Zehe
VERSION : '1.0'

VAR_INPUT
  CONNECT : BOOL;
  ID : WORD;  
  DEV_ID : BYTE;  
  IP_ADDR1 : INT;  
  IP_ADDR2 : INT;  
  IP_ADDR3 : INT;  
  IP_ADDR4 : INT;  
  LOC_PORT :DINT;
  REM_PORT :DINT;
END_VAR
VAR_IN_OUT
  ARDUINO_IO : UDT_ARDUINO_IO;
END_VAR  
VAR_OUTPUT
  CONNECTED : BOOL;
END_VAR    
VAR_TEMP
  TempPointer : ANY;
  AnyPointer AT TempPointer : STRUCT
    BYTE0 : BYTE; //10h
    TYP : BYTE;   //Daten/Parametertyp
    ANZ : WORD;   //Länge
    DBNr : WORD;  //DB-Nummer
    BZ : DWORD;   //Bereichszeiger
  END_STRUCT;
  i : INT;
  BCD_Code : DWORD;
END_VAR
VAR
  TCON : TCON;
  TSEND : TSEND;
  TRCV : TRCV;
  TDISCON : TDISCON;
  TCON_PAR : TCON_PAR;
  TON_CON : TON;
  TON_SEND : TOF;
  PulsePosConn : BOOL;   
  PulseNegConn : BOOL;   
  EdgeFlagPos : BOOL;
  EdgeFlagNeg : BOOL;
  Count : INT;
  RcvData : ARRAY[0..23] OF CHAR;
  GETVALVE: ARRAY[0..12] OF CHAR :=  'G','E','T','V','A','L','V','E',' ','X','X','$L', '$R';

END_VAR

BEGIN

(*********************************************************)    
(* Get the positive pulse                                *)
(*********************************************************)    

  PulsePosConn := CONNECT AND NOT EdgeFlagPos;
  EdgeFlagPos := CONNECT;

(*********************************************************)    
(* Get the negative pulse                                *)
(*********************************************************)    

  PulseNegConn := NOT CONNECT AND EdgeFlagNeg;
  EdgeFlagNeg := CONNECT;

(*********************************************************)    
(* Set ID of the specified connection                    *)
(*********************************************************)

  TCON_PAR.id := ID;
  TCON_PAR.local_device_id := DEV_ID;

(*********************************************************)    
(* Set IP address values                                 *)
(*********************************************************)    

  TCON_PAR.rem_staddr[1] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR1));
  TCON_PAR.rem_staddr[2] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR2));
  TCON_PAR.rem_staddr[3] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR3));
  TCON_PAR.rem_staddr[4] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR4));
  //Port local Port
  TCON_PAR.local_tsap_id[2] :=B#16#0;//WORD_TO_BYTE(DINT_TO_WORD(LOC_PORT));
  TCON_PAR.local_tsap_id[1] :=B#16#0;//WORD_TO_BYTE(SHR(IN:=DINT_TO_WORD(LOC_PORT),N:=8));
  TCON_PAR.local_tsap_id_len:=B#16#0;//B#16#2;
 //Port REM Port
  TCON_PAR.rem_tsap_id[2] :=WORD_TO_BYTE(DINT_TO_WORD(REM_PORT));
  TCON_PAR.rem_tsap_id[1] :=WORD_TO_BYTE(SHR(IN:=DINT_TO_WORD(REM_PORT),N:=8));
  TCON_PAR.rem_tsap_id_len:=B#16#2;
  // Set leagth of the IP address
  TCON_PAR.rem_staddr_len := B#16#4;
  

(*********************************************************)    
(* Establish connection                                  *)
(*********************************************************)    

  IF PulsePosConn THEN
    TCON.REQ := TRUE;
  END_IF;  
  
  TCON(REQ     := TCON.REQ,
       ID      := TCON_PAR.id,
       CONNECT := TCON_PAR);
      
  IF TCON.DONE THEN
    CONNECTED := TRUE;
    TCON.REQ := FALSE;
  END_IF;
  
  TON_CON(IN := CONNECTED,
          PT := T#2s); 
   
(*********************************************************)
(*********************************************************)

  CASE Count OF
      1..9:    GETVALVE[9]  := INT_TO_CHAR(0 + 48);
               GETVALVE[10] := INT_TO_CHAR(Count + 48);
               TempPointer := GETVALVE;

      10..19:
               GETVALVE[9]  := INT_TO_CHAR(1 + 48);
               GETVALVE[10] := INT_TO_CHAR(Count-10 + 48);
               TempPointer := GETVALVE;

    
     
  ELSE
    Count := 1;
  //  TempPointer := GETSTATUS;
  END_CASE;      

(*********************************************************)
(* Send data over existing connection                    *)    
(*********************************************************) 

  TSEND.LEN := WORD_TO_INT(AnyPointer.ANZ);

  IF TON_CON.Q THEN
    
    TON_SEND(IN := NOT TSEND.REQ,
             PT := T#50ms);
              
    TSEND.REQ := TON_SEND.Q; 
    
    TSEND(REQ  := TSEND.REQ,
          ID   := TCON_PAR.id,
          LEN  := TSEND.LEN, 
          DATA := TempPointer);

  END_IF; 

(*********************************************************)
(* Receive data over existing connection                 *)    
(*********************************************************)    

  IF CONNECTED THEN

    TRCV(EN_R := TRUE,
         ID   := TCON_PAR.ID,
         LEN  := TRCV.LEN,
         DATA := RcvData); 
     
  END_IF;
  
  BCD_Code := 0;
  
  IF TRCV.NDR THEN
    CASE Count OF
        
                
    
      1..19: IF CHAR_TO_INT(RcvData[0]) >= 48 AND CHAR_TO_INT(RcvData[0]) <= 57 THEN
                BCD_Code := WORD_TO_DWORD(INT_TO_BCD(CHAR_TO_INT(RcvData[0]) - 48)); 
              END_IF;
              IF CHAR_TO_INT(RcvData[1]) >= 48 AND CHAR_TO_INT(RcvData[1]) <= 57 THEN
                BCD_Code := SHL(IN:=BCD_Code, N:=4);
                BCD_Code := BCD_Code OR WORD_TO_DWORD(INT_TO_BCD(CHAR_TO_INT(RcvData[1]) - 48));
              END_IF;  
              IF CHAR_TO_INT(RcvData[2]) >= 48 AND CHAR_TO_INT(RcvData[2]) <= 57 THEN
                BCD_Code := SHL(IN:=BCD_Code, N:=4);
                BCD_Code := BCD_Code OR WORD_TO_DWORD(INT_TO_BCD(CHAR_TO_INT(RcvData[2]) - 48));
              END_IF;  
              IF CHAR_TO_INT(RcvData[3]) >= 48 AND CHAR_TO_INT(RcvData[3]) <= 57 THEN
                BCD_Code := SHL(IN:=BCD_Code, N:=4);
                BCD_Code := BCD_Code OR WORD_TO_DWORD(INT_TO_BCD(CHAR_TO_INT(RcvData[3]) - 48));
              END_IF;  
              ARDUINO_IO.VALVE[Count] := DINT_TO_INT(DWORD_BCD_TO_DINT(BCD_Code));
                   
              
              
    END_CASE;
    
    Count := Count + 1;
    
    FOR i := 0 TO 23 DO
      RcvData[i] := ' ';
    END_FOR;      
  END_IF;
  
(*********************************************************)    
(* Existing connection end                               *)
(*********************************************************)    

  IF PulseNegConn AND CONNECTED THEN
    TDISCON.REQ := TRUE;
  END_IF;  
  
  TDISCON(REQ := TDISCON.REQ,
          ID  := TCON_PAR.id); 
      
  IF TDISCON.DONE THEN
    CONNECTED := FALSE;
    TDISCON.REQ := FALSE;
    Count := 1;
  END_IF;

END_FUNCTION_BLOCK
 
Zuletzt bearbeitet:
Hallo habe den fehler gefunden actic war nicht auf True.

kann mir jemand erklären was im Char $L und $R Bedeuten ?
 
Ich sehe keinerlei Fehlerbehandlung in deinem Baustein.
Was macht der Baustein, wenn Done nicht kommt, sondern Error, weil z.Bsp. die Verbindung getrennt wurde?
 
Hallo
ich bin kein TCP Fachmann. Habe bis jetzt nur mit dem Siemens Beispiel und dem AVR net io Programm gearbeitet.

Was müsste deiner Meinung nach noch eingebaut werden?


Habe folgendes Problem über das Simatic Beispiel TCP erhalte ich am Arduino immer einen sauber empfangenen String. (siehe Bild TCP 1)
Über mein Programm erhalte ich Fehler( siehe Bild TCP 2)
 

Anhänge

  • tcp1.JPG
    tcp1.JPG
    29,5 KB · Aufrufe: 50
  • tcp2.JPG
    tcp2.JPG
    39,2 KB · Aufrufe: 72
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Über mein Programm erhalte ich Fehler( siehe Bild TCP 2)

"Fehler" ist gut. Was fehlt denn? Die Verbindung wird aufgebaut und der RECV empfängt auch etwas? Kein ERROR Bit an SEND/RECV?
Wenn doch, STATUS damit umkopieren.

So spontan behaupte ich, dass Zeile 180 ein Problem ist:
Code:
LEN  := TRCV.LEN
TRCV.LEN ist nicht initialisiert und müsste hier 24 sein, so groß wie der Empfangsbereich ist.
(Die echte Empfangslänge liegt in TRCV.TRCV_LEN)
 
Hallo
Verbindung OK
kein Fehler siehe Anhang

Am len liegt es nicht wenn ich 24 rein schreibe müssen 24 Byte zurück kommen bis der conter weiter läuft. Senn also eine char '0' die Antwort ist dauert es bis TRCV.NDR = TRUE
Mir ist aufgefallen wenn ich den Sendezyklus schnelle als 1s mache geht garnichts mehr.
 

Anhänge

  • tcp3.JPG
    tcp3.JPG
    140,6 KB · Aufrufe: 38
Zuletzt bearbeitet:
TSend hat u.a. einen Ausgang "Busy", und ein "Done". Senden wird gestartet, wenn am Req-Eingang ein Signalwechsel von False auf True erkannt wird. Du darfst erst wieder ein Send-Request auslösen, wenn der vorherige Sendevorgang fertig ist. Schau dir noch einmal das Siemens-Beispiel an, da wird ein Send-Request gesetzt und der wird erst wieder zurückgesetzt, wenn "Done" oder "Error" vom Send-Baustein zurückkommt. Erst dann wir ein neues Send ausgelöst.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Am len liegt es nicht wenn ich 24 rein schreibe müssen 24 Byte zurück kommen bis der conter weiter läuft.

//edit
Im DB wirst du niemals einen Fehlerstatus sehen, weil der nur einen einzigen Zyklus lang ansteht.
> Mit dem Error Bit STATUS umkopieren.
 
Zuletzt bearbeitet:
Hallo das mit dem empfangspuffer ist glaube ich nicht das Problemm. Ist im Siemens Beispiel auch so. Es kann sein das ich 2 Byte 4 Byte oder 10 Byte emfangen. Woher weiß ich wieviel grade gesendet werden ?
 
Hallo Leute,
ich habe mir vom Themenstarter mal ein bisschen was gemopst. das Ganze sieht Auszugsweise so aus.

//Eingangsparameter
VAR_INPUT
CONNECT :BOOL;
RESET :BOOL;
ID :WORD;
DEV_ID :BYTE;
IP_ADDR1 :INT;
IP_ADDR2 :INT;
IP_ADDR3 :INT;
IP_ADDR4 :INT;
LOC_PORT :DINT;
REM_PORT :DINT;
END_VAR


//Ausgangsparameter
VAR_OUTPUT
CONNECTED :BOOL;
CON_ERROR :BOOL;
SEND_DONE :BOOL;
SEND_ERROR :BOOL;
END_VAR


//temporäre Variable

TempPointer : ANY;
AnyPointer AT TempPointer : STRUCT
BYTE0 : BYTE; //10h
TYP : BYTE; //Daten/Parametertyp
ANZ : WORD; //Länge
DBNr : WORD; //DB-Nummer
BZ : DWORD; //Bereichszeiger
END_STRUCT;
END_VAR


//Variablen
VAR

TCON : TCON;
TSEND : TSEND;
TDISCON : TDISCON;
TCON_PAR : TCON_PAR;
TON_CON : TON;
TON_SEND : TOF;
END_VAR

//ID für die Verbindung setzen
TCON_PAR.id := ID;
TCON_PAR.local_device_id := DEV_ID;


//IP Adresse festlegen
TCON_PAR.rem_staddr[1] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR1));
TCON_PAR.rem_staddr[2] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR2));
TCON_PAR.rem_staddr[3] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR3));
TCON_PAR.rem_staddr[4] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR4));
//Port local Port
TCON_PAR.local_tsap_id[2] :=B#16#0;//WORD_TO_BYTE(DINT_TO_WORD(LOC_PORT));
TCON_PAR.local_tsap_id[1] :=B#16#0;//WORD_TO_BYTE(SHR(IN:=DINT_TO_WORD(LOC_PORT),N:=8));
TCON_PAR.local_tsap_id_len:=B#16#0;//B#16#2;
//Port REM Port
TCON_PAR.rem_tsap_id[2] :=WORD_TO_BYTE(DINT_TO_WORD(REM_PORT));
TCON_PAR.rem_tsap_id[1] :=WORD_TO_BYTE(SHR(IN:=DINT_TO_WORD(REM_PORT),N:=8));
TCON_PAR.rem_tsap_id_len:=B#16#2;
//Set length of the IP address
TCON_PAR.rem_staddr_len := B#16#4;
//Aktive Verbindung
TCON_PAR.active_est := true;




//Datenkommunikation Reset


IF RESET THEN TCON.REQ := FALSE; TSEND.REQ := FALSE; TSEND.ERROR := FALSE ;
END_IF;


//Datenverbindung aufbauen


IF CONNECT AND NOT CONNECTED AND NOT RESET THEN
TCON.REQ := TRUE;
END_IF;


TCON(REQ := TCON.REQ,
ID := TCON_PAR.id,
CONNECT := TCON_PAR);

IF TCON.DONE THEN
CONNECTED := TRUE;
TCON.REQ := FALSE;
END_IF;


IF TCON.ERROR THEN CON_ERROR := TRUE;
ELSE CON_ERROR := FALSE;
END_IF;


TON_CON(IN := CONNECTED,
PT := T#1s);


// Daten senden


//Anypointer.Byte0 := B#16#2; //BYTE0
Anypointer.DBNr := w#16#64; //DB100 (als Wort)
Anypointer.BZ := DW#16#8400_00D0; //DBX26.0 (DBX26.0 = Bereichskennung 16#84 und 26 * 8 ---> DW#16#840000D0)
Anypointer.Anz := w#16#1c; //28 (als Wort)
Anypointer.Typ := B#16#2; //BYTE




TSEND.LEN := WORD_TO_INT(AnyPointer.ANZ);


IF (CONNECTED AND TON_CON.Q) AND NOT TSEND.DONE AND NOT RESET THEN

TON_SEND(IN := NOT TSEND.REQ,
PT := T#250ms);


TSEND.REQ := TON_SEND.Q;

TSEND(REQ := TSEND.REQ,
ID := TCON_PAR.id,
LEN := TSEND.LEN,
DATA := TempPointer);
END_IF;

IF TSEND.DONE THEN SEND_DONE:= TRUE;
END_IF;

IF TSEND.ERROR AND CONNECTED THEN SEND_ERROR := TRUE;
ELSE SEND_ERROR :=FALSE;
END_IF;


//Verbindung schließen


IF (TSEND.DONE AND CONNECTED) OR (RESET AND CONNECTED) THEN
TDISCON.REQ := TRUE;
END_IF;

TDISCON(REQ := TDISCON.REQ,
ID := TCON_PAR.id);

IF TDISCON.DONE THEN
CONNECTED := FALSE;
SEND_DONE := FALSE;
TDISCON.REQ := FALSE;
END_IF;

END_FUNCTION_BLOCK


So, im Grunde genommen habe ich in dem Bereich des FB DBs den ich verschicken möchte einen String stehen mit 28 Zeichen. Dieser String wird in diesem FB auch durch verschiedene Eingangsparameter gebildet.
Wenn ich das Ganze in einem FC mit KOP aufbaue funktioniert das mit dem Senden auch und der String kommt korrekt an.
In SCL bekomme ich jedoch jedes mal einen Sendefehler. Ich finde das Problem einfach nicht.

MFG
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kann es gerade nicht nachstellen ... aber folgendes dazu :
In einer vergleichbaren Problemstellung habe ich es bislang so gehandhabt, dass ich den String in dem FB gebildet habe (der String war auch ein Teil der Instanz des FB). Nun habe ich der AnyPointer-Variablen der String zugewiesen (dadurch baut sich SCL selbstständig den korrekten Pointer) und den dann dem TSend übergeben.
Vielleicht versuchst du das auch mal ...

Ansonsten ... welchen Sendefehler bekommst du denn (und hast du mal nachgesehen, was der bedeutet) ?

Gruß
Larry
 
Ok, hab ich ausprobiert. Wenn ich dem TempPointer den String den ich in diesem FB bilde zuweise klappt es mit dem Senden. Muss ich mal schaun ob ich so weiterarbeiten kann.
Vielen Dank für den Tipp, hat mir sehr weitergeholfen :)

PS: Den Sendefehler den ich vorher bekommen hatte war ein 887F (
Interner Fehler)
 
Wenn ich das Ganze in einem FC mit KOP aufbaue funktioniert das mit dem Senden auch und der String kommt korrekt an.
In SCL bekomme ich jedoch jedes mal einen Sendefehler. Ich finde das Problem einfach nicht.
Dann schau mal: Was machst Du in KOP anders?
Vermutlich bastelst Du da keinen ANY zusammen sondern gibst den Sendestring an TSEND symbolisch an - kannst Du den nicht auch in SCL symbolisch angeben oder als INPUT an Deinen FB übergeben?
Wenn Du einen ANY zusammenbastelst, dann mußt Du den ANY auch komplett zusammenbasteln - in Deinem Code fehlt die Initialisierung des "Anypointer.BYTE0" mit der ANY-Syntax-ID 16#10.

(der "Sendestring" ist vermutlich kein STRING, sondern ein BYTE-Array oder CHAR-Array?)


*Kritik*
Warum mußt Du den in KOP funktionierenden Code in SCL umbauen? War KOP nicht chic genug? ;) SCL verleitet Dich nur zu schlechtem Code:
- OUTPUTs nur manchmal etwas zuweisen sowie OUTPUTs zurücklesen (sogar noch vor der ersten Zuweisung!) ist ziemlich pfui (auch bei FB)
- auch wenn es in SCL möglich ist, relativ ahnungslos schnell eine IF-Wüste zusammenzutippseln, so sollten solche Konstrukte trotzdem nicht passieren:
Code:
[COLOR="#008000"]//sowas verursacht Augenkrebs, dient nur der unnötigen Verkomplizierung:[/COLOR]
 IF TCON.ERROR THEN CON_ERROR := TRUE;
ELSE CON_ERROR := FALSE;
    END_IF;

[COLOR="#008000"]//dies hier tut das gleiche und ist in 1 Sekunde verstehbar:[/COLOR]
CON_ERROR := TCON.ERROR;
- Instanz-Eingänge und -Ausgänge außerhalb des Instanz-Aufrufs direkt manipulieren und abfragen und dann die Instanz so aufrufen, sieht nicht besonders planvoll aus:
Code:
    TSEND(REQ  := [COLOR="#FF0000"]TSEND.REQ[/COLOR],
          ID   := TCON_PAR.id,
          LEN  := [COLOR="#FF0000"]TSEND.LEN[/COLOR], 
          DATA := TempPointer);
- die unnötige Verwendung von hexadezimalen Zahlenwerten statt dezimalen Zahlenwerten erhöht den Unverständlichkeitsgrad und die Fehleranfälligkeit des Programmcodes
Code:
//Anypointer.Byte0 := B#16#2;          //BYTE0
Anypointer.DBNr := w#16#64;         //DB100 (als Wort)
Anypointer.BZ := DW#16#8400_00D0;   //DBX26.0      (DBX26.0 = Bereichskennung 16#84 und 26 * 8 ---> DW#16#840000D0)
Anypointer.Anz := w#16#1c;          //28 (als Wort)
Anypointer.Typ := B#16#2;           //BYTE

[COLOR="#008000"]//besser:[/COLOR]
[COLOR="#008000"]//ANY: P#DB100.DBX26.0 BYTE 28[/COLOR]
Anypointer.BYTE0 := B#16#10;        //Syntax-ID für ANY
Anypointer.DBNr  := 100;            //DB100
Anypointer.BZ := DW#16#8400_0000 OR INT_TO_DWORD(26*8); //DBX26.0 = Bereichskennung 16#84 und 26 * 8
Anypointer.Anz := 28;               //28
Anypointer.Typ := B#16#2;           //BYTE

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Morgen Leute,

also ich hab es inzwischen hinbekommen :) so sieht der geistige Erguss jetzt aus:

Code:
//***********************************************************************************************Datenverbindung***********************************************************************************************

//positive Flanke für Reset--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PulsePosRes := RESET AND NOT EdgeFlagPosRes;
EdgeFlagPosRes := RESET;


//ID für die Verbindung setzen--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TCON_PAR.id := ID;
TCON_PAR.local_device_id := DEV_ID;


//IP Adresse festlegen--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TCON_PAR.rem_staddr[1] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR1));
TCON_PAR.rem_staddr[2] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR2));
TCON_PAR.rem_staddr[3] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR3));
TCON_PAR.rem_staddr[4] := WORD_TO_BYTE(INT_TO_WORD(IP_ADDR4));
//Port local Port--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TCON_PAR.local_tsap_id[2] :=B#16#0;                                 //WORD_TO_BYTE(DINT_TO_WORD(LOC_PORT));
TCON_PAR.local_tsap_id[1] :=B#16#0;                                 //WORD_TO_BYTE(SHR(IN:=DINT_TO_WORD(LOC_PORT),N:=8));
TCON_PAR.local_tsap_id_len:=B#16#0;                                 //B#16#2;
//Port REM Port--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TCON_PAR.rem_tsap_id[2] :=WORD_TO_BYTE(DINT_TO_WORD(REM_PORT));
TCON_PAR.rem_tsap_id[1] :=WORD_TO_BYTE(SHR(IN:=DINT_TO_WORD(REM_PORT),N:=8));
TCON_PAR.rem_tsap_id_len:=B#16#2;
//Set length of the IP address--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TCON_PAR.rem_staddr_len := B#16#4;
//Aktive Verbindung--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TCON_PAR.active_est := true;




//Datenkommunikation Reset--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IF PulsePosRes THEN 
    CONNECT := FALSE;
    Connected := FALSE;    
    TCON.REQ := FALSE; 
    TCON.ERROR := FALSE;
    TSEND.REQ := FALSE; 
    TSEND.ERROR := FALSE; 
    TSEND.DONE :=FALSE;
    Stoe := FALSE;
    END_IF;


//Datenverbindung aufbauen--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


  TCON.REQ :=   CONNECT_TON.Q AND NOT 
                Connected AND NOT
                TCON.Busy AND NOT 
                RESET;


  TCON(REQ     := TCON.REQ,                                 //Daten für den Verbindungsaufbau
       ID      := TCON_PAR.id,                              //
       CONNECT := TCON_PAR);                                //
      
  IF TCON.DONE THEN
    Connected := TRUE;
    TCON.REQ := FALSE;
    CONNECT := FALSE;
  END_IF;
  
  TON_CON(IN := Connected,
          PT := T#250ms);


// Daten senden Telegram--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TempPointerSend := SENDE_STRING;                                            //Pointer String zuweisen
SendPointer.DBNr := INT_TO_WORD(DB_Nummer);                                 //DB100 (als Wort) Instanz-DB Nummer wird automatisch ermittelt
SendPointer.BZ := DW#16#8400_0000 OR (INT_TO_WORD((DB_Offset + 2)*8));      //DW#16#8400_0280; DBX80.0 (DBX80.0 = Bereichskennung 16#84 und 80 * 8 ---> DW#16#84000280) Bereichszeiger wird automatisch ermittelt
SendPointer.Anz := INT_TO_WORD (LEN (SENDE_STRING));                        //Anzahl Stringzeichen als Wort
SendPointer.Typ := B#16#2;                                                  //BYTE


TSEND.LEN := WORD_TO_INT(SendPointer.ANZ);                                  //Sendelänge bestimmen


  IF TON_CON.Q AND NOT TSEND.DONE AND NOT RESET THEN
    
    TON_SEND(IN := NOT TSEND.REQ,
             PT := T#250ms);
    
    TSEND.REQ := TON_SEND.Q; 
END_IF;
 
    TSEND(REQ  := TSEND.REQ,                                    //Daten Senden
          ID   := TCON_PAR.id,                                  //
          LEN  := TSEND.LEN,                                    // 
          DATA := TempPointerSend);                             //
   
//Verbindung schließen--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  TDISCON.REQ := (TSEND.DONE AND Connected) OR (RESET AND Connected); 
  
  TDISCON(REQ := TDISCON.REQ,
          ID  := TCON_PAR.id); 
      
  IF TDISCON.DONE THEN
    Connected := FALSE;
    TSEND.DONE :=FALSE;
    TDISCON.REQ := FALSE;
END_IF;

Vielen Dank für die Hilfe!!
 
also ich hab es inzwischen hinbekommen :) so sieht der geistige Erguss jetzt aus:

Code:
[...]
[COLOR="#FF0000"]TempPointerSend := SENDE_STRING;[/COLOR]                                            //Pointer String zuweisen
[...]
SendPointer.Anz := INT_TO_WORD ([COLOR="#FF0000"][/COLOR][COLOR="#FF0000"]LEN (SENDE_STRING)[/COLOR]);                        //Anzahl Stringzeichen als Wort
[...]
[COLOR="#FF0000"]TSEND.LEN[/COLOR] := WORD_TO_INT([COLOR="#FF0000"]SendPointer.ANZ[/COLOR]);                                  //Sendelänge bestimmen
[...]
    TSEND([COLOR="#FF0000"]REQ  := TSEND.REQ,[/COLOR]                                    //Daten Senden
          ID   := TCON_PAR.id,                                  //
          [COLOR="#FF0000"]LEN  := TSEND.LEN,[/COLOR]                                    // 
          DATA := [COLOR="#FF0000"]TempPointerSend[/COLOR]);                             //
Morgen Azrael666,
mit "hinbekommen" meinst Du lediglich, daß der Quellcode nun ohne Fehler übersetzt wird und in der CPU keinen STOP verursacht :cool: - oder hast Du auch getestet was Dein Code tut?
Nach dem Motto "Liebe Kinder, bitte nicht nachmachen!" ;) schau Dir z.B. mal die von mir rot markierten Programmstellen genauer an.

Harald
 
Morgen Azrael666,
mit "hinbekommen" meinst Du lediglich, daß der Quellcode nun ohne Fehler übersetzt wird und in der CPU keinen STOP verursacht :cool: - oder hast Du auch getestet was Dein Code tut?
Nach dem Motto "Liebe Kinder, bitte nicht nachmachen!" ;) schau Dir z.B. mal die von mir rot markierten Programmstellen genauer an.

Harald

:) also mit hinbekomme meinte ich, dass sich der Quellcode übersetzen lässt, die CPU nicht im Stop ist und, das wichtigste, das Ganze sogar funktioniert und meinen String als Telegram verschickt.

;) ich hab jetzt mit SCL noch nicht so viel Erfahrung als dass mir die roten Markierungen in irgendeiner Weise weiterhelfen, bzw ich sehe nicht was daran falsch sein sollte.
( evtl. ist das Doppeltgemoppelt was ich da zuweise?? )
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hast Du mal verglichen was Du senden willst und was beim Empfänger ankommt - ob das exakt das gleiche ist?
Tip:
- Du sendest einen STRING inklusive des String-Headers, aber 2 Zeichen kürzer als der String lang ist - ist das wirklich so gewollt?
- die anderen roten Markierungen TSEND.x zeigen Zuweisungen von Variablen auf sich selber - ein deutliches Zeichen von Ahnungslosigkeit des Programmierers. Du solltest Dich entscheiden, ob Du die TSEND-/TCON-Aufrufparameter lieber an vielen verstreuten Stellen außerhalb des Instanz-Aufrufs direkt manipulierst oder übersichtlich beim Instanz-Aufruf. Bei Ersterem lasse die nochmalige Zuweisung der Instanz-Aufrufparameter beim Aufruf weg.

Harald
 
Also eigentlich sollte der STRING ohne Header verschickt werden. Ich hab den Code nochmal ein bisschen angepasst.

Code:
TempPointerSend := SENDE_STRING;                                            //Pointer String zuweisenSendPointer.DBNr := INT_TO_WORD(DB_Nummer);                                 //DB100 (als Wort) Instanz-DB Nummer wird automatisch ermittelt
SendPointer.BZ := DW#16#8400_0000 OR (INT_TO_WORD((DB_Offset + 2)*8));      //DW#16#8400_0280; DBX80.0 (DBX80.0 = Bereichskennung 16#84 und 80 * 8 ---> DW#16#84000280) Bereichszeiger wird automatisch ermittelt
SendPointer.Anz := INT_TO_WORD (LEN (SENDE_STRING));                        //Anzahl Stringzeichen als Wort
SendPointer.Typ := B#16#2;                                                  //BYTE
                             
  IF TON_CON.Q AND NOT TSEND.DONE AND NOT RESET THEN
    
    TON_SEND(IN := NOT TSEND.REQ,
             PT := T#250ms);   
END_IF;
 
    TSEND(REQ  := TON_SEND.Q,                                    //Daten Senden
          ID   := TCON_PAR.id,                                  //
          LEN  := WORD_TO_INT(SendPointer.ANZ),                 // 
          DATA := TempPointerSend);                             //

Mit dem DB_Offset ermittle ich die Stelle an der der SENDE_STRING im DB steht und verschiebe diesen Bereich dann um 2 Byte um den Header weg zu bekommen
Dafür ist doch der SendPointer.BZ da oder?

Als kleine Entschuldigung, ich hab bis jetzt nur KOP programmiert. SCL ist aktuell "Neuland" für mich.
 
... dann will ich mal auch meckern (nicht immer nur der Harald) :
Du kannst es dir auch unnötig kompliziert machen.
Wenn du auf deinen SendeString eine AT-Sicht machst, die die Header und die Nutzdaten separiert (also z.B. eine Struktur mit Header:word und Daten:array[1..20] of Byte) dann könntest du schlicht und einfach dem ANY-Pointer den Datenteil deiner Struktur übergeben und du müßtest nicht manipulieren (was m.E. so sowieso nicht korrekt ist).

Gruß
Larry


und Nachsatz:
Wenn man das schön benennt dann steigt vielleicht auch später mal noch jemand da durch ...
 
Zurück
Oben