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.


Technical Article November 29, 2025 by Shawn Dietrich

Every PLC manufacturer, and every developer of text-based code languages, have a slightly different way of defining a variable within the ladder logic or code, and these methods have evolved over the years.

 

Variables In A PLC

A variable is a block of memory that holds a binary value, which could be represented as a single bit, 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 exist in fixed memory addresses, 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.

 

Rockwell PLC

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

 

Defining where a tag exists is an important question. Primarily, there are two locations: they can be defined at the controller (global) scope, or the program (local) scope. This scope determines where they can be used. Global variables can be used by any program, routine, or subroutine at any time, so they can pass information between programs and functions. Local variables can only be used inside the program in which they are defined.

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.

 

Siemens PLC tag listing

Figure 2. Global scope data (top) and the local variable of a function block (bottom) of a Siemens TIA Portal project. Image used courtesy of the author

 

Code Layout

The way you lay out your code structure will vary depending on your project: process automation code will look different from manufacturing automation. Likewise, Siemens code would be structured differently from Rockwell code. One programmer's layout will be different from another's, even for the same project.

Certainly, a large 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 key takeaway is that each tag takes up memory, and PLC memory is limited, and therefore 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.

 

Rockwell Controller Organizer

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. Image used courtesy of the author

 

When Should My Tags Be Local Scope?

Local scope is useful for information that only refers to things happening inside the PLC. For example, loop counters, bits that retain operating statuses, and many timers.

When we consider complex processes, the scope issue becomes more pronounced. There is one similarity between all the different code layouts: repetitive code. Some manufacturing operations take longer than the cycle 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.

 

Palletizing Robot

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. This reduced the need to create globally-scoped tags, leading to a program that is far more efficient in its use of available memory.

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 Should My Tags Be Global Scope?

If information is attached to actions or objects outside of the PLC environment, they must have controller-scoped tags. For example, Ethernet devices 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, assuming they are counting across multiple machine stations. Sometimes, HMI tags must also be universal to all programs.

If I’m going to be using both program (local) scope and controller (global) scope 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.

 

Alias tag listings

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. Image used courtesy of the author

 

Alias Tags

There is a final type of tag that isn't exactly a scope in itself, but it is attached to a tag with a fixed scope, so it must be considered. As an example, 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.

 

Updated; original article published 5/2023