Step 7 PUT_E/GET_E Daten kommen nicht an. Kein Fehlerstatus anstehend.

vollmi

Level-3
Beiträge
5.425
Reaktionspunkte
1.403
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich versuch grade das erste mal eine S7 PUT/GET_E Verbindung zu etablieren.

Ohne Erfolgt bisher. Der Request wird angestossen, mit Done bestätigt trotzdem kommt auf der Anderen Seite nix an und auf der eigenen Seite wird nix abgelegt.

Sieht jemand einen Fehler in meiner Vorgehensweise?

CPU ist derzeit eine PN/DP 315

Code:
FUNCTION_BLOCK MasterCom


VAR_INPUT
    DB_1_Recv : ANY; // 1. DB zum Empfangen
      pDB_1_Recv AT DB_1_Recv : ANY_POINTER;
    DB_2_Recv : ANY; // 2. DB zum Empfangen
      pDB_2_Recv AT DB_2_Recv : ANY_POINTER;
    DB_1_Send : ANY; // 1. DB zum Senden
      pDB_1_Send AT DB_1_Send : ANY_POINTER;
    DB_2_Send : ANY; // 2. DB zum Senden
      pDB_2_Send AT DB_2_Send : ANY_POINTER;
    ID : INT; // VerbindungsID


END_VAR


VAR
    GET : GET_E;
    PUT : PUT_E;
    tGET : TON;
    tPUT : TON;


    
    GET_Status : WORD;
    PUT_Status : WORD;
        
    
END_VAR


VAR_TEMP
    Laenge : WORD;
    DB_1_Send_L : WORD;
    DB_2_Send_L : WORD;
    DB_1_Recv_L : WORD;
    DB_2_Recv_L : WORD;


END_VAR


GET(   ,ID := INT_TO_WORD(ID) // IN: WORD
            ,ADDR_1 := pDB_1_Recv // INOUT: ANY
            ,ADDR_2 := pDB_2_Recv // INOUT: ANY
            ,RD_1 := pDB_1_Recv // INOUT: ANY
            ,RD_2 := pDB_2_Recv // INOUT: ANY
            ); 
 
IF NOT GET.REQ THEN
  GET.REQ := true;
END_IF;  


IF GET.NDR OR GET.ERROR OR tGET.q THEN
  GET.REQ := false;
END_IF;


IF GET.error THEN
    GET_Status := GET.status;
END_IF;


tGET(IN :=  GET.REQ// IN: BOOL
          ,PT := t#30s // IN: TIME
          ); 




PUT(        ID := INT_TO_WORD(ID) // IN: WORD
            ,ADDR_1 := pDB_1_Send // INOUT: ANY
            ,ADDR_2 := pDB_2_Send // INOUT: ANY
            ,SD_1 :=  pDB_1_Send// INOUT: ANY
            ,SD_2 :=  pDB_2_Send // INOUT: ANY
            ); 




IF NOT PUT.REQ THEN
  PUT.REQ := true;
END_IF;  


IF PUT.DONE OR PUT.ERROR OR tPUT.q THEN
  PUT.REQ := false;
END_IF;
  
 IF PUT.error THEN
    PUT_Status := PUT.status;
END_IF;  


tPUT(IN :=  PUT.REQ// IN: BOOL
          ,PT := t#30s // IN: TIME
          ); 
  
END_FUNCTION_BLOCK

Der Aufruf
Code:
      CALL  #Slave1
       DB_1_Recv:=P#DB2201.DBX0.0 BYTE 200
       DB_2_Recv:="Nord_RU_KLP_HW_Input".HW_INPUT
       DB_1_Send:=P#DB2202.DBX0.0 BYTE 40
       DB_2_Send:="Nord_RU_KLP_HW_Output".DB_VAR
       ID       :=1
 
Hallo René,

den Code würde ich selbst so nicht umsetzen. Ich würde mir eine Schrittkette erstellen, die z.B. in folgender Reihenfolge arbeitet :
1 : Get anstossen
2 : Get-Status = aktiv abfragen
3 : Get-Status = nicht aktiv abfragen
4 : warten
5 : Put anstossen
6 : Put-Status = aktiv abfragen
7 : Put-Status = nicht aktiv abfragen
8 : warten
9 : wieder von vorne

... das kann man jetzt natürlich noch zusätzlich mit der fehler-Auswertung "würzen"

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
hmpf. Ich hab das jetzt schnell in awl nachgebaut da tuts genau so.
PUT/GET_E völlig nicht gegeneinander verriegelt funktioniert in AWL einwandfrei. Irgendwas mach ich in SCL da falsch.

mfG René
 
... ich hatte jetzt auch erstmal keinen Fehler gesehen - deshalb mein Ansatz ...
Es wird aber wohl doch schon ein Unterschied zwischen deinem AWL-Test und dem gesposteten SCL-Code sein ... vielleicht bei den Pointern ...?

Gruß
Larry
 
Hallo René,

