UPDPeer Sends only the first packet

jimsmart
2017-09-21
2017-09-21
  • jimsmart - 2017-09-21

    Hello. I'm having an issue with UDPPeer. The instrument I'm trying to communicate with sends one response packet per request (until I request streaming data, which I haven't gotten that far yet). Using the code below, I can send and receive the first packet, but only the first one. It won't send a 2nd packet. Using Wireshark, I can see that the 2nd packet never leaves the PLC. I noticed that UDPSend.XDone always stays high after the first send. I tried changing up the code to disable and re-enable the UDPPeer connection for every send/receive, but that didn't help.

    Please excuse my primitive coding skills.

    Thanks,
    Jim

    FUNCTION_BLOCK FB_Instrument
    VAR_INPUT
       sInstrumentIP: STRING := '192.168.12.80'; // IP address of Instrument
       arrbyInstrumentSendData : ARRAY [0..17] OF BYTE := [16#AB, 16#CD, 16#0, 15(16#0)];
       xInstrumentSendNow : BOOL;
       xInstrumentInit: BOOL;
    END_VAR
    VAR_OUTPUT
       arrbyInstrumentReceiveData : ARRAY [0..87] OF BYTE := [88(16#0)];
       xInstrumentSndRcvComplete : BOOL := FALSE;
       xInstrumentSndRcvError : BOOL := FALSE;
       eInstrumentSndRcvErrorCode: STRING;
       iInstrumentPacketsReceived: CAA.COUNT;
    END_VAR
    VAR
       iState: INT:= 0;
       IPAddress : NBS.IP_ADDR; (* IP Address *)
       uiPort : UINT; (* Port No. *)
       ctRecAnswers : CAA.COUNT; (* No. of received messages *)
       UDPPeer : NBS.UDP_Peer; (* FB UDP Peer *)
       XUDPPeer : NBS.UDP_Peer; (* FB UDP Peer *)
       UDPSend : NBS.UDP_Send; (* FB UDP Send *)
       UDPReceive : NBS.UDP_Receive; (* FB UDP Receive *)
       Peer : CAA.HANDLE; (* Handle to the peer connection *)
       xEnable : BOOL;
       sUDPData :STRING;
       uiRcvSize: UINT;
       iErrorCode : INT := 0;
       TON_WatchdogReceive: TON;
    END_VARIF xInstrumentInit THEN 
       iState := 0;
    END_IF;
    CASE iState OF
    0: // Initialize the connection
       
       IPAddress.sAddr := sInstrumentIP; // IP address of Instrument
       uiPort := 50000;
       xInstrumentInit := FALSE;
       TON_WatchdogReceive.PT := T#500MS;
       TON_WatchdogReceive.IN := FALSE;
       xInstrumentSndRcvComplete:= FALSE;
       xInstrumentSndRcvError:= FALSE;
       xEnable := TRUE; // Used for send case and for UDPPeer function call
       iState := 10;
       
    10: // Wait for Send
       IF xEnable AND UDPPeer.xActive THEN 
          IF xInstrumentSendNow THEN
             // Clear variables for new send
             xInstrumentSndRcvComplete:= FALSE;
             xInstrumentSndRcvError:= FALSE;
       
             UDPsend (
                xExecute   := TRUE, 
                ipAddr   := IPAddress,
                uiPort   := uiPort,
                hPeer   := UdpPeer.hPeer,
                szSize   := 18,
                pData   := ADR(arrbyInstrumentSendData),
                udiTimeOut   := 1000000, (* usec *)
                );
             xInstrumentSendNow   := FALSE;
             iState:= 15;
          ELSE
             iState:= 10; // nothing to send, come back here
          END_IF;
       END_IF;
          
    15: // Wait for send to complete or error
       IF UdpSend.xDone THEN
          UdpSend.xExecute := FALSE;      
          CASE arrbyInstrumentSendData[3] OF // Determine receive size based on Opcode request sent
             0..15: // Opcodes 16#0-16#F - Configuration data
                uiRcvSize := 18;
             16: // Opcode 16#10 - Stream Measurement Data
                uiRcvSize := 88;
             32: // Opcode 16#20 - Information
                uiRcvSize := 88;
          END_CASE
          // Start listening
          IF UDPPeer.xActive THEN
             UDPReceive(
                xEnable:= TRUE,
                hPeer:= Peer,
                szSize:= uiRcvSize, 
                pData:= ADR(arrbyInstrumentReceiveData)
                );
          END_IF;
          iState:= 20; // Wait for data 
          TON_WatchdogReceive.IN := TRUE; // Start watchdog
       END_IF;
       IF UdpSend.xError THEN
          UdpSend.xExecute := FALSE;
          iState:= 30; // Error state
       END_IF;
          
    20: // Wait for data
       IF UDPReceive.xReady THEN
          UDPReceive.xEnable := FALSE;
          ctRecAnswers := ctRecAnswers + 1; // Number of UDP calls
          iState:= 10; // Data received, go back to wait to send
          xInstrumentSndRcvComplete := TRUE;
          TON_WatchdogReceive.IN := FALSE;
          iInstrumentPacketsReceived := ctRecAnswers;
       ELSIF UDPReceive.xError THEN
          UDPReceive.xEnable := FALSE;
          TON_WatchdogReceive.IN := FALSE;
          iErrorCode := UDPReceive.eError;
          iState:= 30; // Error state
       ELSIF TON_WatchdogReceive.Q THEN
          UDPReceive.xEnable := FALSE;
          xInstrumentSndRcvComplete := TRUE;
          TON_WatchdogReceive.IN := FALSE;
          iState:= 10; // Go back to wait for now. Improve handling later.
       END_IF;
    30: // Error
       xInstrumentSndRcvError := TRUE;
       xInstrumentSndRcvComplete := FALSE;
       
    40: // Exit
    END_CASE
    // Call the CAA FUNCTION
    UDPPeer(xEnable:= xEnable, ipAddr:= IPAddress, uiPort:= uiPort, hPeer=> Peer);
    
     

    Related

    Talk.ru: 3

  • Lo5tNet - 2017-09-21

    To me it looks like you never call the function block UDPsend when you have execute set to false so it never registers the falling trigger. After you set UdpSend.xExecute := FALSE; you then need to call UDPsend(); before you go back into case statement 10 where it gets set back to TRUE.

    For example:

    15: // Wait for send to complete or error
       IF UdpSend.xDone THEN
          UdpSend.xExecute := FALSE;
          UDPsend();  (*********************** This is added *****************************)      
          CASE arrbyInstrumentSendData[3] OF // Determine receive size based on Opcode request sent
             0..15: // Opcodes 16#0-16#F - Configuration data
                uiRcvSize := 18;
             16: // Opcode 16#10 - Stream Measurement Data
                uiRcvSize := 88;
             32: // Opcode 16#20 - Information
                uiRcvSize := 88;
          END_CASE
          // Start listening
          IF UDPPeer.xActive THEN
             UDPReceive(
                xEnable:= TRUE,
                hPeer:= Peer,
                szSize:= uiRcvSize, 
                pData:= ADR(arrbyInstrumentReceiveData)
                );
          END_IF;
          iState:= 20; // Wait for data 
          TON_WatchdogReceive.IN := TRUE; // Start watchdog
       END_IF;
       IF UdpSend.xError THEN
          UdpSend.xExecute := FALSE;
          UDPsend();  (*********************** This is added *****************************)
          iState:= 30; // Error state
       END_IF;
    
     
  • jimsmart - 2017-09-21

    That fixed it. Thank you.

    I knew it was something block-headed like that.

     

Log in to post a comment.