Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

TwinCAT tutorial - Beckhoff


Published on

An detailed tutorial for the beginner of TwinCAT. It is usefull for people who want to control the motors of Beckhoff company

Published in: Engineering

TwinCAT tutorial - Beckhoff

  1. 1. TwinCAT Tutorial 1 TABLE DE CONTENT Chapter1: Introduction…………………………………………………………………………………...2 Chapter2:QuickStart………………………………………………………….………………………....5 Chapter3:StructuringPLCData…………………………………………….…………….……………47 Chapter4:PersistentVariables…………………………………………………………………….…...59 Chapter5:StructuringPLCLogic………………………………………….……………………………79 Chapter6:MultipleVirtualPLCs…………………………………….…………..………………………88 Chapter7:LadderLogicEditor………………………………………….……………………………..110 Chapter8:WritingyourownFunctionsandFunctionBlocks……..……………………...……………126 Chapter9: StructuredText…………………………………………...………………………………..139 Chapter10:BuildinganHMIin.NET………………………………….………………………………151 Chapter11:IntroductiontoMotionControl………………………….…………………..……………..162 Chapter12:IntroductiontoTwinSAFE.………………………….…………...………………………..187 Chapter13:TheScopeView……………………………………….…………………………………216 Chapter14:PartTracking……………….……………………………….………...………………….229
  2. 2. Chapter 1: Introduction 2 1 – Introduction In the control system industry we’re used to slow progress. PLCs lag behind PC technology by ten years or more, and we pay an outrageous premium for PLC hardware compared to the technology sitting on our desktop in our offices. Beckhoff has always pushed PC-based control systems based on commodity hardware like Intel x86 processors and Ethernet chips. With TwinCAT 3, their flagship automation software now supports multi-core processing, which leaves traditional PLC technology so far behind it’s not even funny. On all new TwinCAT 3 PLC programs I start, I set the task to run every 0.5ms by default, and I could run most of them much faster. Not only does the PLC logic execute every 0.5ms, but the EtherCAT I/O bus for a reasonably large machine can also run at this speed. When you compare this with a traditional PLC with typical logic scan times (plus I/O refresh times) in the tens of milliseconds, you can see that TwinCAT 3 with EtherCAT is far better suited to any high speed process than your typical PLC. If you think scan times don’t matter, consider a conveyor line running at around 1 m/s (completely reasonable) and you have to fire an output as a specific point on the conveyor passes a given location (measured by an encoder). The difference between a 1ms reaction time and a 10ms reaction time is the difference between 1 mm and 10 mm accuracy. The TwinCAT 3 solution also offers many advantages over the traditional PLC/HMI/Laptop combination we’re familiar with:  The development environment runs on the same machine as the PLC logic, so you don’t need a separate laptop. Going online is as simple as opening the development environment and clicking the Go Online button.  The HMI runs on the same machine as the PLC, so HMI-to-PLC communication responds incredibly fast. Transferring data between the TwinCAT 3 runtime and the HMI is as fast as a
  3. 3. Chapter 1: Introduction 3 memory copy instruction. I’ve been able to transfer hundreds of kilobytes of data from a PLC array to a .NET application in a fraction of a second.  If you’re into writing your own HMI software (for example in .NET), the driver for the protocol (called ADS) is included for free.  The TwinSAFE safety editor is integrated into the development environment, so mapping signals between your safety program and your PLC program is trivial, and safety inputs can also be double-mapped both to the safety program, and to your PLC program for monitoring and alarming.  You can use source control applications like git, mercurial or subversion, and they can even integrate with the development environment. Not only does TwinCAT 3 offer outstanding performance, but you can download it, install it, and try it out indefinitely for free! When you try to activate your first TwinCAT 3 PLC program, you’ll be prompted to generate a 7 day trial license. When that 7 day trial license expires, if you’re not done testing, you can just generate a new 7 day trial license without reinstalling. Obviously you wouldn’t be able to run this in a production environment if you had to do this every 7 days, but the trial is a fully functional version of TwinCAT 3. Want to try something on your test bench before you commit to implementing it in production? Just install the trial version on an old PC and test it out. I’ve been a control system programmer for over 15 years, and I’m also a .NET programmer, but I’m a ladder logic programmer first and foremost. If you’re a control system programmer in North America, you’re likely familiar with Allen-Bradley’s (or Rockwell Software’s) RSLogix family of control software. There is no doubt that RSLogix has set the standard for ladder logic editors, and to be completely honest, no other editor comes close to the user-friendliness of their development environment, and I’m including TwinCAT 3. Beckhoff is a German company and ladder logic just doesn’t seem to be popular on their side of the pond. TwinCAT 3’s ladder editor is a major improvement over the one in TwinCAT 2, but it still doesn’t have the polish you’d be used to if you’re coming from the RSLogix world. I guarantee you’ll be frustrated the first time you try it, but that’s why I’m writing this tutorial. In my experience, programming ladder logic in TwinCAT 3 can be just as productive as in RSLogix, and it doesn’t
  4. 4. Chapter 1: Introduction 4 need to be painful. Also, keep in mind that TwinCAT 3 is very new and Beckhoff continues to support and improve it. If you’re familiar with RSLogix 5000, you may find some of my examples familiar. I’ve tried to organize my TwinCAT 3 projects in a way that’s similar to how most RSLogix 5000 programmers would organize their projects. That made the transition easier for me, and I hope it will for you too.
  5. 5. Chapter 2: Quick Start 5 2 – Quick Start This “Quick Start” is actually rather long, but it’s going to take you through downloading, installing, configuring, programming, building, activating, going online, forcing, and even making online changes to a TwinCAT 3 PLC program. When you’re done you will have a basic understanding of the TwinCAT 3 system and how it works. Prerequisites TwinCAT 3 can run on a plain-vanilla copy of Windows 7. As of June 2016, Beckhoff says TwinCAT 3 is fully supported on Windows 10 (with TwinCAT version 3.1.4020.0). One of Beckhoff’s main product lines is industrial PCs and if you buy their industrial PCs, you’ll get a discount on the TwinCAT 3 license. Also, the license cost scales with the processing power of the PC. Their most expensive license tier is for “3rd party hardware”, which means any PC you didn’t buy from them. I have no opinion on whether you should buy a Beckhoff industrial PC or a commercial PC. One thing to keep in mind is that Beckhoff’s top of the line industrial PC won’t have quite as much processing power as the newest commercial PCs on the market today, so if you’re really concerned about performance, you’ll probably go with a commercial PC. On the other hand, industrial PCs are hardened against tougher environmental conditions like dirt and temperature, and they come in nicer form factors for mounting inside of a control panel. They also take a 24V input rather than running from the AC mains. Whatever you do, make sure you invest in a good UPS as well. BIOS Settings If you use a 3rd party PC, you may have to change the following settings in the BIOS:  Turn off Hyper-Threading (Intel Core-i7 specifically)  Turn on Intel Virtualization Technology Extensions (VT-x), which is required for the 64-bit version of TwinCAT 3
  6. 6. Chapter 2: Quick Start 6 Optional: I/O Whether or not you’re hooking up to a legacy system, or starting fresh, I highly recommend using an EtherCAT I/O bus. The performance is phenomenal compared to any other bus on the market today, including any other Ethernet-based technology, and even SERCOS. The price is also quite reasonable because the technology is based on commodity Ethernet hardware. If you do want to go with EtherCAT, you can’t just use any Ethernet card in the PC as your bus master. It has to be an Intel chip, as that’s the only chipset that Beckhoff’s EtherCAT bus master seems to support. While you can buy a compatible card from Beckhoff, I’ve also had success with commercial off-the-shelf Ethernet cards. Your mileage may vary. For a list of compatible Ethernet chips, do a Google search for beckhoff ethercat compatible cards or visit the following URL: /ethercat/html/ethercat_supnetworkcontroller.htm As of this moment, an Intel Gigabit CT PCI-E Network Adapter EXPI9301CTBLK is a reasonably priced commodity card that works well. If you want to try TwinCAT 3 without any hardware attached, you can do that too, and you won’t need an EtherCAT master at all. If you do happen to need to interface to legacy I/O buses like DeviceNET, rather than installing a DeviceNET bus master card in the PC itself, I highly recommend starting with an EtherCAT bus to an EtherCAT bus coupler such as an EK1100, and then buying one of the many different EtherCAT-to-whatever bridges that Beckhoff sells, as this is usually less expensive in the short run, and lets you expand your system with lower cost (and higher performance) EtherCAT I/O in the future. Optional: Visual Studio 2010 Professional If you’re already a .NET programmer then you may already have Visual Studio 2010 Professional installed. If that’s the case, TwinCAT 3 will actually install as an extension to VS2010. If you don’t have it installed, don’t worry; TwinCAT 3 will install the Visual Studio Shell instead.
  7. 7. Chapter 2: Quick Start 7 You may wonder if you can use the free versions of Visual Studio such as Visual C# 2010 Express edition or Visual Basic .NET 2010 Express Edition. While you can have them installed, and you can use them to write programs that communicate with the TwinCAT 3 runtime, TwinCAT 3 won’t install as an extension to these products. Downloading TwinCAT 3 The TwinCAT 3 installer is free to download, but it requires registration. Beckhoff periodically releases new versions, so to get the very latest, go to their product web page: Click the TE1xxx | Engineering link under the Software section. Click on the TwinCAT 3.1 – eXtended Automation Engineering (XAE) link. Note that XAE includes the runtime (XAR) as well. Once you register you’ll receive an email with download instructions. Download the .zip file and extract it to some temporary directory. Installing TwinCAT 3 In the directory where you unzipped the downloaded TwinCAT 3 archive, locate the “exe” file and double-click it. Follow the directions. Use the default options. When it prompts you about the Visual Studio 2010 shell, check the box to install it:
  8. 8. Chapter 2: Quick Start 8 You will have to restart before it completes. Create Your First TwinCAT 3 Project Now that you have TwinCAT 3 installed, check in your system tray for a new icon: Just for reference, the color of the icon (blue) means the TwinCAT 3 runtime (PLC/motion controller/etc.) is in Config mode. That’s similar to “program mode” on an Allen-Bradley PLC. When the runtime is started the icon will be green. Red means it’s stopped. Right-clicking on the icon will display a system menu:
  9. 9. Chapter 2: Quick Start 9 Select TwinCAT XAE from the system menu. (The “E” stands for “Engineering.” That’s the programming environment.) After the splash screen you’ll see the Visual Studio Start Page: Click the New Project… link (highlighted) on the left side of the page. That will display the New Project dialog: I’ve only installed TwinCAT 3 without installing Visual Studio 2010 Professional, so you can only see one project type: TwinCAT XAE Project. If you have Visual Studio 2010 Professional installed, you’ll see all the regular project types, plus this new TwinCAT XAE Project type. Make sure you’ve
  10. 10. Chapter 2: Quick Start 10 selected this type. Then give your project a suitable Name (see the highlighted field above). When you change the project name, the solution name will change to match. For our purposes they can be the same name. I chose “TwinCAT 3 Tutorial.” Click OK. This could take a minute. It’s building a new TwinCAT 3 project from a template. When it’s complete you’ll see a screen like this: All of the files for this project are organized in the Solution Explorer on the right. Here’s a brief explanation of each section: The top node in the tree is the “Solution.” This is actually a Visual Studio construct, not a TwinCAT 3 object. In Visual Studio, a Solution is a group of Visual Studio Projects and an associated “build order.” In our case there’s only one Visual Studio Project: TwinCAT 3 Tutorial. If you’re using Visual Studio 2010 Professional, you would be able to add additional projects under the solution, such as a C# or VB.NET project (perhaps an HMI or a data collection application?). This would be convenient simply because you could keep everything in one place and even use the integrated source control add-ins to manage everything in one environment. Under the project you have:  SYSTEM: this section manages the runtime including the licenses. You can configure how many PC processor cores to use, which PLC or motion tasks run on each core, and what percentage of each core’s processing power to allocate to each task. Note that it’s possible to connect to runtimes on other computers, but for now we’ll only be concerned with the local runtime.
  11. 11. Chapter 2: Quick Start 11  MOTION: this is where you add motion control tasks, and assign axes to each task. These tasks do the work of closing the control loops for you. Your PLC programs typically interface with the motion tasks using standard motion function blocks and the motion tasks do the heavy lifting of controlling the actual servo drives, etc. When you commission a new axis (setting up your motion parameters like speed, acceleration, deceleration, etc., you interact directly with the objects under the MOTION section of the tree).  PLC: this is where you add PLC projects. Each PLC project lets you define variables (memory assignment) and PLC logic.  SAFETY: if you’re using an EL6900 Safety PLC slice or the new TwinCAT 3 safety runtime (a certified safety PLC that runs on the PC itself), you can edit the safety logic here. This is handy because you can create connections between the PLC and the Safety logic for monitoring and status.  C++: one of the big new features or TwinCAT 3 is the ability to write C++ code that executes directly in the runtime.  I/O: this is where you configure your I/O network, and then create your mappings between all of the different modules. For example, if you define an input in the PLC module, you have to map it to a physical input in the I/O module. TwinCAT 3 Solution File Structure One of the interesting things about TwinCAT 3 compared to other PLC programming environments is that it stores the “solution” in a collection of files and directories rather than in a single monolithic file. If you open the directory where you asked it to create your solution, you’ll see the following:
  12. 12. Chapter 2: Quick Start 12 The TwinCAT 3 Tutorial.sln file is your “solution” file, and it corresponds to the top level node in your solution explorer in the right hand side of your TwinCAT XAE window. The TwinCAT 3 Tutorial folder corresponds to the TwinCAT 3 Tutorial project under the solution. If you double click on that folder, you’ll see a file called TwinCAT 3 Tutorial.tsproj: If you’re inquisitive, you can open this file with Notepad (or any text editor) and look at the contents. You’ll see that it’s just an XML file. When you start to add a PLC program or a Safety program in the editor, you’ll then see new folders created here, and the TwinCAT 3 Tutorial.tsproj file will include references to these child projects. Adding a PLC Project In TwinCAT 3, a “PLC” is like a “virtual” PLC. You can run multiple virtual PLCs on a single computer. This might actually be useful if you had a single PC controlling multiple machines. Each machine could be controlled by a single virtual PLC, which might be a good way to manage the complexity of a large system. You can also separate virtual PLCs by CPU core, so if your scan time started to get too high, you could break out part of that logic and run it in a separate virtual PLC and schedule the task that runs that second PLC on a different CPU core. Two virtual PLCs can still send data back and forth by mapping outputs on one PLC to inputs on the other PLC, and vice-versa. The simplest case is to create a single PLC project. Let’s do that now. Right-click on the PLC node in the Solution Explorer (highlighted):
  13. 13. Chapter 2: Quick Start 13 From the context menu that appears, select Add New Item… to display the following wizard: Enter a name for your new virtual PLC in the Name box (highlighted above). I chose “PLC1” but you may want to pick a more descriptive name, like the name of the machine or cell that this PLC will control. Standard PLC Project is the default template, so leave that selected and click the Add button in the bottom right. TwinCAT 3 will build a new PLC project for you from a template. This could take a few seconds to a few minutes depending on the speed of your computer. When it’s complete, you’ll see your new PLC in the Solution Explorer:
  14. 14. Chapter 2: Quick Start 14 It gets a little confusing to talk about the “PLC Project” now because there are so many nodes in the tree, so from now on I’ll call the nodes by their name: PLC1 or PLC1 Project. Most of the interesting parts are under the collapsed PLC1 Project node, so click on the triangle next to that node to expand it: Let’s go through them one at a time to explain their meaning:  External Types: you should never have to go in here, so don’t worry about it.  References: this is where you add references to external libraries (either ones that are included in TwinCAT 3, such as motion control libraries, or ones that you write yourself, which we’ll explain later).  DUTs, GVLs, POUs, and VISUs: these are just convenience folders that are created by TwinCAT 3, and it’s where you’re supposed to create your Data Unit Types, Global Variable Lists, Program Organization Units, and Visualizations, respectively. What do those mean?  o Data Unit Type (DUT): this is similar to a structure or a user-defined type in other programming languages. It allows you to group a few pieces of data together into a single composite piece of data.
  15. 15. Chapter 2: Quick Start 15 o Global Variable List (GVL): as the name suggests, this is a list of variables (memory locations) that will be accessible from everywhere in this PLC (but not other PLCs) and can be accessed from your HMI. o Program Organization Unit (POU): contains logic (such as ladder logic, function block diagram logic, structured text, etc.) and associated local variables that are only accessible from inside that logic. There are 3 types of POUs: Programs, Functions, and Function Blocks, which will be explained later. o Visualization (VISU): these are your HMI screens. TwinCAT 3 has a built-in HMI system that takes advantage of the fact that you’re already running TwinCAT 3 on a computer with a screen. This is an optional add-on (sometimes called a “supplement”). You have to pay extra for the visualization license if you want to use it in a production machine, but in my experience it’s a reasonable price. Note that you can also use 3rd party HMI/SCADA systems with TwinCAT 3, and you can write your own .NET program. The 3rd party solutions typically use OPC for communication, and .NET programs use Beckhoff’s free DLL that lets you communicate directly with the runtime using their proprietary ADS communication library. When you created the PLC project, TwinCAT 3 automatically created the first POU for you (a Program called MAIN). It did this so that it could automatically create a Task for you. To explain what this means, I’ve expanded a few more nodes in the Solution Explorer tree:
  16. 16. Chapter 2: Quick Start 16 I’ve highlighted the important nodes, above. Under SYSTEM > Tasks, there is a new Task called PlcTask. A Task is what gets scheduled to run on the TwinCAT 3 runtime (that is, you can’t run a Program directly, you have to create a Task, and the Task then runs your Program). The Task has certain attributes, like how often to run. Double-click on the PlcTask node under the SYSTEM > Tasks node, and you’ll see this properties page for the Task:
  17. 17. Chapter 2: Quick Start 17 Note the two highlighted fields above next to the Cycle ticks field. By default the task is configured to run once every 10 cycle ticks, and that corresponds to once every 10 ms. That means the TwinCAT 3 runtime itself is actually configured to “wake up” once per millisecond, and every 10 times it wakes up, it executes this Task. You can then configure what this Task does when it runs. TwinCAT 3 has already done this by linkingPlcTask to the MAIN program in PLC1. That means our program called MAIN in PLC1 will be executed once every 10 ms. Configuring the Real-Time All of the editing we’ve been doing in TwinCAT 3 XAE is a normal Windows program, and Windows is a general-purpose operating system, not a real-time operating system. The runtime component of TwinCAT 3 (called XAR) has to run under real-time conditions so that it won’t be pre-empted by other tasks on the computer while it’s busy executing machine control logic. The TwinCAT 3 runtime pre-empts normal Windows programs by running in “ring 0” execution mode. In Windows there are only two execution modes: ring 0 and ring 3. Ring 0 is “kernel” mode,
  18. 18. Chapter 2: Quick Start 18 which is where all drivers and some internal windows code runs, and ring 3 is “user” mode, which is where normal windows programs run. The runtime registers a timer interrupt to force execution of the runtime at a regular interval (called the clock tick). Interrupt routines run under ring 0, or kernel mode, so the runtime has access to the full resources of the computer. The runtime then executes Tasks, and each Task can do things like run PLC Programs, do Motion Control, interface with the EtherCAT I/O bus, or manage communications with the HMI. These interrupts pre-empt ring 3 (user-mode) programs so the runtime always gets priority over normal Windows programs, like the TwinCAT 3 editor or your HMI. To configure the real-time behavior of TwinCAT 3, double-click on the SYSTEM > Real- Time node in the Solution Explorer (highlighted): That will display the Real-Time configuration window:
  19. 19. Chapter 2: Quick Start 19 Notice that the “Available CPUs” shows only one CPU and it’s allocated to Windows. This is actually incorrect, because my computer is a Core i3 with 4 logical cores. Click the Read from Target button to make TwinCAT 3 read the actual configuration from the PC:
  20. 20. Chapter 2: Quick Start 20 Now it correctly shows 4 cores. The cores are listed in the top list box, numbered 0, 1, 2, and 3. This configuration allows you to allocate cores between Windows, the TwinCAT 3 runtime, or both (or neither). I have found that mixing Windows and TwinCAT 3 on the same core might cause problems (at least in earlier versions of TwinCAT 3), so if you have a 4-core machine, I recommend allocating 2 cores for Windows and 2 cores for TwinCAT 3 runtimes. Changing this allocation requires a reboot, so save everything first. Warning: only use the core isolation feature on Windows 10 if you have build 4020.0 or later. The “core isolation” feature is not compatible with Windows 10 in earlier versions. As far as I have been told, prior to build 4020.0, TwinCAT 3 won’t be able to see the cores set to “Other” and the only way to fix it is to use the “Reset this PC” feature of Windows 10.
  21. 21. Chapter 2: Quick Start 21 If you have Windows 7, to change the core allocation, first click the Set on target button and the following window will pop up: Here, we just set the number of cores available to Windows, and the remainder will be available to the TwinCAT 3 runtime. Change the number 4 to a 2, and then click the Setbutton: Click OK to the confirmation dialog box: Then click OK to the Reboot question (save and close everything except TwinCAT 3 first):
  22. 22. Chapter 2: Quick Start 22 Hang on while the system reboots. Once it has rebooted, open the TwinCAT 3 solution again (either by double-clicking on the TwinCAT 3 Tutorial.sln file wherever you saved it, or by opening TwinCAT 3 XAE again and selecting it from the Recent Files list. Now double-click on the SYSTEM > Real-Time node in the Solution Explorer again, and the real- time configuration window will look like this:
  23. 23. Chapter 2: Quick Start 23 Notice that CPUs 0 and 1 still say “Windows” but cores 2 and 3 now say “Other”. Now we want to configure the TwinCAT 3 runtime to use cores 2 and 3. Under the RT-CPUcolumn, check the checkboxes next to cores 2 and 3, and uncheck the checkbox next to core 0: Notice that the CPU Limit column showed 80% next to core 0 when it was checked but shows 100% next to cores 2 and 3. That’s because when the TwinCAT 3 runtime has to share a core with Windows, we have to limit how much CPU time it can use, so that Windows still has some time to run user programs. However, when the runtime has a core all to itself, it can use to up 100% of the CPU time on that core. The lower grid allows you to configure which tasks run on which core. Currently there are only 2 tasks: PlcTask and PlcAuxTask. The first is the task that was created when we created the PLC1 project. The second is an automatically created “housekeeping” task. For now, both are set to run on core 2, which is a bit wasteful of core 3, but in most real applications there’s a good chance of
  24. 24. Chapter 2: Quick Start 24 using two real-time cores. If your application has any motion control, it’s typical to run the motion control task on a separate core, and if you had more than one virtual PLC, you can choose to run them on different cores to balance the load. Next, check the Base Time columns in the grids above. By default, the TwinCAT 3 runtime “wakes up” every 1 millisecond and checks if it needs to execute any Tasks. You can optionally change the Base Time in the upper grid. 1 millisecond is actually the slowest option. I find that 0.5 ms (500 us) works quite well for most PLC tasks. Note that this is much faster than you’ll be used to if you come from a more traditional PLC brand. In the lower grid, you can see that even though PlcTask is running on core 2 with a 1 ms base time, it only runs once every 10 Cycle Ticks, so it effectively only runs once every 10 ms. I normally set this to 1 Cycle Tick so the PLC task would run every time the runtime wakes up. Note that your I/O refresh is tied to the speed of the Task using the I/O. That means if you set your PlcTask to run every 1 ms, then any I/O mapped to that Task also has to refresh once every 1 ms. The EtherCAT I/O bus is actually fast enough to do this even with a rather large number of devices on the bus. To change the PlcTask so that it runs every 1 ms, double click on the SYSTEM > Tasks > PlcTask node in the Solution Explorer and change the Cycle ticks from 10 to 1:
  25. 25. Chapter 2: Quick Start 25 Edit the PLC Logic Add a Global Variable List Let’s assume we’re going to program a grinding machine. Perhaps there’s a grinding wheel that needs to be turned on and off via a motor starter. Let’s start by declaring some variables for our PLC to interface with the outside world. Under the PLC1 project, right click on the GVLs folder (highlighted): From the context menu that appears, choose Add > Global Variable List… A dialog box will appear where you can enter a name for your new Global Variable List. Let’s enter a suitable name for this list, like Grinder:
  26. 26. Chapter 2: Quick Start 26 Then click the Open button. This will do 2 things: it will add a new Global Variable List in the GVLs folder, and it will open the new Grinders GVL for editing. Your PLC1 project will now look like this in the Solution Explorer:
  27. 27. Chapter 2: Quick Start 27 …and the main editing area will now have a window open for editing the GVL: An empty Global Variable List isn’t very useful, so let’s add some variables. You’ll have to type the following exactly correctly between the VAR_GLOBAL and END_VARlines: Note that I’ve created 3 variables, all of which are of type BOOL. The first variable (GrindingWheelMS) will represent the output for the motor starter that turns on the grinding wheel. The grinding wheel will run as long as this variable is on. The other two variables represent the inputs for start and stop pushbuttons (PBs) for the grinding wheel. We haven’t actually declared them as real outputs or inputs yet, but we’re going to come back to that later. A BOOL value in TwinCAT 3 can take on two values: TRUE and FALSE. These variables can be used anywhere in the PLC program. It’s possible to create two Global Variable Lists that both have a variable of the same name. In that case, if you used that variable name in your program, when you tried to build your PLC project, the compiler will complain that the name is “ambiguous”. In that case you will have to prefix the variable name with the name of your Global Variable List. Due to this possibility, I always use the fully-qualified name (including the Global Variable List name) whenever I use a global variable in my logic, and I will do that in the rest of this tutorial. This is optional (and unnecessary) if you only have one GVL. Adding a Ladder Logic Program Now that we have some variables to control, let’s write some logic to control them. Right click on the POUs folder in the Solution Explorer and choose Add > POU…
  28. 28. Chapter 2: Quick Start 28 In the Add POU dialog that pops up, enter a name for the new Program (RunGrindingWheel), choose Program under Type, and at the bottom under Implementation Language, choose Ladder Logic Diagram (LD): Then click the Open button. Your new Program will show up under the POUs folder in the Solution Explorer, and the Program will be opened for editing in the main window:
  29. 29. Chapter 2: Quick Start 29 The editing screen is split into two parts. At the top is your list of variable declarations. These are similar to the variable declarations in a Global Variable List, but any variables declared here can only be used within this Program. It’s a useful place to declare variables for storing temporary values or helper coils. In order to write a simple start/stop rung, we won’t need to declare any local variables. The bottom part of the screen is where you write the ladder logic. The numeral “1” indicates that it has already added a blank rung #1 for you. Let’s start by adding a coil to this rung. You can right click on the rung and choose Insert Coil from the context menu, or you can click the coil icon on the ladder logic toolbar at the top of the screen: If you don’t see that toolbar, it might be hidden. Try right clicking on the blank toolbar spaces at the top of the screen and selecting the TwinCAT PLC FBD/LD/IL toolbar. A third option is to click on the Toolbox vertical tab on the far left of the screen and drag and drop the coil icon from the toolbox over to the empty rung. Any of those options will result in a new coil being added to your empty rung: Notice that the coil has three question marks over it. This is where you have to enter the name of the variable you want to assign to this coil. Type the fully-qualified name of the grinding wheel motor starter variable into this field: Grinder.GrindingWheelMS:
  30. 30. Chapter 2: Quick Start 30 Now let’s add the start button. The easiest way is to click on the rung right where the small tick- mark is in the center of the rung, and then right-click and choose Insert Contact from the context menu. Now you will see a contact inserted on the left of the rung: Then enter the fully-qualified variable name for the start push button: Grinder.StartGrindingWheelPB: That will turn the motor starter on when the start pushbutton turns on, but of course it won’t stay on unless we add a seal-in circuit. To add a branch around the start button contact, select the contact, right click, and choose Insert Contact Parallel (below) from the context menu: Edit the three question marks over the new parallel contact and change it to Grinder.GrindingWheelMS so that the coil seals itself in:
  31. 31. Chapter 2: Quick Start 31 Now the motor starter will stay on after the start pushbutton input turns off, but it will keep running forever. Finally let’s add the stop pushbutton into the circuit as a normally closed contact. Select the section of rung between the branch on the left and the coil on the right (where the small tick mark is). Right click on this section of rung, and choose Insert Negated Contact from the context menu: Finally, replace the three question marks above the normally closed contact with the fully-qualified variable name of the stop pushbutton: Grinder.StopGrindingWheelPB: Finally, our start/stop circuit is complete! Remember to click the Save All button on the toolbar (it looks like a stack of three floppy disks). Calling the Ladder Logic Program from MAIN There’s one last thing we have to do before we can run our program. When the PlcTaskruns, it will only execute the MAIN program, not our new RunGrindingWheelprogram. To get our program to execute every 1 ms, we need to “call” it from the MAINprogram. Double click on the MAIN program in the POUs folder of the Solution Explorer:
  32. 32. Chapter 2: Quick Start 32 That will open the program in the Structured Text editor: This looks very similar to the RunGrindingWheel program when we first opened it, but in this case, everything in the bottom is in Structured Text (ST) language instead of Ladder Diagram (LD). If you want, you can delete the MAIN program and replace it with a new MAIN program that uses Ladder Diagram. You have to remember to link thePlcTask to this new MAIN program because when you delete the old one it will lose the link. However, since the MAIN program’s only job is to call other programs (in our example), it’s simple enough to do this in Structured Text. Change line 1 of the MAIN program to the following:
  33. 33. Chapter 2: Quick Start 33 That is, it’s just the name of the program you want to call, following by an open and a closed bracket, and finally a semicolon. All statements in Structured Text end in a semi-colon. You could add other program calls below this one on new lines if you wanted. The program will call them once, in sequence, every time it runs (which is once every millisecond). Downloading and Going Online Build the PLC Project It’s a good idea to “build” the PLC project before you try to download it. This will tell you if you have any syntax errors or misspelled variable names. In the Solution Explorer, right click on the PLC1 Project node and choose Build from the context menu: This could take a minute while it compiles the PLC project. At the bottom of the screen, there’s a tab called Output, and it will show you the progress of the compiler:
  34. 34. Chapter 2: Quick Start 34 Take a look at the last line to see if there were any errors. You want it to say “1 succeeded” and “0 failed”. If it failed to build, you should look for error messages earlier in the output messages. Double-clicking on the error message should take you to the site of the error, or close to it. Activate the Configuration Now that our PLC project compiled successfully, the next step is to “activate the configuration”. What this does is: 1. Stop the TwinCAT 3 runtime (all running programs will halt, and I/O will turn off) 2. Apply the real-time configuration to the runtime (number of cores, tasks, etc.) 3. Copy the compiled program(s) to the runtime 4. Apply the “mapping” configuration (we will discuss mapping later) 5. Restart the TwinCAT 3 runtime in run mode Note that when the runtime starts, it won’t automatically load the PLC program unless we “activate it as the boot project”, and it won’t start executing the PLC program unless we configure it to “autostart the boot project”. Do these two things by right clicking on the PLC1 node in the Solution Explorer:
  35. 35. Chapter 2: Quick Start 35 …and then choose Activate Boot Project… from the context menu, and then do it again and choose Autostart Boot Project. Now go to the top menu and choose TwinCAT > Activate Configuration from the menu. You will have to confirm this action with the following dialog box: Click the OK button. Since we haven’t purchased a runtime license for this machine, it’s going to ask us if we want to generate “trial licenses”:
  36. 36. Chapter 2: Quick Start 36 Click the Yes button. Then it will ask you to enter a captcha-type randomly generated group of characters to prevent you from automating the generation of trial licenses. Enter the letters in the text box underneath exactly as they appear (yours will be different than mine): Then click the OK button. This generates a “trial” license which will expire after 7 days. Don’t worry too much about exceeding this 7-day limit though, as you can just generate another 7-day license when that happens. You will have to purchase an actual license only when you deploy to a production system. After generating the trial license, it will ask you if you want to restart in run mode: Click the OK button. You should see the TwinCAT icon in the system tray (if it’s visible) turn from blue (config mode) to red (stopped) and then finally to green (running). If that happens, the TwinCAT 3 runtime is running in run mode on your PC! If you look at the PLC1 node in the Solution Explorer window, you will also notice that it now displays a green rectangle, indicating that the PLC program is running:
  37. 37. Chapter 2: Quick Start 37 Go Online Like most other modern PLCs, TwinCAT 3 supports online debugging. To see this in action, start by double-clicking on the RunGrindingWheel program so that it’s open in the editor’s main window. Then select PLC > Login from the main menu: That puts the system into “online” mode and you can view the current state of the logic. Power is represented by the blue lines, and the status of the contacts and coils are represented by the blue rectangles in the middle of each. As you can see above, the Grinder.GrindingWheelMS coil is currently off, as are the start and stop pushbuttons. Write Values to Variables (Online) Even though the pushbuttons and motor starter variables aren’t connected to anything physical, the code is running. We can watch the state of the motor starter variable change by writing new values to the pushbutton variables. Let’s start by simulating someone pressing the start pushbutton. To do that, we’re going to write the value TRUE to Grinder.StartGrindingWheelPB. The first step is to queue a value to write. Hover your mouse over the center of the Grinder.StartGrindingWheelPB contact and double-click the small rectangle in the center: Next to the contact you can now see a queued write value (“TRUE“). You can change the queued write value to FALSE by double-clicking it again, and remove the queued write value entirely by double-clicking it a third time. When you’re ready to write the queued values to the PLC variables,
  38. 38. Chapter 2: Quick Start 38 choose PLC > Write values to all online applications from the drop-down menu at the top of the screen. You will immediately see the state of the rung change to reflect the new value: As you can see, simulating the start pushbutton turning on caused the logic to turn on the Grinder.GrindingWheelMS motor starter variable. Now let’s simulate releasing the start pushbutton by writing the value FALSE to the start pushbutton: …and write the values by choosing PLC > Write values to all online applications from the drop- down menu at the top of the screen: You can see that the motor starter variable (coil) stayed on. To finish the example, let’s simulate someone pressing the stop pushbutton by writing the value TRUE to the Grinder.StopGrindingWheelPB contact:
  39. 39. Chapter 2: Quick Start 39 Writing the value then turns off the motor starter coil: Writing a value to a variable is a one-time operation, so if you tried to write the valueTRUE to the motor starter coil, it won’t appear to have any effect, because 1 millisecond later, the program logic will execute and change the value back to FALSE. If you want to override the logic, you need to use the “force.” Force Variables (Online) Forcing a variable is similar to writing a variable, except that the force overrides the logic of the program. For instance, we can force the motor starter coil to TRUE even though the logic is trying to keep it turned off. Start by double-clicking on the small rectangle in the middle of the motor starter coil: You can see that we’ve queued the value TRUE, just like if we were going to do a variable write. However, in this case we’re going to choose PLC > Force values to all online applications from the menu at the top of the screen:
  40. 40. Chapter 2: Quick Start 40 Forced variables are indicated with a small “F” in a red box next to the contact or coil that is forced. These variables will stay forced until you choose PLC > Unforce all values on all online applications from the menu at the top of the screen. You will also be asked if you want to unforce existing forces if you logout (go offline). Using the TwinCAT PLC Toolbar We’ve been going through the PLC menu at the top of the screen for all of the online functions, but there is also a toolbar that can give you quick access to these functions. It looks like this: If you don’t see it, try right right-clicking on the toolbar area near the top of the screen and making sure that the TwinCAT PLC option is checked. If it’s already checked and you can’t see it, then you might have too many toolbars on one line, and that would force it to shrink the toolbar to almost nothing, like this: If that’s the case, drag and drop the shrunk toolbar onto a new empty toolbar line and it will expand fully for you. Making Online Changes to PLC Programs TwinCAT 3 supports online changes to PLC program logic and variables. TwinCAT 3 does not support online changes to the mapping between your PLC program and your physical I/O, so if you want to add or remove I/O, or you want to change the mapping between your PLC I/O and your physical I/O, you have to use TwinCAT > Activate Configuration from the top menu, and you will then have to restart the runtime, which will restart your PLC programs. This will cause your machine to stop. The process for making an online change to a PLC program is: 1. Make sure you are offline (logged out). 2. Edit your PLC program logic and variables.
  41. 41. Chapter 2: Quick Start 41 3. Login (at the prompt, select Login with online change). 4. If you’ve edited a variable (for instance, changed the type), it will warn you that the variable will be moved to a new memory location, and ask if you want to continue. This is safe to do unless you have an external program (like an HMI or a data collection system) reading or write variables in the PLC, in which case you may want to shut them down before continuing. 5. Click Yes when it asks if you want to “update the boot project” (if you say No then your changes will be lost if you restart the runtime or reboot the computer). Your changes will be applied without stopping the PLC program, and without any interruption to the machine. Now let’s make a change to our logic. Stop buttons on machines are sometimes wired using a normally closed contact instead of a normally open contact (so the input is on when nobody is pushing the button and the input turns off when someone pushes it). The reason for this is so that the machine will stop if the wiring to the stop button is disconnected (and it also allows you to chain stop buttons in series). Let’s change our grinding wheel start/stop logic to work with a normally closed stop pushbutton. First, make sure that you are offline. Choose PLC > Logout from the menu if you haven’t done so already. Here is the original logic: Left-click to select the contact in the middle (Grinder.StopGrindingWheelPB): TwinCAT 3 has a handle shortcut for changing a normally closed contact to a normally open contact, or vice-versa: just press the slash key (“/”). Now your logic will look like this:
  42. 42. Chapter 2: Quick Start 42 Login to the PLC by choosing PLC > Login from the menu. TwinCAT 3 will notice that the logic has changed and will ask you what you want to do: Leave Login with online change selected and click OK. Next it will ask you if you want to update the boot project: Click Yes. After that you will be online with the PLC, and your changes will be applied:
  43. 43. Chapter 2: Quick Start 43 Notice that the Grinder.StopGrindingWheelPB contact is now a normally open contact, meaning the input has to turn off to stop the grinding wheel. Designating PLC Inputs and Outputs When we built our example PLC program above, we didn’t actually define which variables were inputs and which were outputs, so as far as the runtime was concerned, all of the variables were internal variables and the PLC didn’t interact with any physical I/O. Designating a variable as an input or output only makes it available for mapping to a physical input or output during the mapping phase (after we’ve configured our I/O devices, which will be covered later). We designate a variable as an input or output by modifying the variable declaration. Here is the original list of variables in the Grinder Global Variable List: First let’s designate the GrindingWheelMS variable as an output. Change the variable declaration to the following:
  44. 44. Chapter 2: Quick Start 44 As you can see, I’ve added AT %Q* directly after the variable name. The Q means output. You can designate the other two variables as inputs like this: This is the same, but I’ve replaced the Q with an I meaning “input.” I know this is a weird syntax, but it’s a throwback to processors where you could (or had to) explicitly map variables to an input or output memory area. In this case, the asterisk means “I don’t care where you put it, just put it in the input or output map accordingly.” Now you have to “build” the PLC project to see these variables show up on the PLC’s input or output map. Right-click on the PLC1 Project node in the Solution Explorer and choose Build from the context menu: After the project is compiled, you will now see two new nodes under the PLC1 Instance node:
  45. 45. Chapter 2: Quick Start 45 Expand the inputs and outputs by clicking on the small triangle next to each node: Now you can see the variables that you designated as inputs and outputs are available here for mapping. Normally you will map these variables to physical I/O, but they can also be mapped to I/O in the motion control task, the Safety program, or even to I/O from another PLC. That’s how you would be able to interlock two PLC programs together virtually without running any physical wiring. The runtime takes care of copying the data between each task, or between tasks and physical I/O.
  46. 46. Chapter 2: Quick Start 46 Beware that if you change the name or type of a variable that has been designated as an input or output, TwinCAT 3 will unmap that variable from any existing mappings, and will only give you a rather easy-to-miss message in the output window when the PLC project builds. When you activate the configuration and restart, you may be left wondering why your output won’t turn on, or why your start button isn’t working. Note that when you’ve mapped a variable, the icon will change to include a small arrow, so you can tell which ones are mapped: (All I did here was map the PLC output Grinder.GrindingWheelMS back to PLC input Grinder.StartGrindingWheelPB, which is a rather silly thing to do in real life.) Whew! That concludes the Quickstart chapter of this tutorial! You’ve now covered all the basics of downloading, installing, configuring, programming, going online, forcing, and making online changes to your PLC program in TwinCAT 3. That’s a lot of new information, but I hope it gives you a good enough introduction to feel like you can experiment and play around with the system some more. When you’re ready, you can move forward in the tutorial with more advanced topics.
  47. 47. Chapter 3: Structuring PLC Data 47 3 – Structuring PLC Data TwinCAT 3 gives you a lot of options about how to organize the data (whether Boolean, integer, floating point, string, or user defined data) in your PLC project. As with any PLC project, you want your data structures to follow naturally from the actual machine it’s controlling. I think we can all agree that Infeed.Conveyor.Running is easier to understand than bit[328]. Global vs Local Variables If you’re coming from the RSLogix 5000 world then you’re probably already familiar with the concept of global vs. local variables. A ControlLogix has “controller scope” and “program scope” tags. Essentially “controller scope” tags are global (because every program can see them) and “program scope” is local because only the program they’re defined in can see them. It’s also pretty common to come across PLC projects where all the tags are declared in “controller scope”. TwinCAT 3 also has global variables and local variables. Global variables live in “Global Variable Lists” and Local variables live inside programs, function blocks and functions (a.k.a “POUs”). As for what should go where, that’s ultimately your decision, but here are the rough guidelines I use:  Inputs and Outputs: Global  HMI Buttons and Indicators: Global  HMI Alarms: Global  Faults: Global  Interlocks: Global  Everything Else: Local What do I mean by “Interlocks”? When you divide up your program, you typically divide it into modules that physically match your machine, so you might have a program for the Infeed Conveyor, one for the Pick & Place, and one for a Robot. Most of your Infeed Conveyor logic shouldn’t care about the Pick & Place logic, except that you might want to prevent the Infeed Conveyor from running if the Pick & Place isn’t out of the way of the conveyor. In that case, you probably want to create a global PickAndPlace.ClearOfInfeedConveyor variable.
  48. 48. Chapter 3: Structuring PLC Data 48 The Pick & Place logic is responsible for setting this using a coil, and the Infeed Conveyor logic uses it to prevent running the conveyor. This is an “interlock” signal and since two different programs need to access it, then it’s a good candidate for a global variable. You’ll also notice that everything accessible from an HMI is also global. This is just my preference. You don’t have to do that… an HMI can access local variables, but since an HMI-accessed variable is kind of like an interlock, I like to give them Global status. When someone is reading or modifying your PLC logic they’ll tend to make the assumption that Local variables are only accessed, well… locally. That means when they want to make a change, they’ll only check for usages of the variable within that local scope. Checking the HMI for references to that variable is much harder. That’s why I suggest making HMI-accessed variables Global and also indicating with a comment that they are accessed from the HMI. Global Variable Lists When you created your PLC project in TwinCAT 3, the wizard automatically creates a GVLs folder: “GVL” stands for “Global Variable List.” It’s Beckhoff’s intention that you should put all your global variable lists in the GVLs folder, but I think that’s incorrect. The organization and structure of your PLC project should mimic the physical and logical organization of your machine. Let’s continue
  49. 49. Chapter 3: Structuring PLC Data 49 our example of a machine with an infeed conveyor followed by a pick & place. If those are two major components of the machine, then that’s a logical way to break down our logic and data. Let’s create two folders under our project called InfeedConveyor and PickAndPlacerespectively. Start by right clicking on the PLC Project node and selecting Add -> New Folder from the context menu. That will create a new folder called NewFolder1 and you can change the name to InfeedConveyor: You can do the same to add a PickAndPlace folder: I want to stop here and talk about folder ordering. First of all, TwinCAT 3 will order the folders and items in a folder alphabetically. Secondly, TwinCAT 3 has a bug where it will only re-order them after you save your project, close the solution and open it again. Initially they show up based on the original folder name, which was NewFolder1 (hopefully this is fixed in a later version). Since the folders represent the major components of our machine, we want the ordering to flow logically
  50. 50. Chapter 3: Structuring PLC Data 50 from the way the machine works. If the machine works by parts being introduced to the machine on the infeed conveyor, and are then processed by the pick & place, then it makes the most sense to have the InfeedConveyor folder come before PickAndPlace folder. It just so happens that “I” comes before “P” in the alphabet, but this is only a happy coincidence. That’s why I suggest prefixing each folder with a number so you can enforce a logical ordering: I used two digit numbers because that will allow it to sort correctly from 01 through 99. Don’t worry about needing to insert one later as renumbering even 10 or 20 folders doesn’t take very long. Now let’s add a Global Variable List for the infeed conveyor. Right click on the01_InfeedConveyor folder and select Add -> Global Variable List… from the context menu. That will display the Add Global Variable List dialog. Enter InfeedConveyorin the Name text box and click the Open button:
  51. 51. Chapter 3: Structuring PLC Data 51 Now you’ll see an empty global variable list in the editor: Now we have to imagine some global variables that our imaginary conveyor might have. I think it needs an output to turn on the motor (we’ll call that “Run”), a through-beam sensor across the end of the conveyor to sense when a part reaches the pick position (we’ll call that the “NoPart” input) and maybe this conveyor needs to signal to the pick & place that the conveyor is stopped (we’ll call that the “Stopped” interlock). Here’s what a global variable list with those 3 variables would look like:
  52. 52. Chapter 3: Structuring PLC Data 52 Let’s look at the first variable: NoPart AT %I* : BOOL; (* Through-beam sensor *) The line starts with the variable name (NoPart). Typical variable naming rules apply, so you can’t start the name with a number, and you can’t have spaces or special characters in the name, except an underscore. Here I’ve used the PascalCase way of writing the variable, by sticking capitalized words together. You don’t have to use PascalCase, but you should pick a consistent way of naming your variables and stick with it. After the variable name is an optional element that defines the variable as an input or output (AT %I*). The “I” means input and a “Q” means output. Adding this element will force the variable to show up in the PLC project’s I/O map which makes it available for linking to physical I/O. Inputs are set by the input scan before your logic runs, and outputs are set by your logic, but copied to the physical outputs during the next output scan. (Technically the input and output scans happen at the same time.) A colon (:) separates the declaration of the variable from the variable type (BOOL). Here are the common types you’ll use, though there are more:  BOOL: A boolean value (TRUE or FALSE)  BYTE: An 8-bit unsigned integer value (0 to 255) aka USINT  SINT: An 8-bit signed integer value (-128 to 127)  WORD: A 16-bit unsigned integer value (0 to 65,535) aka UINT  INT: A 16-bit signed integer value (−32,768 to 32,767)  DWORD: A 32-bit unsigned integer value (0 to 4,294,967,295) aka UDINT  DINT: A 32-bit signed integer value (−2,147,483,648 to 2,147,483,647)  ULINT: A 64-bit unsigned integer value (0 to 18,446,744,073,709,551,615), new in TwinCAT 3
  53. 53. Chapter 3: Structuring PLC Data 53  LINT: A 64-bit signed integer value (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807), new in TwinCAT 3  REAL: A 32-bit floating point value  LREAL: A 64-bit floating point value  STRING: An ASCII null-terminated string, default 80 characters  STRING(n): An ASCII null-terminated string, with max length “n” characters  TIME: A 32-bit time value (typically used in timers) A note on how much memory each one takes: for anything that says “8-bit”, “16-bit”, “32-bit” or “64-bit” then the memory usage is 1 byte, 2 bytes, 4 bytes, or 8 bytes respectively. A BOOL could be represented by a single bit, but takes a full byte (this is for performance reasons). There is also a rarely used data type called BIT which uses a single bit, and can have the values 0 and 1, but this is not equivalent to a BOOL. ASTRING takes 81 bytes (80 for the characters and 1 for the null terminator) and a STRING(n) takes n+1 bytes. Beckhoff’s Infosys site has more information about TwinCAT 3 Data Types. After the data type, there is a terminating semi-colon (;). The compiler stops reading here. After the semi-colon you can put an optional comment ((* Through-beam sensor *)). There are two ways to insert comments: you can enclose them in bracket-asterisks, as I did, or you can preface them with a double-slash (//). Note that comments will show up as tool-tips when you hover your mouse over any use of this variable in your logic, so they are helpful. The other thing that shows up in a tool-tip over a variable is the data type (BOOL, INT, etc.). Long before we had helpful features like this in our IDE, programmers invented a system for embedding the type of the variable in the variable name called Hungarian Notation. You will often see TwinCAT code examples, even in the official documentation, that use Hungarian Notation (such as bIsTRUE : BOOL;). This is now discouraged thanks to smarter and more helpful editors. In general you should avoid Hungarian Notation in your TwinCAT 3 programs. When you refer to global variables in your logic, you should use the fully qualified name of the variable (including the Global Variable List name) such as InfeedConveyor.Run. Technically it will let you omit the Global Variable List name and just use the variable name (Run). This is a throw-back to TwinCAT 2 where there was only one Global Variable List. You don’t want
  54. 54. Chapter 3: Structuring PLC Data 54 to run into a situation where it gets confused with another global variable called Run in another Global Variable List (OutfeedConveyor.Run would be an obvious one). If you happen to do this, the compiler will give you an error telling you that you have an ambiguous variable name and it will force you to use the fully qualified name. I suggest using fully qualified names for all global variables. Adding Structure(s) A conveyor is a pretty simple piece of equipment and I doubt you’d want to break up the structure of the InfeedConveyor Global Variable List into smaller pieces, but for a larger part of the machine you might want to. For instance, the pick & place might have two positions (Pick and Place). Rather than having variables such asPickAndPlace.InPickPosition it’s a bit nicer to havePickAndPlace.Pick.InPosition (I realize some of the reasons why it’s nicer might not be obvious at this point, but trust me). You can accomplish this with TwinCAT 3’s Structure, which is a kind of Data Unit Type, a.k.a. “DUT”. In the RSLogix 5000 world, this is called a “UDT” meaning “user defined type.” Let’s start by creating a Structure for the pick & place’s Pick position. Begin by right clicking on the 02_PickAndPlace folder and selecting Add -> DUT…, which will open the Add DUT dialog window. Enter PickAndPlace_Pick in the Name text box. Make sure the Structure radio button is selected in the Type group box. Then click the Open button:
  55. 55. Chapter 3: Structuring PLC Data 55 That will generate a new (empty) structure in the editor window: Any variables we add here will show up prefixed with PickAndPlace.Pick in their fully qualified name. Add an InPosition variable like this:
  56. 56. Chapter 3: Structuring PLC Data 56 Now let’s create a new PickAndPlace Global Variable List. Right click on the 02_PickAndPlace folder, use Add -> Global Variable List… and after creating it, add this variable: Now we’ve created a variable called PickAndPlace.Pick.InPosition. Note that you can also define inputs and outputs inside your structure (by adding AT %I* orAT %Q* respectively). Arrays It’s often advantageous to declare a numbered list of variables, and for this we traditionally use arrays. TwinCAT 3 has full support of arrays of any type. The syntax for declaring an array variable looks like this: To use this array in your logic, it would look like this: ExampleGlobalVariableList.SomeArrayVariable[1]. That would be the first element. The last element in the array would be ExampleGlobalVariableList.SomeArrayVariable[10]. Note that the syntax ARRAY[lower..upper] OF allows you to define any lower or upper bounds you like. Unlike a language like C, your lower bound doesn’t have to be zero. The total number of elements in the array is upper - lower + 1. You can also define multi-dimensional arrays like this:
  57. 57. Chapter 3: Structuring PLC Data 57 You could access the first element of the array like this: ExampleGlobalVariableList.SomeArrayVariable[1,50] and the last element asExampleGlobalVariableList.SomeArrayVariable[10,55]. Caution: when some programmers graduated from RLogix 500 to RSLogix 5000 and were first introduced to tags, they just didn’t “get” it. They wanted their nice safeB3:0/5 or whatever. Since the concept of tags was confusing, they just created a big controller-scope array tag called bits and used bits[0], bits[1], bits[2], etc. in their logic. It was a bad idea, but doing the same thing in TwinCAT 3 is a really bad idea. At least in RSLogix 5000 you could add a useful comment for each element of the array but there is no method of doing that in TwinCAT 3 (because you’re not supposed to do that anyway). Your TwinCAT 3 program would be completely incomprehensible. I would also like to caution you against using arrays for things that aren’t naturally numbered, or which aren’t a good fit for fixed numbers. For instance let’s say you have an auto sequence of steps like: 1. Run conveyor to sensor 2. Pick part from conveyor 3. Place part on fixture 4. Return pick & place to home Perhaps you would like to implement that auto sequence using the Step pattern. Good idea. Now you might think you want to create an array of variables for your steps, such as PickAndPlace.AutoSequence.Step[1]. Having done this in the past, I now think it’s a bad idea. It’s very common to have to modify your auto sequence to add or remove steps in the future. What if between your pick and place step you wanted to add a measurement step? It’s not so easy to add a step 2.5 when you’ve declared them as an array, and renumbering the steps in all your logic can be a real pain. I think it’s better to create variables like PickAndPlace.AutoSequence.PickStepand PickAndPlace.AutoSeq uence.PlaceStep. Then you can add and remove steps, or even re-order them, without cursing yourself later.
  58. 58. Chapter 3: Structuring PLC Data 58 Conciseness and Readability You might notice that some of my variable names above end up very long. I agree that’s a problem. On the one hand, since the comments for each variable only show up if you hover your mouse over the variable, you shouldn’t make your variable names too cryptic or it will be hard for someone to understand your logic. On the other hand, if you make them too long, you can’t fit enough of your ladder logic on the screen at once, and the logic itself becomes difficult to follow. There’s a trade-off to make in conciseness vs. readability. I suggest making short codes or acronyms for your top level machine elements. For example, you could abbreviate InfeedConveyor as IFC and PickAndPlaceto PP. When someone looks at your PLC project, they will still see 01_InfeedConveyor and 02_PickAndPlace as two folders, and inside each there will be Global Variable Lists IFC and PP respectively. Since you’re only doing this at the top level of your program, and it’s fairly easy for someone to see the relationship of the full name to the abbreviation, I think this is a good way to shorten your fully qualified variable names without sacrificing much readability. For the lower level variable names, make an effort to pick names that are still concise but convey the meaning to the reader. Yes, it takes practice and there’s no perfect answer, but effort really counts here.
  59. 59. Chapter 4: Persistent Variables 59 4 – Persistent Variables Traditional PLCs offer various forms of data persistence (so your PLC memory isn’t lost when the PLC loses power). Some use battery-backed SRAM, which maintains power to all or a portion of the memory even when power is removed from the PLC. Some use flash-memory technologies. Since TwinCAT 3 runs on PC hardware, and PC memory isn’t battery-backed up, it has a different mechanism for storing persistent variables. By default, variables in TwinCAT 3 are not persistent. If you restart the runtime, or your PC loses power, then when your PLC program restarts the variables will revert to their default state. This is fine for many situations (we generally want our outputs to start in the off state anyway). However, there are times when we need to store machine state such as part presence or process information and we don’t want to lose it when the PC reboots. TwinCAT 3 allows you to explicitly define variables that are “persistent” for this purpose. In this chapter I’ll explain how to create persistent variables, how TwinCAT 3 saves and restores them, and how to write a program to periodically save them to a file in case of a crash or power loss. Declaring Persistent Variables For this example, I created a new Global Variable List called “PersistentExample”. Note that persistent variables don’t need to be global (they could be defined in a program or a function block, for example). By default a Global Variable List only has one section of declarations (called VAR_GLOBAL): Anything declared inside of the VAR_GLOBAL section is not persistent. However, we can declare a section to be persistent like this:
  60. 60. Chapter 4: Persistent Variables 60 Adding the PERSISTENT keyword after VAR_GLOBAL tells TwinCAT 3 that any variables in this section should be written to persistent storage when the runtime shuts down, and restored from persistent storage when the runtime restarts (the data is actually stored to a file on disk, and I’ll explain more about the details later). I’ve declared two integer variables (one persistent and one non-persistent) as examples, and I’ve initialized them with default values (5 and 3 respectively). Now let’s login to the PLC, and apply this as an online change. You will now see an online view of this Global Variable List: As you can see, both variables have been created in the PLC, and they have the values 5 and 3, respectively. Now I’m going to write new values to them. In the Prepared value column, enter the values 10 and 6, like this:
  61. 61. Chapter 4: Persistent Variables 61 Now choose PLC > Write values to all online applications to overwrite the variable values in the PLC memory: As you can see, the values have changed. Now we’re going to restart the runtime and see what happens. First choose PLC > Logout from the menu and then choose TwinCAT > Restart TwinCAT System to initiate a runtime restart. You will be asked to confirm: Click OK to restart in Run Mode. You will see the TwinCAT icon in the system tray briefly turn red, and then turn back to green. When that’s done, go back online by choosing PLC > Login from the menu: You can see that the persistent variable retained the value of 10 that we wrote to it, but the non- persistent variable reverted to the initialization value of 3 that we defined in the variable declaration. The written value of 6 was lost.
  62. 62. Chapter 4: Persistent Variables 62 How Persistence Works TwinCAT 3 stores the persistent variables in a file on the computer’s hard drive. The sequence of when this happens is critical to understand to prevent you from losing your valuable persistent data. When you shut down the TwinCAT 3 runtime, here is how it saves your variables: 1. The PLC program stops executing 2. The runtime reads all of the persistent variables and writes them to a file 3. The runtime stops The persistent data file is stored in the C:TwinCAT3.1BootPlc folder, and it will be named Port_851.bootdata. Each PLC instance on a runtime has an “ADS port number”. The default port numbers start at 851. You can change the port number, but that’s not important right now. When TwinCAT 3 restarts, here is how it restores your variables: 1. The runtime loads the PLC program (including the default values of all variables) 2. The runtime looks for a persistent data file on the hard drive, and if it finds one, it restores the saved values to the PLC variables 3. It deletes the persistent data file from the hard drive 4. The PLC program starts executing If, for some reason, the runtime can’t find the persistent data file, then all of your persistent variables will be reset to their default values. This is actually very easy to demonstrate because if the runtime doesn’t get a chance to shutdown cleanly, it won’t write the persistent data file to the hard drive. Here are some ways that this can happen:  The PC loses power without doing a Windows shutdown  The runtime crashes (this shouldn’t happen, but it can happen)  The persistent data file can become corrupted The recommended way to install a TwinCAT 3 system is to use a PC with some kind of battery backup, like an Uninterruptible Power Supply (UPS). You must connect the PC to the UPS (via USB cable, etc.) and use the software provided with the UPS to make sure that Windows does a
  63. 63. Chapter 4: Persistent Variables 63 clean shutdown if the UPS loses power for any appreciable length of time. However, this isn’t good enough. Protecting Your Persistent Data Even if you use a UPS to provide Windows enough time to do a clean shutdown, there are still many ways that you can lose your persistent data (such as the UPS failing, the hard drive failing, or a runtime crash). Unless you can afford to lose the persistent data, you must do more to protect it. While your PLC program is running, the only up-to-date copy of your persistent data is the actual values of the variables in your PLC memory. The persistent data file is only written when the runtime shuts down cleanly, and it deletes the persistent data file after reading it when the runtime restarts. The first step in protecting your persistent data is to periodically write out the persistent data to disk while the program is running. Thankfully TwinCAT 3 provides a function block called WritePersistentData that does exactly this. You can manually instruct the runtime to write out the persistent data file from within the PLC program. Create a Save Persistent Variables Program In this section I’ll describe how to write a generic program that handles saving the persistent variables regularly while your program is running. This program will make use of a function block called WritePersistentData that’s provided with TwinCAT 3 in the Tc2_Utilities library. This library wasn’t referenced automatically when you created the PLC program, so you’ll have to add a reference before you can use it. Start by finding the References folder under the PLC1 Project:
  64. 64. Chapter 4: Persistent Variables 64 There are already 4 libraries referenced. These references were added when you created the project, and they provide some basic function blocks like timers, counters, and string functions. To add a reference to the Tc2_Utilities library, right-click on the References folder and choose Add Library… from the context menu. That will display the Add Library window: Now click on the System node (highlighted above) to expand it so you can see the system libraries:
  65. 65. Chapter 4: Persistent Variables 65 Click on Tc2_Utilities (highlighted above) and then click the OK button. The window will close and you will now see the Tc2_Utilities library added under the References node in the Solution Explorer: If you want to see a list of what is contained in a library, double-click on that library name in Solution Explorer and it will open the Library Manager window:
  66. 66. Chapter 4: Persistent Variables 66 Select a library in the top portion of the window, and you’ll be able to browse the contents of the library in the bottom left corner. With the Tc2_Utilities library selected, expand the POUs folder on the bottom left and expand the TwinCAT PLC folder beneath that to find the WritePersistentData function block. Click on the name of the function block to display a picture of the block on the right side:
  67. 67. Chapter 4: Persistent Variables 67 You can click on the Documentation tab above the picture of the block to see more detailed information about the inputs and outputs:
  68. 68. Chapter 4: Persistent Variables 68 Now we’re going to create a new Program POU called “SavePersistentVariables.” Start by right- clicking on the POUs folder in the Solution Explorer and choosing Add > POU…from the context menu. Enter the program name in the Add POU window and choose Program as the type and Ladder Logic Diagram as the implementation language:
  69. 69. Chapter 4: Persistent Variables 69 …then click Open to create the program. You will now see the empty SavePeristentVariables program in the ladder logic editor:
  70. 70. Chapter 4: Persistent Variables 70 Since WritePersistentData (from the library) is a function block, that means it has local state (stored in internal variables) and we have to allocate space for those state variables by declaring an “instance” of the function block as a variable in our program. (Note that the main difference between a Function and a Function Block is that a Function doesn’t have any internal state, so you can use a Function without first declaring an instance of it as a variable). If you’ve ever used a timer or a counter function block in another PLC, you will be familiar with the idea of allocating memory space for each instance of a timer or counter. Declare the function block variable as a local variable of the program, like this: This is just like declaring a BOOL variable. WritePersistentDataFB is the name of the variable, and WritePersistentData is the type. In this case, the type is a data structure that the function block needs to store its internal state. To add the function block to rung 1, right click on the rung and choose Insert Empty Box… from the context menu. Your rung will now look like this: The three question marks inside the box are where you type the function block name, and the three question marks above the box are where you type the variable (or “instance”) name. Go ahead and type WritePersistentData inside the box and WritePersistentDataFB above it:
  71. 71. Chapter 4: Persistent Variables 71 The editor recognizes the function block name and automatically adds the required input and output parameters to the block. We can start by filling in the NETID, PORT, and TMOUT inputs like this: The NETID is an empty string (just two single quotes), which means that the AMS Net ID is the local target (i.e. the PC it’s currently running on). The PORT is 851 because that’s the ADS port number of the PLC1 program. The TMOUT input is set to 10 seconds, which is a maximum time we will allow for the operation before the function block will abort and set the ERR and ERRID outputs. Notice the format we used for specifying the time. This is a syntax defined in the IEC 61131-3 standard. It allows you to specify durations like this:  T#10ms (10 milliseconds)  T#5000ms (5000 milliseconds, or 5 seconds)  T#5s (5 seconds)  T#1m (1 minute)  T#1h30m (1 hour and 30 minutes)  T#2d1h (2 days and 1 hour)
  72. 72. Chapter 4: Persistent Variables 72 The WritePersistentData function block initiates a save of the persistent data when the START input transitions from off to on (also called a “rising edge”). The BUSY output will turn on immediately and will stay on until an acknowledgement has been received (or the timeout expires). When the BUSY output turns off, if there was an error then the ERR output will turn on and the ERRID output will indicate the ADS error number (do a Google search for “ADS Return Codes” to see the list). Ideally we should save the persistent variables immediately after the PLC program starts, and then at regular intervals after that. We’re going to use two on-delay timers, one to trigger the initial write and a second to trigger the subsequent writes. TwinCAT 3 includes an on-delay function block called TON. It’s included in the standard library, which is already referenced. First you have to create the variables to hold the timer instance data: Declare two timers called StartTON and IntervalTON. Now we want to insert a rung to put the first timer on (note that in TwinCAT 3, rungs are called Networks because the ladder diagram editor is also the function block diagram editor, and function block diagram programs are divided into networks). Right-click on the existing rung and choose Insert Network from the context menu. The existing rung will become rung 2, and a new blank rung will be inserted as rung 1:
  73. 73. Chapter 4: Persistent Variables 73 Now right-click on rung 1 and choose Insert Empty Box from the context menu. Inside the new box, where the three question marks are, type TON and press enter. Then where the three question marks are above the box, type StartTON and press enter. Your rung #1 should look like this: The IN input of the timer controls when the timer is timing. The PT input is the “preset time” which is how long the timer will run before turning on the Q output. The ET output gives you the current “elapsed time” which is how long it has been since the IN input turned on. We want this timer to start timing right away, so replace the three question marks above the contact that feeds the IN input with the constant value TRUE. We want this timer to fire very shortly after the PLC starts, so enter the time constantT#1ms in place of the three question marks next to the PT input. That will make the timer Q output turn on one scan after the PLC starts (I did this to make sure the WritePersistentData function block will see a transition from off to on). Since we don’t need the ET output, right click on the timer and choose Remove unused FB call parameters from the context menu. That will remove both the Q and ET outputs. Now your timer rung should look like this: The timer’s output Q will transition from FALSE to TRUE 1ms after the program starts. Use the output to drive the WritePersistentData function block’s START input (highlighted):
  74. 74. Chapter 4: Persistent Variables 74 Now we need to create another timer that will fire repeatedly after a certain interval. Insert another rung (between rungs #1 and #2), add another TON function block, this time using IntervalTON as the timer instance. Set the preset time to 1 minute. We want this timer to start after the initial startup timer is complete, and we want it to reset every time the WritePersistentData function block is busy: Now modify rung #3 (the WritePersistentData rung) so that both timers will trigger the function block’s START input. Begin by selecting the StartTON.Q contact: Now right click on the contact and choose Insert Contact Parallel (below) from the context menu:
  75. 75. Chapter 4: Persistent Variables 75 Then replace the three question marks over the new parallel contact with the output of the second timer (IntervalTON.Q): Finally, there remains one problem. The StartTON.Q variable will be on almost all the time, but we’re only interested in the rising edge. TwinCAT 3 allows you to change a contact from a normally open contact into a rising edge or falling edge (also called “differentiate up” and “differentiate down”) by selecting the contact and pressing the “P” or “N” keys, respectively. Select the StartTON.Q contact and press the “P” key:
  76. 76. Chapter 4: Persistent Variables 76 Finally, we don’t want to use the ERR and ERRID outputs. Rather than making them disappear, just delete the three question marks next to those outputs and the compiler will just leave them disconnected for now. Eventually you should consider using the ERR output to create an alarm to notify someone that there’s a problem saving the persistent variables. Here is the complete program:
  77. 77. Chapter 4: Persistent Variables 77 Here’s how it works: 1. The StartTON timer fires almost immediately when the PLC starts, and that gives a single pulse to the START input. 2. During the initial write process, the BUSY output is on, which prevents IntervalTON from running. 3. When the initial write is complete, BUSY turns off and then IntervalTON starts running. 4. One minute later the IntervalTON timer completes and turns on the Q output. This triggers the START input again, which makes the BUSY output turn on, which resets IntervalTON until the write is complete. 5. When the write completes, we go back to step 3.
  78. 78. Chapter 4: Persistent Variables 78 Before this program will run, you have to call it from your MAIN program. The Quick Start chapter explained how to call other programs from your MAIN program so I won’t repeat that here. Remember to login with an online change to start running this new program. When you execute this code, you can watch the C:TwinCAT3.1BootPlcfolder and see the Port_851.bootdata file created, and then see the file timestamp update every minute after that. Now we have a copy of the persistent data on the hard drive that is at most about 1 minute old. That will protect us if there is a runtime crash or the UPS stops working but it still doesn’t protect us from a corrupt file or a hard drive that stops working. To make sure you can recover from these scenarios, you need to make backups of the persistent data file at regular intervals to another computer. To restore a backup of your persistent data file: 1. Restart your runtime in Config mode 2. Replace the .bootdata file with the backed up one 3. Restart your runtime in Run mode Note that in the event of a crash, the restored persistent variables might be up to 1 minute old. That’s still a problem for part presence data, but at least you won’t lose all your setpoints. The persistent data saved when the runtime does a clean shutdown is the primary method for protecting the consistency of your persistent data. That means a good UPS connected to the PC with the USB cable and running the UPS software so it will do a clean shutdown in the event of a power loss is absolutely necessary for every production system using TwinCAT 3.
  79. 79. Chapter 5: Structuring PLC Logic 79 5 – Structuring PLC Logic TwinCAT 3 gives you a lot of flexibility in organizing your PLC logic. In this chapter I’ll explain how to make use of this flexibility to organize your logic in a way that makes it easier for someone reading your program to find what they need. The MAIN Program When you create your first TwinCAT 3 PLC project, the wizard will helpfully create a MAIN program for you: The MAIN program is called by the PlcTask task on a schedule defined in the PlcTask configuration. This is the point at which your program now has control of the runtime. From within MAIN, you have to call other programs that are part of your PLC project.
  80. 80. Chapter 5: Structuring PLC Logic 80 Note that the MAIN program is inside of a POUs folder. This is only Beckhoff’s default output generated by its wizard. Right now you could move the MAIN program into the GVLs folder and PlcTask would still call it without a problem. Folders In my programs I delete the DUTs, GVLs, POUs and VISUs folders and then I create my own folder structure that mimics the structure of the machine. For instance, if I was programming a multi-zone conveyor system, I would create folders called Zone01, Zone02, etc., and if I was programming a rotary assembly cell I would create folders such as RotaryTable, Station01, Station02, etc. Then, inside each folder I would put both the data structures and logic related to that part of the machine. There’s no need to separate the data from the logic in separate folders: Note: the folders sort themselves alphabetically. It just so happens that “R” comes before “S” so it all worked out nicely above, but usually you want to enforce an ordering scheme. In that case, you can add a numerical prefix, such as “01_” to the beginning of every folder name to make them show up in the order you want. Also note that the current version of TwinCAT 3 doesn’t seem to
  81. 81. Chapter 5: Structuring PLC Logic 81 sort properly as you add new content. To get it to sort properly, save everything, close the solution, and open it again. You can also put folders inside of folders. For instance, if you have a zone-based conveyor system inside of the infeed side of your automation cell, you can put all of the zone folders inside of an Infeed folder. Programs Within your new folder structure, add programs to control each logical element or function of the machine. For instance in a zone-based conveyor system, it’s typical for each zone to have a “drive” which is the motor that turns the rollers and a “stop” which is an air-actuated plunger that pops up to prevent a pallet from moving past a point, and drops down out of the way to allow the pallet to go forward. In a system like that, I would expect to see logic like this: Always try to imagine someone trying to troubleshoot this machine. In a normal factory there will be a maintenance team that handles the maintenance on several different machines. Nobody will
  82. 82. Chapter 5: Structuring PLC Logic 82 know any particular machine to the depth that you know it while you’re programming it. An operator might call them because there’s a pallet stuck in zone 2 and it won’t leave. If they open up the project above, they can quickly navigate to the Zone02 folder, open the Zone02_Stop program and find the output that drops the stop. If the output is on but the stop isn’t dropping, then they know there’s something wrong on the mechanical or electrical side with the stop, but if the output isn’t on in the program, then they can start working their way backwards through the logic trying to figure out why the program isn’t turning the output on. You might wonder why you wouldn’t create a single function block and call it 3 times, one for each zone. Good question. Remember that even though the conveyor system appears to have 3 zones and they all look the same, you should expect the logic for each zone to be slightly different. Remember that these are 3 separate physical parts of the machine and even though we might like to imagine that they’re identical, they’re not. If zone 1 is where material gets introduced to the line, then it likely has some kind of interface logic for interlocking with whatever is feeding it, such as a light curtain or a robot. Similarly the 3rd zone might need to be interlocked with some kind of pick-and-place equipment. If you create a function block that can handle the logic for all 3 zones, then you’ve complicated the logic for no real gain. It’s better to see if you can pull out components of each zone that are necessarily identical (such as the stop) and create a function block for just that component. However, even then I would caution you that these are 3 separate physical stops and you should expect the logic to have to work slightly differently for each one, even if it’s something as simple as a timer. Also, it’s common that someone in maintenance might need to bypass some condition in the logic either to recover from an unforeseen problem or to bypass a broken sensor until it can be replaced. It’s much more difficult to do this if all 3 components share the same logic, since any bypassing code will likely affect all 3 stops, when in reality you only want to bypass a single sensor. Ultimately it’s your decision, but I suggest defaulting to the copy/paste method rather than the function block method in most cases.
  83. 83. Chapter 5: Structuring PLC Logic 83 Calling Program from MAIN After you’ve created your programs, you need to “call” them once-and-only-once from your MAIN program. Here is what your MAIN program would look like in the conveyor example above: Remember that there is only one “instance” of each program (unlike a function block like a timer where there can be more than one instance). That means there is only one copy of the local variables declared inside of a program. If you call a program twice, you are executing the logic a second time, and it’s going to affect your local program variables and any global variables referenced by that program. That’s almost certainly not what you want. Someone reading your project will assume that every program is called once, and typically in the order that the programs are listed in the solution explorer, so please work hard to make the order that they show up and the order that you call them in match. If they need to be called in a certain order, please rename your programs and folders so that the ordering is the same. Every time you create a new program you have to remember to call it from MAIN. If you don’t, the logic won’t execute and this can be difficult to debug. Thankfully, TwinCAT 3 will give you a hint that you made this mistake. As an example, I’m going to comment out the line where I call Zone02_Stop from the MAIN program:
  84. 84. Chapter 5: Structuring PLC Logic 84 The two forward slashes turn the line into a comment, which means anything after the slashes is ignored by the compiler. Now, right click on the PLC1 Project node in the Solution Explorer window and click Build from the context menu. After building, TwinCAT 3 will gray out any POUs that aren’t “linked,” which generally means any that aren’t called by your MAIN program:
  85. 85. Chapter 5: Structuring PLC Logic 85 I highlighted the grayed out node with a red arrow above. Note that you can defeat this helpful feature by forcing the compiler to link it even if it’s not called. Click on the grayed out node, and then look at the Properties window: If you change the Always Link property from False to True, and then build the project, the node will no longer be grayed out. When you run the program it still won’t call this program, so you may wonder why this feature exists. Well, if the program isn’t linked, then that means the compiler didn’t even try to build it. There are certain cases where you might be trying to write some new logic and you don’t want to call it yet, but you do want to check if there are any compile errors. In that case you can set the Link Always property to True, build the project, and any compile errors will show up in the error list at the bottom of the screen. Just remember to change the property back to false so you will remember that you’re not calling this logic yet. Program Variables Each program has a variable declaration section at the top of it for local variables. Any variable that is only referenced by this program should go in the program’s local variables, not in a Global Variable List. That helps someone reading your program understand the “scope” of a variable. Global variables have more impact across your whole project and might even be referenced by your HMI program, but local variables should only be used by your program and modifying them should only have a local effect. Note: In the latest version of TwinCAT 3, you can actually read and write program local variables from the HMI. I advise against doing this, but if you do, please make sure that you at least comment these variables in your program to let other people know that they’re accessed by the
  86. 86. Chapter 5: Structuring PLC Logic 86 HMI. Even global variables accessed by the HMI need to be commented. That’s because it’s easy to find all the places where a variable is used in your program: just change the variable name and do a build. You’ll get compile errors at every reference (and there’s also a cross reference feature too). Unfortunately there’s no simple way to find places where that variable is referenced in the HMI, so make sure you make it obvious. In addition to normal local variables, you can add a PERSISTENT variable section inside the variable declarations of a program, just like you would in a Global Variable List. The variables in a VAR PERSISTENT block will be saved and restored through a shutdown and a restart of the PLC runtime, just like persistent variables in a Global Variable List: Less is More How much logic should you put in a single program? My general rule of thumb is “as little as you can get away with.” You want all of the logic in a program to be “tightly coupled.” That is, all of the logic in a single program should be highly related to the other logic in there. Conversely, you want the logic in different programs to be “loosely coupled.” That is, ideally you want all the logic in a program to stand on its own without interacting with the logic in other programs at all. Obviously this isn’t always possible, but in practice you want to reduce the coupling between programs. Since the coupling between programs takes place through global variables, this means you want to separate your logic in such a way that the interfacing signals between programs are few and simple. If you have a conveyor feeding a pick-and-place robot, then PickAndPlaceClearOfConveyor is a reasonable global variable that’s set in the pick-and-place logic and used in the conveyor logic. The conveyor logic shouldn’t “care” how that
  87. 87. Chapter 5: Structuring PLC Logic 87 signal is created (that’s the job of the pick-and-place logic). It just needs to know that it’s clear so the conveyor can move. In practice, I try to keep my programs between 1 and 12 rungs long, but that’s certainly not a hard and fast rule. Logic that needs to be longer should be longer. However, if your program logic really starts to grow, see if it’s really doing two things that could be separated out into two programs where just one or two global variables could handle the interaction between those two programs.
  88. 88. Chapter 6: Multiple Virtual PLCs 88 6 – Multiple Virtual PLCs In the Windows Server world, the big trend in the last 10 or so years has been server virtualization. That means we take one big beefy server and we run many “virtual servers” on that hardware. One physical server takes on the role of email server, file server, database server, etc., and we can logically think of each server as a separate entity because we can login to each one, see its disk drives, install programs, etc., but each virtual server shares the resources of the parent physical server. This revolution in the data center has also made its way into PLCs. The TwinCAT 3 runtime running on a PC is kind of running a “virtual” PLC. That PLC runs in “ring 0” of Windows and handles all the tasks that a traditional PLC would, like scanning the I/O, and solving logic. TwinCAT 3 lets you create multiple virtual PLCs and run them all in the same TwinCAT 3 runtime. You might wonder why you’d want to do this. Here are some reasons… Reason 1: Make use of Multiple Cores The primary reason touted by Beckhoff is that this is how you make use of more than one core in those fancy new multi-core CPUs we can buy now. Modern CPUs in the Intel Core-i3, i5, and i7 series have 4 physical cores in the CPU, and each one can be executing a different program at the same time. However, the fundamental scheduled unit in Beckhoff, the “task”, can only run on a single core. Even though the processor power available in a single core is much more than in a traditional PLC, EtherCAT is so fast that you may also be pushed to run your logic faster. In case you run out of CPU time, you now have the option of breaking your system up into multiple tasks that run on separate cores. In a typical system with a PLC and a motion controller, you can already do this by running your PLC task on one core and the motion control task on another. However, you still have the option of splitting your PLC logic into multiple virtual PLCs and running each one on a separate core so you can balance the loads. Reason 2: Separation of I/O Let’s say you have a really big system with lots of I/O. The more I/O you have, the longer it can take to scan the whole bus. Some day you might have a case where you want to scan a small