7 Strategies for Designing Troubleshooting-Friendly PLC Applications

plc structure troubleshooting Apr 14, 2024

In the exciting world of industrial automation, PLCs and PLC logic are key to running machines and production lines smoothly.  However, even the best PLC applications can run into problems - incorrect assignment of tags, sequences getting stuck, copy paste faults etc...  This is where troubleshooting comes into play. 

But what if I told you that PLC applications can be designed from the ground up to be significantly easier to troubleshoot and maintain?

Here are seven strategies to ensure your PLC applications are as troubleshooting-friendly as possible.


1 - Develop modular logic instead of opting for All-In-One solutions

Now this is an interesting one.  I've observed that certain machine builders lean towards creating a software standard that includes all features for every potential configuration of a specific piece of machinery. The big plus is having to maintain just one software standard - if something needs fixing, you only have to do it in one place. Yet, a notable drawback is the potential for your PLC application to expand significantly, with an abundance of blocks and increased complexity.  This size increase can make troubleshooting considerably more challenging compared to working with a smaller, more streamlined PLC application that contains only the essential logic.

One specific practice that I have noticed among some PLC programmers is packing all possible features of a particular unit, function, or module into a single block of logic.  These giant blocks, crammed with logic for every possible configuration, become frustrating to troubleshoot and maintain. Instead, I recommend breaking down these extensive blocks into smaller, more manageable modules or functions. You can facilitate the data exchange between these blocks using user-defined tag data structures. 

Here's an example of a cooler unit, expanded with an auxiliary fan (slave unit) and a PID control unit:



Instead of having one large cooler block containing everything within a single function, I've chosen to program one primary control block, 'FB - Ctrl Cooler,' alongside two additional blocks: 'FB - Ctrl Cooler - Slave' and 'FB - Ctrl Closed Loop.'  An added benefit here is the ease with which you can delete the slave unit or the PID unit (if they're not applicable for your project), thereby reducing the size of your PLC application and simplifying troubleshooting once again.

Start applying this modular setup to your own PLC projects and you'll notice how much easier it is to pinpoint and fix incorrect code, ultimately saving you a lot of time and effort when troubleshooting.


2 - Keep nesting of functions to a depth of no more than 3 to 4 levels

Consider this scenario: A few years back, one of your colleagues created a control block for a cooling fan. This block featured a temperature control system, which itself incorporated a PID control, which then included a temperature scaling function, and finally, a calculation function nested within. Fast forward two years, and now a customer is on the line, reporting an issue with how the cooling temperatures are calculated. Good luck finding a temperature calculation fault in your colleague's logic 5 levels down.  Can you recognize how excessively nesting your functions can make troubleshooting difficult and time-consuming?  I've encountered this scenario numerous times, and each time, I find myself shaking my head (followed by taking a couple of deep breaths).

Excessive nesting can make it hard for someone else (or even you, returning to the code after some time) to understand the logic flow.  Instead of primarily focusing on vertical software development (with block calls nested inside one another), consider adopting a more horizontal approach, where block calls are arranged next to each other.



The above screenshot showcases a vertical integration where the PID control block (FB - PID - Control) is called inside of the parent block (FB - EM Refill).

The screenshot below displays the same blocks in a horizontal call structure where the PID control block is called next to the parent block.



Now just to be clear, I do not suggest that you never nest any functions inside other functions.  I actually use nesting frequently in my own PLC programming because it makes a lot of sense in most cases.  As a matter of fact, I would prefer the vertical integration in the above example (which is taken from my premium training bundle).  The 'FB - PID - Control' does not contain any block calls within the block, so I only end up with a nesting level of 2 (PID block call inside of the refill block).  As long as I don't exceed nesting level 4, I'm a happy PLC programmer.

By the way, you'll notice that adopting a horizontal structure is closely tied to my first tip (avoid building All-In-One blocks).  By steering clear of extensive blocks and developing modular, well-structured PLC code, you reduce the chances of introducing errors and you'll significantly simplify the debugging process.


3 - Organize related information within tag data structures

If you've been watching any of my tutorials on YouTube (you can do that right here), or you're following me on my LinkedIn page (you can check me out right here), then you may have noticed that structuring PLC applications is my favorite topic.  In my opinion, it's the single most important skill that will elevate you from the amateur level of PLC programming to the professional league.

One key element of a structured PLC program, is the data structures that you create for your application.  A tag data structure is a user-defined collection of tags.  The idea is that you group tags together based on their association to a certain module, unit, or process.  

Take a look at the following example: Imagine you have a cooling unit on your machine, which includes a temperature sensor, a pump, and an analog valve. The cooling unit's temperature is maintained at a setpoint using a PID control loop. This control loop uses the pump and regulates the analog valve to circulate a specific amount of cooling liquid, ensuring the desired temperature is achieved.

Here's how the tag data structure for this cooling unit could look like:



The data structure that I've build for the above cooling unit example consists of the following key segments:

  • configuration (Cfg) = data related to the configuration of the cooling unit e.g. scaling of the temperature sensor
  • buttons (Btn) = tags related to HMI buttons for this unit
  • PID control (PID) = parameters used for operating the PID control loop
  • status (Sts) = status information for this unit
  • command (Cmd) = command flags and values for this unit
  • fault (Flt) = fault tags for this unit


So all data and information associated with this cooling unit are neatly organized and instantly accessible within the user created data structure. If your customer calls you in the middle of the night due to issues with the cooling unit, a brief examination of this data structure will likely guide you in the correct direction. Now, consider how challenging and time-consuming troubleshooting the same problem would be if all the cooling unit information were scattered across various data areas or (heaven forbid) declared as individual simple data types. You'd probably have to sift through multiple data blocks in your PLC application before gaining any insight into the issue.

Build your PLC logic from the ground up with data structures, and you'll find troubleshooting down the road a much smoother process.


4 - Keep tag names short and descriptive

Choosing meaningful names for tags, functions, and modules makes your code self-explanatory.  When an issue arises, clear tag names can immediately give insights into its function, significantly simplifying the troubleshooting process.

When it comes to naming tags, I'm a big fan of the Hungarian notation, which essentially follows this format:

  • Write the first letter of each word in uppercase, the remaining letters in lowercase
    Examples: Pump_1_Running, Button_Reset_Faults, Temperature_Level, Fan_Speed
  • In front of the base name, append a prefix in lowercase to indicate the data type of the variable
    Examples: xPump_1_Running (boolean), xButton_Reset_Faults (boolean), rTemperature_Level (real), wFan_Speed (word)


Here's an illustration from my PLC Programming Basics course, where I take it one step further by incorporating the tag usage ahead of the lowercase prefix.

  • i_ = input tag
  • q_ = output tag
  • iq_ = inout tag
  • _ = temporary tag
  • nothing = static tag



In addition to employing Hungarian notation, I aim to keep tag names short and clear by utilizing widely accepted industry abbreviations, such as:


  • Cfg for configuration
  • Cmd for command
  • Sts for status
  • Par for parameter
  • Btn for button
  • Flt for fault


Here's an example of tag naming within PLC ladder logic from my premium training course:


The data type and function of each tag are immediately clear from its name (e.g., _xCmd_Open_Valve represents a temporary boolean tag for a valve open command, while i_xValve_Open indicates a boolean input tag for valve open feedback).  Moreover, the ladder logic is easy to read because the tag names are kept short.  

A quick note on acronyms: I tend to use fewer acronyms (words formed from the initial letters of a phrase or name, like VFD for Variable Frequency Drive) in my tag naming compared to abbreviations (shortened forms of words, such as Cmd for command).  Acronyms often relate to specific industries or machinery, so I recommend using only widely recognized acronyms like PLC, HMI, VFD, SCADA, PID, CPU, CIP, I/O, MES, CAN, etc...


If you're interested in delving deeper into optimizing your tag naming, feel free to explore my blog article right here.  Now, let's continue - on to tip number 5!


5 - Optimize your PLC logic to simplify the cross-referencing of tags

One, if not the biggest tool in your troubleshooting repertoire, is the possibility to cross-reference tags.  Cross-referencing a tag allows you to view all places in your user program where this specific tag is accessed, either being read or written.

Consider a scenario where every time you try to enter a new value for a parameter on the HMI, it gets overwritten by a value from the PLC.  The steps to troubleshoot this issue are pretty straight forward. 

  1. Find the specific tag in your PLC program
  2. Cross reference the tag
  3. Check every location in your PLC logic where the tag is being written to

One of these locations will most likely provide you with an answer to your problem.

But there is a caveat.  Depending on the automation platform you are using (Siemens, Rockwell, Schneider, Beckhoff, B&R,...), tags that are part of a data structure may not appear in a cross-referencing list if they are referenced within a function.


Example of a data structure tag being referenced inside of a function.


Put simply, if a complete data structure is passed as an input, output, or inout to a function, the usage of its tags within that function won't be shown in a cross-referencing list.  Relating this to our initial example, if the HMI parameter is part of a data structure referenced and overwritten within a function, pinpointing the fault becomes significantly more challenging.

The solution: use data structure tags directly into the logic of your function, rather than passing them into the function first. 


Example of data structure tags being accessed directly inside of a function block.


This approach is effective for functions that are called only once in your user program. However, it is not suitable for functions that are called multiple times.  Functions of the latter type are generally created to encapsulate specific functionalities, allowing them to be reused throughout different sections of your program.  Directly using tags and data structures within these functions can create dependencies and potential side effects, which might compromise the behavior and maintainability of your code.

My advise is to be cautious and thoughtful when passing tags and data structures to a function.  If the function is called only once in your PLC program, I would use those data structures directly in the function because it enhances cross-referencing capabilities and simplifies troubleshooting.  If the function is called multiple times in various parts of your application, then pass them through.


6 - Include detailed explanations and comments throughout your code

While PLC logic can be self-explanatory to some extent (proper tag naming - tip 4 - really helps here), nothing beats proper documentation.  Clear comments within your code, detailed titles and descriptions of networks and blocks, clear input/output annotations, explanations for the different steps of a sequential function etc... can significantly improve the troubleshooting experience. You can even take it to the next level by creating external manuals that describe the overall system logic and specific functionalities. 

Here's an example of a function block with ladder logic that features a clear block title and description (1), distinct network titles (2), and a detailed network description (3).



Give your fellow programmers (and yourself) a fighting chance during times of adversity and include clear titles, descriptions, and comments throughout your code.


7 - Remove any logic that is not being used or is disabled

This final tip is kind of self-explanatory.  I see it all the time, PLC applications with disabled functions, test bits left and right declared with the programmer's initials (e.g. 'HSC_ALWAYS_OFF'), or even complete modules copy-pasted by mistake from another project.

The solution is simple: clean up after yourself.  Unused or disabled logic blow up the size of an application unnecessary, resulting in longer troubleshooting hours as you're forced to sift through excessive logic.

I recently came across some PLC logic that perfectly illustrates my point:



Besides the absence of a block title (which I'm not a big fan of either - see tip 6), the entire 'FB - Ctrl Jog' block is deactivated by an 'OFF' tag in front of the block. Meanwhile, the network title screams 'BACKUP!!!!'.  Instead of leaving this disabled network in place, why not remove it entirely and document the change in your program log?

Keep your PLC applications organized and streamlined – your fellow PLC programmers will appreciate it, and you'll benefit from easier troubleshooting and maintenance.


Are you already using any of these tips in your own PLC program development?  Do you see how they could help you build better applications?

Start integrating these practices into your PLC application development process, and you'll do more than just program - you'll create robust PLC applications that are easy to troubleshoot and maintain.  This will lead to less downtime and higher productivity for your machines and production lines, ultimately leaving your customers impressed and satisfied.




Grab my '5 Simple Steps to Drastically Improve your PLC Program Structure in TIA Portal' and start building better PLC applications TODAY.

Where should I send you the guide?

When you signup, we'll be sending you further emails with additional free content. You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.