Have you ever received a tweet from a machine on the factory floor?
These days, modern PLCs interact with the typical PC and Information Technology world (Ethernet, SMTP/emails, SMS/text messaging, cloud technologies), but there often are caveats. You might need an OPC server to talk to the PLC and then a separate web service to interface with the your intranet. You might need to send messages out from the PLC to a PC-based server, specially configured to listen and interpret. You might need a PC-based SCADA system to read the PLC tags and then relay the data out to the rest of the network with scripts. The common theme here is that often times a specially configured PC is required to be the PLC’s interpreter and guide in the foreign IT world.
Beckhoff’s PLCs eliminate the need for that third-party PC. Beckhoff’s CX series PLCs run on hardened Windows machines allowing full access to PC-based tools right at the controller. We recently had the opportunity to integrate some Beckhoff CX9020 PLCs with a UDP messaging system. With Beckhoff’s powerful TwinCAT 3 programming language, build-in libraries, and available reference libraries, setting up some simple UDP communication was very straightforward.
What is UDP?
For some quick background, UDP (or User Datagram Protocol) is a mainstay protocol of the IT world, around since 1980, running on IP networks. It's designed to be a simple and minimal message/packet-based protocol. UDP routes data packets using an IP address and port number for the source and destination. The structure of a UDP packet is shown below:
Beckhoff TwinCAT UDP: How To
Beckhoff has some great reference code available on their website for TwinCAT UDP that was incredibly valuable throughout our implementation. The three main components of their implementation are:
- The FB_PeerToPeer function block, a full-fledged state machine for sending and receiving UDP data
- The FB_Fifo function block, which is instantiated twice for both a send and receive UDP buffer to communicate between FB_PeerToPeer and your main application. Details can be found in the downloads available for the FB_PeerToPeer function block and some documentation can be found here.
- Beckhoff’s Tc2_TcpIp library, which contains all of the low level socket and UDP functions.
Note that there are two examples of FB_PeerToPeer on Beckhoff’s website. There is a TwinCAT 2 implementation which includes projects you can download and a TwinCAT 3 implementation. The TwinCAT 3 implementation does not include downloadable code and is missing some background on the underlying structures, so if you are implementing in TwinCAT 3, I would recommend you pull down both implementations and use the TwinCAT 2 project to fill in the blanks.
When fbPeerToPeer is called, it requires some parameters and objects:
- sendFIfo and receiveFifo should be two different buffers, of the type FB_Fifo.
- sLocalHost can be set to an empty string (‘’) to use your Beckhoff system that will be executing this code.
- nLocalPort should be the port on your local Beckhoff system. Beckhoff uses 1001 in their examples which should work well, although there are other UPD Ports available.
- bEnable is a Boolean that should be set to true for operation. If this is set to false, the UDP messaging will stop and then will reinitialize on a rising edge of bEnable.
Encoded messages are passed into fbPeerToPeer through the sendFifo. SendFifo uses a structure called ST_FifoEntry. To send a UDP message, you will need to declare a variable of this type in your main program:
sendToEntry : ST_FifoEntry;
In your application, you populate the ST_FifoEntry properties:
- sRemoteHost, the IP address string of the remote system you are sending to
- nRemotePort, the port number on which the remote system will receive the UDP message
- msg, the string of data you are sending
Then, you add that to your sendFifo using the AddTail method:
sendFifo.AddTail( new := sendToEntry );
Receiving data works very similarly, where information comes out through a ST_FifoEntry in fifoReceive, using the RemoveHead method. bOK will return a false if RemoveHead is called when the receive FIFO is empty. It also will return false if the send FIFO is already full.
fbPeerToPeer is built on a state machine that executes through one single state each time it is called. Sending and receiving requires multiple state cycles, so that means sendFifo is bound to overflow if you add to your send buffer every scan and only call fbPeerToPeer once per scan. It takes somewhere around five cycles for fbPeerToPeer to go through a complete sequence.
If you want to send several UDP messages quickly, you can call fbPeerToPeer multiple times per scan, just be sure to make sure that you don’t increase the execution time of your program to the point where it is greater than your scan time. If you want to send or receive several UDP messages in a short time frame, another option is to increase the size of your sendFifo and receiveFifo by adjusting the constant MaxFifoSize. However, this will only work if there are breaks between your send and receive spikes that give FB_PeerToPeer a chance to catch up.
Learn more about DMC's Beckhoff and TwinCat 3 Programming services.