was ist das für ein "komischer" Datentyp ANY_POINTER? Wozu soll das gut sein?
Code:
VAR_INPUT
    DB_1_Recv : ANY; // 1. DB zum Empfangen
      [COLOR="#FF0000"]pDB_1_Recv AT DB_1_Recv : ANY_POINTER;[/COLOR]
    DB_2_Recv : ANY; // 2. DB zum Empfangen
      [COLOR="#FF0000"]pDB_2_Recv AT DB_2_Recv : ANY_POINTER;[/COLOR]
    DB_1_Send : ANY; // 1. DB zum Senden
      [COLOR="#FF0000"]pDB_1_Send AT DB_1_Send : ANY_POINTER;[/COLOR]
    DB_2_Send : ANY; // 2. DB zum Senden
      [COLOR="#FF0000"]pDB_2_Send AT DB_2_Send : ANY_POINTER;[/COLOR]
    ID : INT; // VerbindungsID
END_VAR

Versuchst Du, die Adresse der INPUT-Parameter an GET bzw. PUT zu übergeben?
Es muß der gesamte ANY in die INPUT-Parameter von GET/PUT kopiert werden (also der Wert des ANY-Parameters, nicht dessen Adresse).
Dein Code sieht gekürzt aus. Fummelst Du in Deinem realen Programm vielleicht noch an den ANYs rum?
Funktioniert es, wenn Du das mit dem ANY_POINTER wegläßt?
Code:
[COLOR="#008080"](*
GET(   ,ID := INT_TO_WORD(ID) // IN: WORD
            ,ADDR_1 := [COLOR="#FF0000"]pDB_1_Recv[/COLOR] // INOUT: ANY
            ,ADDR_2 := [COLOR="#FF0000"]pDB_2_Recv[/COLOR] // INOUT: ANY
            ,RD_1 := [COLOR="#FF0000"]pDB_1_Recv[/COLOR] // INOUT: ANY
            ,RD_2 := [COLOR="#FF0000"]pDB_2_Recv[/COLOR] // INOUT: ANY
            );
*)
[/COLOR]
GET(        ID := INT_TO_WORD(ID) // IN: WORD
            ,ADDR_1 := [COLOR="#0000FF"]DB_1_Recv[/COLOR]  // INOUT: ANY
            ,ADDR_2 := [COLOR="#0000FF"]DB_2_Recv[/COLOR]  // INOUT: ANY
            ,RD_1 := [COLOR="#0000FF"]DB_1_Recv[/COLOR]    // INOUT: ANY
            ,RD_2 := [COLOR="#0000FF"]DB_2_Recv[/COLOR]    // INOUT: ANY
            );
 
[COLOR="#008080"]//IF NOT GET.REQ THEN[/COLOR]
  GET.REQ := true;
[COLOR="#008080"]//END_IF;[/COLOR]
(das IF.. ist überflüssig)

(Die Außen beim Aufruf des FB MasterCom übergebenen ANY dürfen nicht auf Variablen in TEMP zeigen.)

Ansonsten sehe ich in dem SCL-Code keinen Fehler.
Gibt es die DBs auf beiden CPUs? Und lang genug?

Harald
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
was ist das für ein "komischer" Datentyp ANY_POINTER? Wozu soll das gut sein?

Das ist ein UDT der den Any_Pointer beschreibt. Und die AT sicht ist ja sozusagen dann der ANY Pointer im Temp. Eigentlich sollte dass ja das machen was man in AWL macht wenn man den Anypointer aus der Schnittstelle nimmt in den Tempbereich zieht um ihn an weitere FBs durchzureichen.

Hier z.B. habe ich das genau so gemacht um ihn an einen BlockMove weiterzureichen.
Code:
FUNCTION_BLOCK Obj_ABLUFTKLP


VAR_INPUT
    LS_PAR : ANY; // Pointer aufs erste Wort des Kommunikationsbereichs zum UeLS
      POINTING AT LS_PAR : ANY_POINTER; 
    AumaIN : AumaIN;
END_VAR


VAR_OUTPUT
    AumaOut : AumaOut;
END_VAR


VAR_IN_OUT
    Klp_Fahr: Klp_fahr; // UDT für Automatikanforderungen
    GrpTestRein: INT := 1000; // Welcher Testgruppe zugeordnet?
END_VAR


VAR_TEMP
   Ret : INT;
   KLP : LS_ABL_KLP; // temporäre Variablen
END_VAR


VAR
  Bedienart_save : INT;  // Bedienart sichern
  Automatik : BOOL;
  ST_TIMER : TON;
END_VAR




(*Pointer auf UDT schreiben zum arbeiten*)
  pointing.Bereichstyp := 2;   // Typ des Bereichs soll Byte sein (INT = 2)
  pointing.Anzahl_Werte := 24; // Länge des Pointers weil wir einen Any ohne Länge angeben wollen
  Ret :=  BLKMOV(SRCBLK := LS_PAR ,DSTBLK := KLP);

Oh mann jetzt seh ichs. Ich hab da garnicht den UDT ausm Temp an Blockmove gehängt sondern das nur zum verändern des Pointers genutzt.

jargl. Danke für den Denkanstoss.

mfG René
 
Zuletzt bearbeitet:
Zurück
Oben