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_BLOCKFB_InstrumentVAR_INPUT
  sInstrumentIP: STRING :='192.168.12.80'; // IP address of Instrument
  arrbyInstrumentSendData : ARRAY [0..17] OFBYTE := [16#AB, 16#CD, 16#0, 15(16#0)];
  xInstrumentSendNow : BOOL;
  xInstrumentInit: BOOL;END_VARVAR_OUTPUT
  arrbyInstrumentReceiveData : ARRAY [0..87] OFBYTE := [88(16#0)];
  xInstrumentSndRcvComplete : BOOL :=FALSE;
  xInstrumentSndRcvError : BOOL :=FALSE;
  eInstrumentSndRcvErrorCode: STRING;
  iInstrumentPacketsReceived: CAA.COUNT;END_VARVAR
  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_VARIFxInstrumentInitTHEN
  iState :=0;END_IF;CASEiStateOF0: //Initializetheconnection
 Â
  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: //WaitforSend
  IFxEnableANDUDPPeer.xActiveTHEN
    IFxInstrumentSendNowTHEN
      //Clearvariablesfornewsend
      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: //Waitforsendtocompleteorerror
  IFUdpSend.xDoneTHEN
    UdpSend.xExecute :=FALSE;   Â
    CASEarrbyInstrumentSendData[3] OF//DeterminereceivesizebasedonOpcoderequestsent
      0..15: //Opcodes16#0-16#F-Configurationdata
        uiRcvSize :=18;
      16: //Opcode16#10-StreamMeasurementData
        uiRcvSize :=88;
      32: //Opcode16#20-Information
        uiRcvSize :=88;
    END_CASE
    //Startlistening
    IFUDPPeer.xActiveTHEN
      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;
  IFUdpSend.xErrorTHEN
    UdpSend.xExecute :=FALSE;
    iState:=30; // Error state
  END_IF;
   Â
20: //Waitfordata
  IFUDPReceive.xReadyTHEN
    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;
  ELSIFUDPReceive.xErrorTHEN
    UDPReceive.xEnable :=FALSE;
    TON_WatchdogReceive.IN :=FALSE;
    iErrorCode :=UDPReceive.eError;
    iState:=30; // Error state
  ELSIFTON_WatchdogReceive.QTHEN
    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: //ExitEND_CASE//CalltheCAAFUNCTIONUDPPeer(xEnable:=xEnable, ipAddr:=IPAddress, uiPort:=uiPort, hPeer=>Peer);
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: //Waitforsendtocompleteorerror
  IFUdpSend.xDoneTHEN
   UdpSend.xExecute :=FALSE;
   UDPsend(); (*********************** This is added *****************************)  Â
   CASEarrbyInstrumentSendData[3] OF//DeterminereceivesizebasedonOpcoderequestsent
     0..15: //Opcodes16#0-16#F-Configurationdata
      uiRcvSize :=18;
     16: //Opcode16#10-StreamMeasurementData
      uiRcvSize :=88;
     32: //Opcode16#20-Information
      uiRcvSize :=88;
   END_CASE
   //Startlistening
   IFUDPPeer.xActiveTHEN
     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;
  IFUdpSend.xErrorTHEN
   UdpSend.xExecute :=FALSE;
   UDPsend(); (*********************** This is added *****************************)
   iState:=30; // Error state
  END_IF;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
Related
Talk.ru: 3
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:
That fixed it. Thank you.
I knew it was something block-headed like that.