Understanding PLC Tags: Controller Scope vs. Program Scope
Is it best to ‘controller scope’ or ‘program scope’ your tags? This is the question asked by many new PLC programmers, and it often comes down to personal preference.
Variables In A PLC
Every PLC manufacturer, and every developer of text-based code languages, all have a slightly different way of defining a variable within the ladder logic or code, and these methods have evolved over the years.
A variable is a block of memory that holds a binary value, which could be represented as an integer, a floating point number, or an ASCII character. Today, most PLC variables are ‘tag-based’ meaning each variable is given a data type that defines how the variable will be represented. This could be the standard integer, double integer, byte (all of which are variations of integers), word (also variations of integers), or string, all given a name.
Compared to some standards from previous generations, such as Rockwell’s SLC 500, tags used to look like N7:0.1 or B3:5.0, with letters denoting specific blocks for different types of variables. For example, timer addresses would be T:XX and counter types would be C:XX. The variable is also defined in a specific location (address), it can be globally defined or defined within a program.
Figure 1. I/O modules are always assigned to the controller (global) scope since the real-world data applies to all programs equally. Image used courtesy of Adobe Stock
Before answering the original question, whether it is best to define variables within one scope or the other, let’s discuss how these variables are represented in a couple of software environments.
Tag Definitions in Studio 5000 and TIA Portal
When creating tags within Rockwell’s Studio 5000 Logix Designer IDE, you can choose to create the tags universally accessible to the entire controller project, called controller scope (these are global variables to many CS engineers), or down within a single program, called program scope (also called local variables).
With Siemens PLCs, tags can be created in data blocks, or they can be defined inside function blocks and function calls. When tags are created in a program or FB and FC (function block and function call), only that program or function can access those tags. Building your ladder logic code this way allows for compact tag lists and compartmentalized code structure.
Figure 2. Global scope data (top) and the local variable of a function block (bottom) of a Siemens TIA Portal project. Author’s image
The way you lay out your code structure will vary depending on your project.
Process automation code will look different from manufacturing automation.
Siemens code will look different from Rockwell code.
Certainly, larger machine code automating an entire facility will look different than a program driving a single smaller machine.
Whichever style of code your project requires, some thought should be given as to how you will lay out your code so that you reduce the amount of unnecessary code and reduce the number of tags.
Perhaps the most key takeaway is that each tag takes up memory, and PLC memory is very expensive. Controller or global scope tags permanently reserve memory allocation for every single variable in the entire program. The program (local) tags can reuse the same memory block over and over for repetitive routines and programs.
Figure 3. Comparing the controller scope of tags in a Rockwell Studio 5000 project to the parameters and local tag menus inside each respective program. Author’s image
When To ‘Program Scope’ Your Tags
There is one similarity between all these different code layouts: repetitive code. Some manufacturing operations take longer than the takt time of the machine, to alleviate this issue, some stations are doubled to help make up for the slower process.
This 2UP style of automation requires exactly the same code in two different locations, the only difference being the input and output mapping.
One option is to copy and paste all your code then do a find-and-replace to change all your tag names. This option would use all controller-scope tags, with a set of tags for each station using different prefixes or suffixes.
Another option is to have a program for each station, keeping all your tags local to that program. Input and output routines can take care of the I/O mapping and all your tags will have the same names. When code changes need to be made, it can be debugged in one program and when it's ready, you can copy and paste the code without having to change tag names.
By compartmentalizing your code into programs, you make it easier to reuse code in different locations, accelerating the integration of your machine.
Figure 4. Modular automated cells, like robotic palletizing solutions, often rely on repetitive code that can be optimized to increase efficiency. Image used courtesy of Adobe Stock
Parameters: Passing In And Passing Out
A common programming technique borrowed from PC programming is to pass in parameters into a function and then pass out results or status.
If we think of our operation or station as a function, then we would pass into our station program the machine control logic and pass out the status results of the operation. This style of programming is used extensively with Siemens function blocks and function calls and produces compact code that is easy to find logic and debug problems.
When To Controller Scope Your Tags
In some situations, you must have controller-scoped tags. For example, Ethernet and I/O modules always have controller-scoped tags. Likewise, physical part-tracking data should be controller scoped, as every operation will need to modify the part tracking array. Sometimes, HMI tags must also be universal to all programs.
If I’m going to be using program and controller scoped tags within the same machine logic, I like to add a prefix to all global scoped tags so that I can quickly identify if that tag is defined in the controller or the program. Typically I’ll prefix the tag name with a lowercase g which represents global, and program tags would have no prefix.
Figure 5. Top image shows the global (controller scope) tag arrays, with the local aliases for two identical machine centers in the program scope tag lists below. Author’s image
Sometimes, you might have a requirement for a global tag which is used in every operation; fault arrays fit this bill. Faults need to be displayed on the HMI, but they will be set in the station programs.
With Studio 5000, you can define a global tag and then alias it to a local tag, so when the tag value is set in the program, the global alias will also be set. I like to define an array of fault tags and then alias an index from the array to the program fault tags. This can be confusing to read initially, but is a very clean way of connecting global and local tags together.