Quick Start (PLC / UDP)

The sample implements an “echo service”: A UDP server is started on a port (default: 10000). If this server receives a UDP packet, it returns the content to the sender (with same IP and same port).

The sample is also available for download under Sample 02. In addition to the Quick Start, the download contains extended code, which does not affect the basic functionality.

Implementation of the UDP echo server in a PLC project

A TwinCAT solution was generated
1. If no PLC project exists in the TwinCAT solution, you have to create one.
2. A function block is generated, which implements the interface "ItcIoUdpProtocolRecv". This creates a method, which is called when UDP packets arrive.
By right-clicking on the node "POU" in the PLC project you can allocate names in the Popup window, activate "SampleUdpEchoServer" and "Implements" by ticking, and select the interface mentioned with the button "…":
Quick Start (PLC / UDP) 1:

The declaration part of the function block contains several variables in the declaration:

3. The declaration part is created in this way:
{attribute 'c++_compatible'}
FUNCTION_BLOCK SampleUdpEchoServer IMPLEMENTS ITcIoUdpProtocolRecv
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
    {attribute 'TcInitSymbol'}
    oid:              OTCID;
    ipUdp:            ITcIoUdpProtocol;
    nUdpPort:         UINT := 10000;
    nReceivedPakets:  UINT;
    hrInit :          HRESULT;
    hrSend :          HRESULT;
END_VAR

The CheckReceive() method of the TCP/UDP RT module must be called in the body of the function block.

4. The body is created in this way:
IF ipUdp <> 0 THEN
    ipUdp.CheckReceived();
END_IF

The method "ReceiveData", which was created through implementation of the interface, will be called repeatedly via "CheckReceived": one call for each packet received in the meantime.

5. The method has both sender information and data as input parameters. In this sample, the "SendData" method returns an incoming packet as response (with sender/receiver reversed). The implementation is done as follows:
nReceivedPakets := nReceivedPakets+1;
IF ipUdp <> 0 THEN
    hrSend := ipUdp.SendData(ipAddr, udpSrcPort, udpDestPort, nData, pData, TRUE, 0); // send data back
END_IF

During start and finish, a reference to the "UdpProtocol" interface must be set from the configured OID; corresponding approvals should be taken care of during shutdown.

6. The function block requires the methods "FB_init", "FB_reinit" and "FB_exit", which can be created by right-clicking on the function block "Add…" method:
Quick Start (PLC / UDP) 2:

Appropriate signatures are generated automatically, so that only the actual body has to be realized. Of particular significance is the "RegisterReceiver" call, which opens a UDP port for reception.

7. The "FB_init" method requires two local variables:
VAR
    ipSrv: ITComObjectServer;
END_VAR
8. The "FB_init" method is implemented as follows:
IF NOT bInCopyCode THEN // no online change
IF ipUdp = 0 AND oid <> 0 THEN
hrInit := FW_ObjMgr_GetObjectInstance(oid:=oid, iid:=TC_GLOBAL_IID_LIST.IID_ITcIoUdpProtocol, pipUnk:=ADR(ipUdp) );
IF SUCCEEDED(hrInit) THEN
IF SUCCEEDED(ipUdp.RegisterReceiver(nUdpPort, THIS^)) THEN //open port
FB_init := TRUE;
ELSE
FB_init := FALSE;
FW_SafeRelease(ADR(ipUdp));
END_IF
END_IF
ELSIF oid = 0 THEN
FB_init := FALSE;
hrInit := ERR_INVALID_PARAM;
END_IF
END_IF

In the "FB_reinit" method, which is executed during an OnlineChange, the TCP/UDP RT object must be supplied with the new address for the callbacks.

9. The "FB_reinit" method is implemented as follows:
IF (ipUdp <> 0) THEN 
ipUdp.RegisterReceiver(nUpdPort, THIS^);
FB_reinit := TRUE:
END_IF

The port must be closed again during shutdown (but not during OnlineChange, cf. bInCopyCode).

10. The "FB_exit" method is implemented as follows:
IF (NOT bInCopyCode AND ipUdp <> 0) THEN //Shutdown
     ipUdp.UnregisterReceiver(nUpdPort);
    FW_SafeRelease(ADR(ipUdp));
     FB_exit := TRUE;
ELSE
     FB_exit := FALSE;
END_IF
11. Finally, the function block must be called:
PROGRAM MAIN
VAR
        udp1 : SampleUdpEchoServer;
END_VAR

udp1();

“TCP/UDP RT” module configuration

Notice Variable names relating to TCP are used here. They have to be substituted accordingly.

1. Create the “TCP/UDP RT” module under the RT Ethernet adapter by selecting “Add Object(s)…” in the context menu.
Quick Start (PLC / UDP) 3:
2. Then select the “TCP/UDP RT” module:
Quick Start (PLC / UDP) 4:
The TCP/UDP RT object is created under the adapter.
Quick Start (PLC / UDP) 5:
3. Parameterize the previously created instance of the module (here: Module1) under “Interface Pointer” “TcpProt” with the OID of the created “TCP/UDP RT” object: Quick Start (PLC / UDP) 6:
4. For PLC projects this configuration is also done at the instance, under the tab “Symbol Initialization”:
Quick Start (PLC / UDP) 7:
The configuration is thus completed
Quick Start (PLC / UDP) 8:

Disconnection by the operating system in Promiscuous mode

If Promiscuous mode is active at the RT Ethernet adapter in the “Adapter” tab, any TCP connection attempts are blocked by the operating system, since it does not recognize a port opened in the TCP/UDP RT object.

Testing

Once the configuration has been activated, a UDP packet can be sent to the PLC via the UDP Sample Client. It can be observed that each call increments the counter. The client displays the returned packets at the top.

Quick Start (PLC / UDP) 9:
Quick Start (PLC / UDP) 10:

No local communication

The UDP sample client must run on a different computer than the PLC with the TCP/UDP RT object, because no local communication between the Windows operating system and the real-time is available.
Alternatively, a so-called "loop cable" can be used to connect two network ports. The UDP sample client can be forced to use a specific port by selecting the source (dropdown menu "Source").