Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

NetVarUDP, 3.5.11.0 Errorhandling

Anonymous
2017-08-31
2017-09-04
  • Anonymous - 2017-08-31

    Originally created by: Codesys>>Twincat

    Hallo,

    ich betreibe erfolgreich eine UDP-Verbindung von der ControlWin SPS zu einer Siemens Cpu mit Hilfe der NetVarUDP-Bibliothek und folgendem Code:

    PROGRAM UDP_PRG
    VAR
       HandleSND:SysTypes.RTS_IEC_HANDLE;
    END_VAR
    ________________________________________________________________________
    IF HandleSND = 0 THEN
       HandleSND:=NetVarUdp.UdpOpenSendSocket(iPort:=3334);
    END_IF
    UdpReceiveData(
       hSocket:= HandleSND, 
       iPort:= 3333, 
       pbyData:= ADR(Global_Variables.bufrcv), 
       diDataSize:=200 );
    UdpSendData(
       hSocket:= HandleSND, 
       iPort:= 3334, 
       stIPAddress:= '192.168.72.247', 
       pbyData:= ADR(Global_Variables.bufsend), 
       diDataSize:= 200);
    

    Das Programm läuft in einer eigenen Task mit 10ms Zykluszeit und funktioniert eigentlich ganz gut. Probleme gibt es wenn der Partner, aus welchen Gründen auch immer, aufhört zu senden. Dann hängt der Task endlos bei UdpReceiveData fest und bei STOP meldet die PLC schließlich Ausnahmefehler weil "Task does not react within timeout switchting to stop! An application reset is neccesary!" (Screenshot)

    In den Code von UdpReceiveData kann man offensichtlich nicht reinschauen und die vorhandene Dokumentation dazu lässt sehr zu wünschen übrig (Screenshot). (Grundsätzlich wären Code-Beispiele für die Verwendung solcher Bausteine sehr hilfreich.)

    Irgendwelche Vorschläge wie ich das abfangen oder grundsätzlich besser programmieren kann, um diesen Fehler in Zukunft zu vermeiden? Die verwendete CODESYS Version ist 3.5SP11 x64

    IMG: udpreceivedata_doku.PNG

    IMG: udpreceivedata_Ausnahmefehler.PNG

     
  • Anonymous - 2017-09-04

    Originally created by: Codesys>>Twincat

    Das Problem ist, dass ich hier die falschen Bausteine verwende.
    Die Bausteine aus der NetVarUDP-Bibliothek werden, wie der Name schon sagt bei Verwendung von globalen Netzwerkvariablen im Hintergrund benutzt. Das ist, nach meinem Verständnis allerdings nur sinnvoll wenn zwei CODESYS-CPUs miteinander kommunizieren sollen.

    Um eine generische UDP-Kommunikation von einer Netzwerkschnittstelle zu einer anderen einzurichten sollte man die Bibliothek "CAA Net Base Services" verwenden. Dort geht es dann auf gewohnte Weise mit Sockel aufmachen und Handle an Receive und Sendebaustein übergeben.
    Also z.B. so:

    PROGRAM UDP_PRG_2
    VAR
       
       Sockel: NBS.UDP_Peer;
       handle:CAA.HANDLE;
       Send: NBS.UDP_Send;
       xsend: BOOL;
       Receive: NBS.UDP_Receive;
       remIP:NBS.IP_ADDR := (sAddr := '192.168.72.247');
       localip: nbs.ip_addr := (sAddr := '192.168.72.41');
    END_VAR
    __________________________________________________________________________________
    --------------------------------------------------------------------------------------------------------------
    Sockel(
       xEnable:= TRUE, 
       xDone=> , 
       xBusy=> , 
       xError=> , 
       ipAddr:=localip, 
       uiPort:= 3333, 
       ipMultiCast:= , 
       eError=> , 
       xActive=> , 
       hPeer=>handle );
       
    IF NOT Sockel.xActive THEN
       RETURN;
    END_IF
    Receive(
       xEnable:= TRUE, 
       xDone=> , 
       xBusy=> , 
       xError=> , 
       hPeer:=handle , 
       szSize:= 200, 
       pData:= ADR(global_variables.BufRcv), 
       eError=> , 
       xReady=> , 
       ipFrom=> , 
       uiPortFrom=> , 
       szCount=> );
    Send(
       xExecute:= xsend, 
       udiTimeOut:= 1000, 
       xDone=> , 
       xBusy=> , 
       xError=> , 
       hPeer:= handle, 
       ipAddr:= remip, 
       uiPort:= 3334, 
       szSize:= 200, 
       pData:= ADR(Global_Variables.BufSend), 
       eError=> );
       
       IF send.xdone OR send.xerror THEN
          xsend:=FALSE;
          BufSend.Cnt:=BufSend.Cnt+1;
          RETURN;
       END_IF
       xsend:=TRUE;
    

    Hier wird allerdings nur jede zweite Ausführung des Tasks gesendet, da der Sendebaustein zurückgesetzt werden muss. (Kann man bestimmt noch besser machen.) Außerdem komplett ohne Errorhandling wie man sieht.

     

Log in to post a comment.