Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 9 von 9

Thema: Probleme beim Übertragen mit der Funktion Put/Get (SFB14/15 bzw. FB14/15) via SCL

  1. #1
    Registriert seit
    01.03.2013
    Beiträge
    6
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Frage


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo liebe Forum-Gemeinde,

    bin neu hier und möchte mich erstmal für zahlreiche Infos bedanken.
    Leider stehe ich vor einem Problem, bei welchem ich alleine nicht weiter komme Google und Co. auch nichts brachbares finden.

    Ich möchte eine Datenkommunikation via Profinet zwischen einer ET200S und einer 315-PN/DP aufbauen.
    Es soll von der ET200S ein teil eines Datenbausteins DB300 an die 315 übertragen werden.
    Der DB300 ist 12Byte gross. Davon sollen die ersten 8Byte gesendet (put) und die letzen 4 Byte empfangen (get) werden.

    Nun habe ich mit der Siemens-"Hilfe" den Anypointer und die Übertragung im SCL zum Laufen bekommen..

    ABER....

    Hier kommt mein Problem
    Ich muss bei der Übertragung immer die ganzen 12Byte übertragen. Sobald ich nur die ersten zwei oder vier Byte übertragen möchte, bringt die Funktion den Status 4 als Fehlermeldung. Und meine Funktion möchte dann wieder neu Senden/bzw. empfangen. Doch mit dem Status 4 kann ich mit der Siemens-"Hilfe" nichts anfangen...

    Hier mal meinen prinzipiellen Aufbau des SCL codes:

    Teile der Input/Parameter (NICHT Vollständig!!)
    VAR_INPUT
    I_Int_ADDR_1: ANY; // Interne Adresse des DB´s "Symbolisch"
    I_ID: WORD; // ID-Nummer der externen Steuerung
    I_DB_Nr: INT; // Nummer des DBs
    I_DB_Byte_Adr: INT; // Bereichszeiger auf Bit- und BYTE-Adresse
    I_Byte_Count: INT; // Anzahl der Byte
    END_VAR

    VAR
    Get_Data: "GET"; //"FB_Get"; // Struktur von FB14 "Get" in Instanz DB (GET=SFB 14 FB_Get=FB14)
    Put_Data: "PUT"; //"FB_Put"; // Struktur von FB15 "Put" in Instanz DB (PUT=SFB 15 FB_Put=FB15)

    Get_Impuls: BOOL; // Startimpuls DB empfangen
    Put_Impuls: BOOL; // Startimpuls DB senden
    END_VAR

    VAR_TEMP
    Buffer: "UDT_ANY_Pointer"; // Zwischenspeicher für Pointer
    Temp_Any_Pointer AT Buffer: ANY; // Any-Pointer
    END_VAR




    //Teile des SCL Codes
    //======================================
    // Any Pointer deklarieren
    //======================================
    Buffer.Syntax_ID := b#16#10; //Pufferlänge
    Buffer.DataTyp := b#16#02; //Code für Datentyp BYTE
    Buffer.Count := INT_TO_WORD(AnzahlBytes); //Anzahl der Nutzdaten-Byte
    Buffer.DB_Number := INT_TO_WORD(300); //Nummer des Ziel-DBs für die Nutzdaten
    Buffer.Byte_Pointer := dw#16#84000000; //Pointer auf Globaldaten DBX0.0

    //Byte-Adresse in Pointer laden
    //Buffer.Byte_Pointer:= Buffer.Byte_Pointer OR (SHL(in:=WORD_TO_DWORD(INT_TO_WORD(StartByte)),N:=3));;

    Schritt := Schritt;
    //======================================
    // Function"Get": DB receive
    //======================================
    Get_Data(REQ := Get_Impuls // DB empfangen
    ,ID := I_ID // ID-Nummer der externen Steuerung
    ,ADDR_1 := Temp_Any_Pointer //Temp_Any_Pointer // Externe Adresse des DB´s
    ,RD_1 := I_Int_ADDR_1); // Interne Adresse des DB´s

    //======================================
    // Function "Put": DB send
    //======================================
    Put_Data(REQ := Put_Impuls // DB senden
    ,ID := I_ID // ID-Nummer der externen Steuerung
    ,ADDR_1 := Temp_Any_Pointer // Externe Adresse des DB´s
    ,SD_1 := I_Int_ADDR_1); // Interne Adresse des DB´s


    Habe is mit den SFC und den FC aus der Siemens Bibliotek versucht. Beides läuft nur wenn ich immer den ganzen DB übertrage. Ich möchte aber nur einen Teil senden und einen anderen Teil empfangen..

    Mache ich was falsch, oder wo könnte der Fehler sein?

    Besten dank schonmal..

    Grüsse
    Zitieren Zitieren Probleme beim Übertragen mit der Funktion Put/Get (SFB14/15 bzw. FB14/15) via SCL  

  2. #2
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.218
    Danke
    533
    Erhielt 2.696 Danke für 1.948 Beiträge

    Standard

    Du holst die Daten und sendest die selben Daten zurück.
    Wie machst du das, wenn du unterschiedliche Bereiche senden/empfangen willst?
    Dann mußt du Put und Get auch mit unterschiedlichen Adressen versorgen.

    Also von dir aus 8 Byte per Put an die entfernte SPS, Byte 0-7 und 4 Byte per Get holen, Byte 8-11.
    Demnach müssen deine je 2 Any für Put und Get jeweils unterschiedlich sein. Dann sollte das auch gehen.
    Die Größe von Temp_Any_Pointer und I_Int_ADDR_1 muß jeweils gleich groß sein, also bei Put 8 Byte Länge, bei Get 4 Byte Länge.
    Gruß
    Ralle

    ... there\'re 10 kinds of people ... those who understand binaries and those who don\'t …
    and the third kinds of people … those who love TIA-Portal

  3. #3
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.163
    Danke
    921
    Erhielt 3.286 Danke für 2.655 Beiträge

    Standard

    Die Datenbereiche der eigenen CPU (was senden + wohin empfangen) willst Du per ANY-Parameter an Deinen Baustein übergeben, die Adressen der remote Partner-CPU (wohin senden + woher empfangen) willst Du aus Einzelangaben zusammenstellen.

    Damit Du unterschiedlich große Bereiche senden und empfangen kannst, brauchst Du 2 In-Parameter für die eigenen Datenbereiche: I_Int_Send_Buf, I_Int_Recv_Buf
    Damit Du mit unterschiedlichen Bereichen für Schreiben/Lesen in der remote CPU arbeiten kannst, brauchst Du getrennte In-Parameter für die Schreib/Lese-Adressen: I_Rem_DB, I_Rem_Put_Adr, I_Rem_Get_Adr

    Code:
    VAR_INPUT
      I_Rem_ID: WORD;       // Verbindungs-ID zur remote CPU
      I_Rem_DB : INT;       // Nummer des DB für Put und Get in der remote CPU
      I_Rem_Put_Adr : INT;  // Ziel-Anfangsadresse für Put in dem remote DB
      I_Rem_Get_Adr : INT;  // Quell-Anfangsadresse für Get in dem remote DB
      I_Int_Send_Buf : ANY; // Bereich der eigenen CPU: was gesendet werden soll
      I_Int_Recv_Buf : ANY; // Bereich der eigenen CPU: wohin empfangen werden soll
    END_VAR
    Zitat Zitat von Daten in eine remote CPU schreiben mit dem SFB/FB 15 "PUT"
    Sie müssen darauf achten, daß die über die Parameter ADDR_i und SD_i definierten Bereiche in der Anzahl, in der Länge und im Datentyp zueinander passen.
    Zitat Zitat von Daten aus einer remoten CPU lesen mit dem SFB/FB 14 "GET"
    Sie müssen darauf achten, daß die über die Parameter ADDR_i und RD_i definierten Bereiche in der Anzahl, in der Länge und im Datentyp zueinander passen.
    Die Längenangaben der Bereiche in der eigenen CPU und der remote CPU müssen jeweils GLEICH GROSS sein:
    PUT: Der Zielbereich in der remote CPU muß so groß sein wie die Anzahl der von der eigenen CPU zu sendender Byte.
    GET: Der Empfangspuffer in der eigenen CPU muß so groß sein wie die Anzahl der von der remote CPU zu lesender Byte.
    Also am besten die Längenangaben aus den ANY der eigenen CPU entnehmen und in die ANY der remote CPU eintragen.
    Code:
    //======================================
    // GET: Daten aus remote CPU lesen
    //======================================
    Temp_Any_Pointer := I_Int_Recv_Buf;  //Syntax-ID, Datentyp und Länge vom eigenen Bereich übernehmen
    Buffer.DB_Number := INT_TO_WORD(I_Rem_DB);
    Buffer.Byte_Pointer:= DW#16#84000000 OR SHL(IN:=INT_TO_DWORD(I_Rem_Get_Adr),N:=3);
    
    Get_Data(REQ := Get_Impuls           // Daten aus remote CPU lesen
             ,ID := I_Rem_ID             // Verbindungs-ID zur remote CPU
             ,ADDR_1 := Temp_Any_Pointer // Bereich in der remote CPU
             ,RD_1 := I_Int_Recv_Buf     // Empfangspuffer
             );
    
    //======================================
    // PUT: Daten in remote CPU schreiben
    //======================================
    Temp_Any_Pointer := I_Int_Send_Buf;  //Syntax-ID, Datentyp und Länge vom eigenen Bereich übernehmen
    Buffer.DB_Number := INT_TO_WORD(I_Rem_DB);
    Buffer.Byte_Pointer:= DW#16#84000000 OR SHL(IN:=INT_TO_DWORD(I_Rem_Put_Adr),N:=3);
    
    Put_Data(REQ := Put_Impuls           // Daten in remote CPU schreiben
             ,ID := I_Rem_ID             // Verbindungs-ID zur remote CPU
             ,ADDR_1 := Temp_Any_Pointer // Bereich in der remote CPU
             ,SD_1 := I_Int_Send_Buf     // Sendedaten
             );
    S7-300 CPU haben keine SFC14/SFC15. Es sind die FB14 "GET" und FB15 "PUT" zu verwenden.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  4. #4
    Ultimate_01 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    01.03.2013
    Beiträge
    6
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Guten morgen zusammen,
    danke für eure Hilfe. Ich habe wohl im Eifer des Gefechts den falschen Quellcode kopiert.
    Hier mal den richtigen bei welchem die beiden Any-Pointer unterschiedlich sind. Den erzeugten DB habe ich "vorerst" direkt als Baustein in die andere CPU rüber kopiert, so dass diese zu 100% identisch sind. Dies läuft ja auch, bis ich halt die Anzahl der zu übertragenden Byte änder...

    //======================================
    //Daten senden (PUT)
    //======================================
    //----------------------------
    // Any Pointer deklarieren
    //----------------------------
    Buffer_Put.Syntax_ID := b#16#10; //Pufferlänge
    Buffer_Put.DataTyp := 2; //Code für Datentyp BYTE
    Buffer_Put.Count := INT_TO_WORD(I_Byte_Count_Put); //Anzahl der Nutzdaten-Byte
    Buffer_Put.DB_Number := INT_TO_WORD(I_DB_Nr_Put); //Nummer des Ziel-DBs für die Nutzdaten
    Buffer_Put.Byte_Pointer := dw#16#84000000; //Pointer auf Globaldaten DBX0.0

    //Byte-Adresse in Pointer laden
    Buffer_Put.Byte_Pointer:= Buffer_Put.Byte_Pointer OR (SHL(in:=WORD_TO_DWORD(INT_TO_WORD(I_DB_Byte_Adr_Put)),N:=3));

    //----------------------------
    // Function "Put": DB send
    //----------------------------
    Put_Data(REQ := Put_Impuls // DB senden
    ,ID := I_ID // ID-Nummer der externen Steuerung
    ,ADDR_1 := Temp_Any_Pointer_Put // Externe Adresse des DB´s
    ,SD_1 := I_Int_ADDR_1_Put); // Interne Adresse des DB´s


    //======================================
    //Daten empfangen (GET)
    //======================================
    //----------------------------
    // Any Pointer deklarieren
    //----------------------------
    Buffer_Get.Syntax_ID := b#16#10; //Pufferlänge
    Buffer_Get.DataTyp := 2; //Code für Datentyp BYTE
    Buffer_Get.Count := INT_TO_WORD(I_Byte_Count_Get); //Anzahl der Nutzdaten-Byte
    Buffer_Get.DB_Number := INT_TO_WORD(I_DB_Nr_Get); //Nummer des Ziel-DBs für die Nutzdaten
    Buffer_Get.Byte_Pointer := dw#16#84000000; //Pointer auf Globaldaten DBX0.0

    //Byte-Adresse in Pointer laden
    Buffer_Get.Byte_Pointer:= Buffer_Get.Byte_Pointer OR (SHL(in:=WORD_TO_DWORD(INT_TO_WORD(I_DB_Byte_Adr_Get)),N:=3));

    //----------------------------
    // Function"Get": DB receive
    //----------------------------
    Get_Data(REQ := Get_Impuls // DB empfangen
    ,ID := I_ID // ID-Nummer der externen Steuerung
    ,ADDR_1 := Temp_Any_Pointer_Get // Externe Adresse des DB´s
    ,RD_1 := I_Int_ADDR_1_Get); // Interne Adresse des DB´s



    Leider verstehe ich nicht ganz was du damit meinst:
    Die Längenangaben der Bereiche in der eigenen CPU und der remote CPU müssen jeweils GLEICH GROSS sein:
    PUT: Der Zielbereich in der remote CPU muß so groß sein wie die Anzahl der von der eigenen CPU zu sendender Byte.
    GET: Der Empfangspuffer in der eigenen CPU muß so groß sein wie die Anzahl der von der remote CPU zu lesender Byte.
    Also am besten die Längenangaben aus den ANY der eigenen CPU entnehmen und in die ANY der remote CPU eintragen.
    Die DB´s sind ja zu 100% identisch. Oder muss der Empfangsbereich sowie der Sendebereich jeweils gleich gross sein?

    Besten Dank schon einmal!!

    Liebe Grüsse

  5. #5
    Ultimate_01 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    01.03.2013
    Beiträge
    6
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo zusammen,
    habe nun meinen Fehler gefunden..

    Ich habe im FB als Eingangsvariable den internen DB symbolisch zugewiesen. Dabei macht der SCL-Compiler aus dem Symbolischen Namen nur einen Pointer ohne Längenangabe.
    Somit ist klar warum es nur Funktioniert hat, wenn ich als Eingangsparameter den gesamten DB angegeben habe..

    Trotzdem danke nochmals für eure Tipps und hilfen

    Grüsse Manuel

  6. #6
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.218
    Danke
    533
    Erhielt 2.696 Danke für 1.948 Beiträge

    Standard

    Zitat Zitat von Ultimate_01 Beitrag anzeigen
    Hallo zusammen,
    habe nun meinen Fehler gefunden..

    Ich habe im FB als Eingangsvariable den internen DB symbolisch zugewiesen. Dabei macht der SCL-Compiler aus dem Symbolischen Namen nur einen Pointer ohne Längenangabe.
    Somit ist klar warum es nur Funktioniert hat, wenn ich als Eingangsparameter den gesamten DB angegeben habe..

    Trotzdem danke nochmals für eure Tipps und hilfen

    Grüsse Manuel
    Kannst du bitte noch einmal genau erläutern, was da falsch war? Ich kann deiner Erklärung überhaupt nicht folgen, welche Variable meinst du?
    Gruß
    Ralle

    ... there\'re 10 kinds of people ... those who understand binaries and those who don\'t …
    and the third kinds of people … those who love TIA-Portal

  7. #7
    Ultimate_01 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    01.03.2013
    Beiträge
    6
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo Ralle,

    Ich versuche es mal...

    Also ich hatte die ganze Kommunikation in einem FB untergebracht. Per Inputvariable konnte man den Internen DB für die Put/Get Funktion Symbolisch anlegen. Für den Ziel DB auf der Fremdsteuerung musste man nur noch die DB-Nummer, die Byte-Anzahl und die ID angeben. (Symbolischer DB-Name wurde mit dem Datentyp ANY eingelesen)
    Der SCL-Compiler hat aus dem Symbolisch angelegten internen DB einen Pointer gemacht, jedoch ohne eine Anzahl an Byte.
    Somit war an den Eingängen des PUT/Get Bausteins ADDR_1= ein Pointer mit Bytelänge und am Eingang SD_1 ein Pointer ohne Bytelänge. Was dann dazu führte, dass es beim übertragen des kompletten DBs funktionierte und sobald der Pointer am SD_1 eine andere Bytelänge als der gesamte DB hatte eben nicht...

    Nun habe ich für jeden Eingang der Put/Get-Funktion einen eigenen Pointer zusammengebaut. Ich kann nun in meinem Funktionsbaustein, welcher die gesamte Kommunikation inkl. Überwachung und Auswertung übernimmt, folgende Parameter einstellen.

    -> ID der Partnersteuerung

    Parameter für das Senden
    -> Intere DB-Nr
    -> Internes Startbyte
    -> Externe DB-Nr
    -> Externes Startbyte
    -> Bytelänge

    Und das gleiche dann wieder, um Daten zu Empfangen

    Liebe Grüsse

  8. #8
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.218
    Danke
    533
    Erhielt 2.696 Danke für 1.948 Beiträge

    Standard

    Jetzt verstehe ich, du hattest also rein den DB symbolisch an den Input geschrieben und nicht eine Struct aus diesem DB (was sich da gut anbietet) oder eben auch nur den Any pur (absolut adressiert).
    Gruß
    Ralle

    ... there\'re 10 kinds of people ... those who understand binaries and those who don\'t …
    and the third kinds of people … those who love TIA-Portal

  9. #9
    Ultimate_01 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    01.03.2013
    Beiträge
    6
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo Ralle,


    Zitat Zitat von Ralle Beitrag anzeigen
    Jetzt verstehe ich, du hattest also rein den DB symbolisch an den Input geschrieben und nicht eine Struct aus diesem DB (was sich da gut anbietet) oder eben auch nur den Any pur (absolut adressiert).
    Genau!
    Hatte es nur symbolisch angehängt. Somit hat der Compiler aus dem symbolischen Namen nur eine absolute Adressierung gemacht ohne einen Pointer mit Byte Anzahl.

    Grüsse

Ähnliche Themen

  1. Probleme mit der REAL_TO_INT Funktion
    Von Superfly im Forum CODESYS und IEC61131
    Antworten: 22
    Letzter Beitrag: 03.07.2013, 14:01
  2. Antworten: 10
    Letzter Beitrag: 03.12.2012, 10:35
  3. Antworten: 14
    Letzter Beitrag: 17.08.2012, 10:02
  4. Probleme mit Scl funktion Replace
    Von RMLIF im Forum Simatic
    Antworten: 2
    Letzter Beitrag: 23.01.2011, 07:37
  5. Antworten: 9
    Letzter Beitrag: 15.12.2010, 12:27

Stichworte

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •