Part 12 - TwinCAT functions (using TF6250 - TC3 Modbus TCP)
Video: https://youtu.be/FOC0rUeECDs
#PLC #TwinCAT3 #Beckhoff #IEC_61131-3 #Modbus #Redes_Industriales #Networks #Industrial_Automation
Table of Contents:
A) Objectives
Welcome back! Until now I would say that we have covered all the basics of TwinCAT.
We've learned:
- how TwinCAT works,
- how we create a project,
- some basics of structured text.
- Object oriented programming.
- How to organize code.
- And we also interfaced with some hardware.
Everything I've shown so far is included in the base installation of TwinCAT 3, so in other words the TwinCAT 3 XAE that we installed.
With the functionality that's included in the base XAE, you can do the vast bulk of the stuff you need for an industrial automation project.
However, sometimes you need to do things that require you to extend the functionality of TwinCAT. This is achieved through what Beckhoff calls TwinCAT functions.
Beckhoff have a complete ecosystem of functions that you can use to solve various problems. Some of the functions are very basic, while some of them are so big that they would require their own 18 part tutorial to cover the functionality.
In this part of the tutorial we will look at the concept of the functions, and then we are going to the fun part of this tutorial and install a TwinCAT function and use it to solve a problem. Let's get started!
B) Introduction to TwinCAT functions
The TwinCAT functions are divided into a couple of different categories. Each category has several TwinCAT functions.
The first category is the TF1-series, the TC3 system.
Here we have some extensions to the normal PLC runtimes, such as extensions to run models created in Matlab/Simulink, or editors for creating PLC software in UML
The next category is regarding the human machine interface. So for the operator panel of your TwinCAT software.
With this category you can create a frontend using modern technologies such as HTML5, CSS and JavaScript.
The third category is the measurement one, which for example includes tools for analytics, power measurement and the superb tool called scope.
These tools are very useful and come in handy both when you need to do a short and long term analysis of your process.
ScopeView is very important, you can learn more here:
Video: 🦾 Industrial Automation Courses/PLC Programming Courses/BECKHOFF/Motion Control and IO with TwinCAT by SquishyBrained/EP13 - Scope View
Next we have the controller category which includes all the basic controllers that you might need, such as a PID controller and various filters.
In this category you also have the TwinCAT speech which you for example can use to send commands to your PLC using your voice
Next we have a ginormous category which is the one for motion control.
Whenever you want to do anything in TwinCAT that's related to motion you find it here.
Working with TwinCAT I sometimes get the feeling that half of TwinCAT's functionality is in this category.
The sixth category is connectivity, which includes functions for whenever you want your PLC to connect to other systems and the outside world.
I'll get into more details with this one soon.
Next we have one of the newer functions in TwinCAT, vision.
With this you can integrate a camera into TwinCAT when you for example want to use it for quality inspection
The last category is the industry specific.
Here you will find functions that are specific for certain industries, such as building automation and a framework for wind turbines.
B.1) TF6xxx - Connectivity
For the rest of this tutorial, we will focus on the connectivity category,
where we will look deeper into what functions that are actually available here.
Each category has several functions. Some of them are already integrated into the default installation of the TwinCAT XAE, whilst others require a separate download.
The first example of a function in the connectivity category is TF6020, JSON data interface.
JSON, which stands for javascript object notation, is an open standard file format and data interchange format.
This function is used when you want to exchange data between TwinCAT, and an external application in JSON.
Next we have TF6100, OPC-UA. OPC-UA is a cross-platform open source IEC standard for data exchange between systems, developed by the OPC foundation.
It's an industry standard which most PLC brands understand. This function will give your PLC both an OPC-UA server and client.
Next we have TF6250, modbus TCP.
Modbus is a data communications protocol, originally from the 70s Lots of various devices use modbus. If you work with PLCs you are 100% guaranteed to come across devices that only talk modbus. This is the slightly more modern IP-based version of it.
TF6270 is a function to enable your PLC to talk PROFINET, which is a fieldbus developed by Siemens and used as a standard fieldbus on all Siemens PLC.
Because Siemens has such a big market share there are many devices only talking PROFINET out there.
TF6300 is a function which gives your PLC software the capability to connect to an FTP server to upload and download files.
B.1.1) TF6250, modbus TCP
There are half a gazillion other functions in this category.
Probably enough to keep you occupied for weeks if you wanted to try all of them out.
This category alone could probably keep me occupied making video tutorials for months.
For the programming part of this tutorial we will focus on the TF6250 function,
in where we will run a simulated modbus server and talk to it using our TwinCAT software.
Comment:
When I say that there are a lot of functions to extend your TwinCAT 3 program with, then I really mean it. It's not just the connectivity functions, but every category that I just showed you has so much functionality that I could literally talk for hours and hours about each one.
I wish that I had an infinite amount of time, where I could create courses and tutorials for you and include these functions also in this tutorial.
But fact is that each and one of these categories of TwinCAT functions are a multi-part tutorial by themself.
If you for example look at the TF2000 category,
which covers all the different functions to make a modern web-based front-end or operator panel to your system. This could easily be a complete tutorial by itself, just this single category.
Who knows, maybe I'll make a tutorial about this as well? Anyway let's get back
B.1.2) How does the TF6250, modbus TCP work?
Before diving into the practical part, I thought I wanted to show you a few more details about how the TF6250 works.
So first we have our PLC which runs the XAR,
in other words the TwinCAT runtime.
As I told you in one of the introductory parts of this tutorial, the PLC can be splitted up into two parts.
The operating system and the TwinCAT kernel,
To start using the modbus function, you first need to go to the Beckhoff website and download the TF6250 function.
This is a standard executable that you install on your PLC.
Note: We'll do this step and all the other steps together when we get to the programming part.
By installing this function in the PLC, there will be a process available in the operating system for this function.
Next, to use this function, we need our development environment, that is the XAE.
For some of the functions it's necessary to install the downloaded function in the XAE machine as well, to get access to for example libraries for the function,
However with TF6250, these are already pre-installed with the default XAE installer.
Next, we need to add a reference to the TF6250 modbus library in our TwinCAT 3 project, which we'll do the same way as we've done for other libraries.
This library will give us access to the modbus function blocks in our PLC code.
B.1.2) // ---------------------------------------------------------------------------------------------------------------------
Once we are done with the development of our PLC code we simply need to do an activate configuration, which will deploy our executable on the PLC.
Once our program starts, it will try to initiate a connection to whatever modbus servers that we have defined in the program.
Once a connection is up and running, data exchange can occur The modbus data is initialized in the PLC program and then sent to the process in the operating system As the operating system has access to the network stack, the application now has a channel to send the modbus data to whatever modbus devices that are connected to the network The modbus process will take care of the transmission of the modbus data to the modbus servers, and also tunnel the data in the other direction This architecture allows us to run the real-time kernel applications asynchronous of whatever
happens in user-land. We'll get back to this topic more deeply when we will talk about ADS Okay it's time for a little bit of programming. This part is gonna be a little bit special because we're actually gonna use two separate virtual machines. So the configuration that I will do here is...so first of all I will demonstrate how to use the modbus function.
So the modbus function for TwinCAT. And to do this I need something to talk to. So normally what I would do is to just run everything from the local virtual machine Where we have the development environment, where we have the PLC runtime and where we would in this case have a modbus simulator. I'm not going to do that now. I will have a separate virtual machine.
So the virtual machine here to the left is a separate virtual machine, where we will just run a modbus simulator. And on the right, that's our usual development environment. That's where we will also run our PLC code. So this is also what's simulating the PLC and where we will run the modbus function.
So the modbus supplement that we're gonna download and install. There's one thing more I want to mention. In the modbus terminology there's this...um...so in modbus there is the definition of client and server...are a little confusing. Because y
ou have a master and a slave and you know...I'm not gonna use the standard definition because it it really makes my head explode, and we don't want that to happen. I'm just gonna see this as simply...we will have the modbus client, which will be the PLC and the modbus server which is whatever we're gonna talk to. So the modbus server in this case...it could be a real device but you know because I don't have lots of equipment here in my home, I will simply simulate the modbus server.
The first thing we need to do is to go to the website of Beckhoff and download the function, the modbus function. For that we just look for Beckhoff modbus TCP. TF6250. Okay this is in German. My german is quite bad. "Auf Englisch bitte" And we go to software and tools. Downloads. Exe. Start download. And then we just download the supplement This supplement would normally then again be installed on the PLC to make this bridge from the PLC code to the operating system, where we will have this process that will do the communication with the modbus servers
I will install it here because here we're using the PLC, also as as our runtime So let's install it Installation complete Another thing I forgot to mention is that we have two different network devices. So here we have the PLC which has a certain IP address, so this specific IP address, while the modbus virtual machine, the modbus server virtual machine has this IP address.
So we will be talking from this machine to this machine. So let's start the development environment and create a new project A new TwinCAT project and just call it modbus learning New PLC project So the first thing we're going to do is to add a reference to the modbus library For certain functions then the library is added with the installation Which means you also have to install it on the PLC, on the development environment With some functions this is already installed... the library is already installed with the XAE
So just look for modbus And it's this guy. So this is the RTU version which is serial communication, while this is the TCP variant We can see here that this provides several function blocks for doing different functions in modbus.
So modbus has these these different functions depending on what you want to achieve There's some function codes to read basically bits. And then there's functions to read 16-bit values so integers or words. Then there's functions to write bits. It's just basically different functions. Modbus is an extremely primitive protocol. You don't have the luxury to like you would have in something more modern like opc ua where you can do a method call and get some values or read a variable with a certain name.
I mean this is a protocol from the 1970s, so everything is basically just getting bits and bytes or writing bits and bytes. It's extremely primitive, but yeah. What I thought is that we will start with some of these functions We will write a function block to read some bits. To do that we first have to create a simulation I will use this software that I have downloaded. It's for free.
There are some restrictions so you can run it only for 10 minutes at the time. Then you have to close it down and restart it But with this we can simulate the modbus server. Or modbus slave as the official name is But okay I'm just gonna use server here. Then we can use this simulator to talk from our client And to do that we will simply start with...just register later here.
30 days evaluation Again this is fine for us now. I will by the way provide a link in the description below for the software so you can try this out at home. And then we want to use modbus TCP/IP with this port. This port is important to remember here, because we will have to use this port to talk from the client.
So it's just a standard socket basically Here we can define the slave, so we can define what function we want to provide. We will just start with the coil. A coil just basically provides a list of bits. Then we can try to read them So we will...to read this now...so we can for example set this one to ON To read this now we will create a function block that will read this from the server This value from the server.
And I will just call it "ReadCoilsExample" So we will have to use a function block from the this library called...I actually have it here MBReadCoils, where you have to provide some inputs and you will get some outputs And the way this guy works is... You define an instance of it And then...here's a shortcut. If you press F2... You can do text search.
ReadCoils, and then it will provide just all inputs and outputs, which is quite convenient. So you don't have to enter them manually, like you would maybe normally do The IP address is the IP address of this virtual machine so it's 192.168.5.34 The port is 502. The unit id according to the documentation, is identification number blah blah blah. If it's used by TCP/IP, which we will do, the value should be this.
So then we do that Quantity is...number of digital inputs data bits to be read. So for this example we just set one And...this value is start address of the digital inputs to be read. So the address here is zero. If you just want to read this...the first value cbLength is...contains the max byte size of the destination buffer.
So yeah we need to provide a buffer where we're going to write the data that we have read. We will do that We can just call it nReadValue and it can be a byte Let's just store it in a byte. So this will be the size of that, right? So the SIZEOF will r
eturn the number of bytes which is, in this case...the number of bytes of one byte is one And the destination address is the address of where we want to store the data once we read it. That will be this nReadValue, so address of nReadValue. And then we have to do some triggering of execute, to trigger this function block to actually kind of send the command to this process that's running in windows to do the actual execution.
Actually for fun we can see whether this installation that we did actually started some process in windows, which it should do. So if you go to task manager We should have something with modbus here now. Yepp! There we go. So we have...now we have a process here that's running in the operating system. This is the guy that that our PLC runtime will talk to. I assume through ADS.
And then this is the process that will go out on the network and talk with the actual modbus server, so this virtual machine A little confusing, I know. But once you've worked a little bit with TwinCAT you're going to get the hang of this...how everything works. I mean I could go really geeky here and just start to use a wireshark and show you exactly what's happening.
But I would probably bore the hell out of you doing that. Anyway, so now we can't just call this, because we need a state machine, right? So we need some state machine that defines how we're gonna...you know...start reading by triggering execute. Then wait for the response by lowering execute, and then we just wait for an answer So I would just create a state machine using local variables.
I don't recommend you to do stuff like this...like coding...this is the typical typical way to do it. Which most of the Beckhoff documentation does. A nicer way is to define these local enumerations and I would just call it...we kind of need three states, right? We need one state for while we're waiting, nothing is happening. One state where we're triggering the execute flag.
And one state where we're just waiting for the response. The response or an error. So I would just call it a WAIT, TRIGGER, READ Maybe that's a good name. So in the WAIT state...coding Then we have a trigger state here we will do the triggering and then read Here we will wait for the response, right? A very simple state machine What I will do now, is that I will copy paste this guy, the trigger Oops And when you trigger it we want to trigger it with execute true
But we first want to get to the trigger, right? So when we start this we're in a WAIT state and for that we need a trigger function block. So we'll just call it trigger We will execute the trigger. So the trigger here will be the way to know that okay... "Now we want to go from WAIT to executing this logic". and here we simply check...
coding...then we want to go to TRIGGER, but only if we are in WAIT. This means that we shouldn't allow the user to TRIGGER here unless we're actually already in WAIT. So if it triggers and we're not in WAIT so if you're for example reading the value, we shouldn't do anything. Then we should just let it finish. We simply check eReadState is equal to...
coding...so if the current read state that is WAIT then we go to TRIGGER I think i got this right...yepp These outputs...we're gonna check in the next state. So we trigger this read coils function block here And then we go to the next state...coding And now we're just going to call this function block in the read state with the execute flag set to false.
So it's just executed until we will get the response. Because you know you kind of have to think it about it this way... that here we are in kernel space, so we are in real time. We're running it with our cycle time, whatever the cycle time is set to And we have the real time constraints, and then on parallel to this execution that we have for the real time, we have the operating system, so we have Windows.
And Windows (applications) as you know runs in user space, so there's no deterministic properties of this. Windows can decide to do whatever. But we have the the modbus communication going here, because that happens in Windows We simply have to wait until Windows responds to us. That's why we have this asynchronous communication between the two.
That's kind of the thing I had a hard time to wrap my head around when I went from doing kind of traditional software development to going into real-time PLC control. Then I always had to think about this you know...I have an operating system and I have the TwinCAT kernel. And they are living in their two isolated worlds but we need to communicate between them, and we need to have a way to handle that.
That's exactly what we're doing here So we need to simply call this function block until we get a response And just provide execute false. Here we're going to be in read until we get something from the modbus application in Windows. The only thing we need to check now is... coding Here you see that the 10-minute trial period, so I will close this down A limitation with the software I will start it when we actually need it *
coding*...or we have an error then we don't want to be here anymore Then we want to go back to waiting And I mean, this is just an example but if I would do this more professionally, I would probably create a generic modbus client function block. That we can instantiate w
ith values like the IP address and port, so we don't have to provide that. And also getting...so getting data in and out, so getting the error data and the actual value from the modbus server. Here I'm just doing a demonstration of how to actually use this function block. Obviously this can be cleaned up. And I mean, this is called read coils EXAMPLE after all. Yeah, I think that kind of is everything we need.
And of course we need to instantiate this function block in our MAIN And we need to execute it. And we need to make sure that our real-time properties are correct Okay, I will have to set the isolated core on this one, so I will do a quick reboot Okay, let's run it on the isolated core. Let's activate configuration Okay, so now let's try to talk with the server.
But of course first we have to create the server So again let's create the connection Port 502. Let's just put a value here But first let's set the right slave definition. So we're going to use this coil status, which again is what we're using here. We're using the read coils function block Let's set the first address to 1 or TRUE And let's run this now.
So we have our trigger If we trigger it, it will...because we're in wait, it will go to TRIGGER There it will execute all of this, and then we will wait for the answer. Let's write it Okay, I didn't...nothing happened, what have I missed? Okay, I didn't miss anything, we got an error. Error 1828.
Let's look what this could mean What's 1828 in hexadecimal? That's...okay, let's find the manual for this guy. For some reason I prefer the PDFs ADS error codes 724, license not found. Ah! That's very VERY stupid of me Of course. What we need to do...this is a function, so this is not included in the standard development environment from the XAE.
So you actually have to go to real time Go to...no sorry, to license. Manage licenses and you have to add the TF... what was the name? TF6250 as a license. We have to generate a test license for this. Normally if you would use this in a production environment you would actually order a license for the modbus TCP from Beckhoff to run it.
So yeah, that was a little clumsy of me, but this is just stuff that happens when you run live Let's activate configuration. Now it should want to...yeah, some required runtime license is missing Now we need to add the additional license, or generate a test license for it Here we have all the other licenses that you might want to use, and as you can see there's a gazillion million billion quadrillion licenses that you could buy from Beckhoff So there's many functions. Let's run it again.
Hopefully that was the last surprise I don't have a big problem with surprises, but too many surprises are not fun either. Okay. Let's trigger this guy again. Because we have to start it Yeah, and then we got the value of one. Which is this one. If we set it to false... Let's retrigger it. As you can see we went back to WAIT.
We're in the WAIT, so if we trigger this...if we trigger, so we have to go low... Then we have to go high, then it's gonna run this again And then we got a read value of zero. We can also confirm that this is... that it actually succeeded to read it by going to the function block So...this is the function block in the library. We can see cbLength is one, so cbLength is...
This is not correct in the documentation. "cbRead, contains the number of bytes currently read". We can also see that the number of bytes is one. But we can also see that error is false, which means we had a successful read Okay? The next one we're gonna do is to do some communication in the other direction So in the other direction we're gonna write data to the server.
For that we have the function block MBWriteSingleRegister, where we can write 16 bit values to the modbus server. So we're going to create an instance of this function block and write data to the server instead, so we're not going to read but write data. To do that let's just copy this function block, and instead of calling it read coils example we will call it write register example.
We will create an instance of this function block instead And instead of read the value we'll write a 16 bit value, so an integer for example And instead of a read state it will be a write state. We will still wait, we will still trigger the function block but instead of reading we will do writing so we just call it WRITE. Everything else is more or less the same.
The only difference is that you will have to provide a pointer to the value that you want to write to the modbus server instead of providing a value where you want the data to be stored. We can change this value online to something that we want to write to the modbus server. So let's just simply replace all of these guys This write state is going to go to WRITE here instead.
This is going to be a write state and we're going to do our write single register instead. We can replace everything. So all the logic is the same. We still have... ...we still have to wait when we want to do something. Then we have to trigger the function block, and then we have to wait for the response.
Whether it's a modbus read or whether it's a modbus write, doesn't matter. For the control logic of our PLC it's exactly the same. But now the inputs however will be different. So if you look at the inputs of this We can do like this. Then we will do our nice F2 trick.
I don't know if it's a trick actually It's just a convenience. We use this function block. As you can see...now the inputs are slightly different, not much. It's still an IP address, naturaly. We still need a device to talk to It's a TCP port. A unit id, is the same. And MBAddr is zero, so let's just write zero to this location. nValue will be the value that we will write, so we will just provide...
the write value for the address. Let me think... Okay so it wants the write value, or the nValue is a word so we need to convert this to a word. We can do it with this thing that we also learned in a previous part of this tutorial, type conversion. And execute is true. Then timeout.
If we don't change the timeout it will be the default ADS timeout, whatever that is. One second, five seconds or something. So we don't have to change it And then the outputs we won't use in the trigger but we will use them in the actual write state. And I think that's pretty much it, yeah. So we don't have any pointers or anything because we don't need to provide a pointer to where the function block should store data, because again the communication is going in the other direction, so we just need to provide the data that we want to write to the modbus server. But that's pretty much it, so let's...
First of all, of course we need to provide an...we need to create an instance of this function block And we need to execute it. And it's okay to do reading and writing at the same time. This library and this supplement...this TwinCAT function can handle writing and reading at the same time You can even do reading and writing to different addresses and and registers at the same time Hopefully I haven't forgotten anything.
Only time will tell Let's run it. And now, first of all, we need to provide a value to write So we have to provide the...so let's provide the value 1000. That's what we want to write Let's just write it down. Then let's trigger this function block So yeah, I'm just going to open... Here so let's do it from here instead.
We're going to trigger from here, and let's write it and see what happens Yeah. You see we got value 1000 here. So let's change it to minus 32 000. It's an integer so it should be fine. And let's retrigger the function block So retriggering the function block will make us go from WAIT Because again, the trigger will change the wait states to TRIGGER and then we will go execute high and execute low and wait.
Yeah, I guess you kind of get this now at this point Yeah. And we got minus 32 000 here. So now we've actually had two virtual machines talking to each other in both directions. We've been reading data from the modbus server. The simulated modbus server, and we've been writing data to it using two different function codes. The first one was function code...modbus function one, read coils.
The other one was function six which is write single register. And if you want to, I would highly encourage you to read about modbus and exactly how it works. It's quite interesting but again this is a very very old protocol. But you will still find it everywhere in the industry. There's so many devices that are only talking modbus so I would highly recommend you to learn this for only that reason.
I'm just basically 100% sure you will at some point in your automation career get to use these functions Yeah, but that's it! Time runs fast when you have fun. This was just a tiny tiny preview of the various TwinCAT functions that are available to discover. If I ever do more videos after this tutorial is finished, this is sure to be one of the topics that I will get back to This was the last video of the basic part of this tutorial.
Congratulations! The next video will be the first one in the advanced series of videos, where we will look at a very important topic, version control. Thank you for being with me so far. See you in the next part!
G) 💬 Summary (copy code 🖥️)
Z) 🗃️ Glossary
File | Definition |
---|
Uncreated files | Origin Note |
---|