Streamlined Automation of PLC Program Creation with L5X Format
Maxim Krylov
Co-founder of Kiptr.com
The industrial automation market is becoming more competitive every day, both for engineers and equipment manufacturers. In this modern world, we always want to get more for less. Hence, we seek new and more efficient ways to solve our problems. At the same time, our industry is very slowly evolving, and engineers show high resistance to accepting new technologies.

So, let's see if we can use the old technology in a new manner!

Allen Bradley (owned by Rockwell Automation) is one of the market leaders in the world. Their equipment and software products are well known and widely accepted.

Studio 5000 (former RSLogix 5000) platform is well familiar to controls engineers and I think I can say - is still a default choice for majority of companies in US.

In this article, I want to show you how to create Studio 5000 projects much more efficiently than people used to. You can save hours and even days of work depending on the size of your project if you start automating repetitive and routine tasks. And L5X is the file format that can help you do it.
So, what exactly is L5X format, how is it different from ACD, and why do we need it?

When you create a PLC program in Studio 5000 and hit the "Save" button, you get a ".ACD" file. This is a proprietary binary file format and is native to the software. If you open it with any text editor, the only thing that you will see is "machine code" that a human cannot understand. But if in Studio 5000 you click "Save As" and select "Logic Designer XML file (.L5X)" you will get something much more interesting.
Before we go any further, I want to say that there is a document called Publication 1756-RM084Z from Rockwell Automation. This document describes every little detail of L5X and L5K formats. I highly recommend reading it if you need to go very deep into this topic.

Do not confuse L5X with L5K – another text-based format that human can read, but it is organized in a way Allen Bradley came up with a long time ago. It is not as flexible as L5X since there are some limitations to it. The inability to save parts of project is an example of an important one.

Now we know that L5X is "Logic Designer XML file". XML stands for "extensible markup language" – it is the whole language that is both machine and human readable. You can find plenty of information about XML, it's history and areas of use on the internet.

We will be using it to automate the creation of PLC program or it's parts. XML files contain plain text, which is organized in a certain way. Therefore, XML files can be opened with any text editor. Notepad is the easiest way to look at what's inside for Windows users. There are also software products that were built to work with XML format. They make it easier to modify this type of files by providing special tools.

Here is an example of the XML structure:


<?xml version="1.0" encoding="UTF-8"?>
<rootelement>
<element1>some text</ element1>
<element2 attribute1 = "attribute value" attribute2 = ”another value”> </ element2>
<element3 structure="has children">
    <element4>child of element3</ element4>
</ element3>
</ rootelement >

A little of terminology:

The first line is called "XML prologue". It is optional for XML in general, but L5X has to have it.

XML syntax is not so hard to understand. There is always a root element. It starts with element's start tag ("<rootelement>") and ends with the element's end tag (</ rootelement>).

Any element can contain other elements, text, and attributes. In our example, "root element" contains 3 children. Element "element1" contains only text. "element2" has only two attributes. "element3" includes one element and one attribute.

Now let's take a look at the simplest L5X file:
 < ?xml version="1.0" encoding="UTF-8" standalone="yes"? > 
 < RSLogix5000Content SchemaRevision="1.0" SoftwareRevision="32.02" TargetName="Example" 
 TargetType="Routine" TargetSubType="RLL" ContainsContext="true" Owner="Some, User" 
 ExportDate="Thu Aug 19 18:45:35 2021" ExportOptions="References NoRawData L5KData DecoratedData 
 Context Dependencies ForceProtectedEncoding AllProjDocTrans" > 
     < Controller Use="Context" Name="RM2" > 
         < DataTypes Use="Context" >  < /DataTypes > 
         < Tags Use="Context" > 
             < Tag Name="bit1" TagType="Base" DataType="BOOL" Radix="Decimal" Constant="false" ExternalAccess="Read/Write" > 
                 < Data Format="L5K" > 
                     < ![CDATA[0]] > 
                 < /Data > 
                 < Data Format="Decorated" > 
                     < DataValue DataType="BOOL" Radix="Decimal" Value="0"/ > 
                 < /Data > 
             < /Tag > 
             < Tag Name="bit2" TagType="Base" DataType="BOOL" Radix="Decimal" Constant="false" ExternalAccess="Read/Write" > 
                 < Data Format="L5K" > 
                     < ![CDATA[0]] > 
                 < /Data > 
                 < Data Format="Decorated" > 
                     < DataValue DataType="BOOL" Radix="Decimal" Value="0"/ > 
                 < /Data > 
             < /Tag > 
         < /Tags > 
         < Programs Use="Context" > 
             < Program Use="Context" Name="General" > 
                 < Routines Use="Context" > 
                     < Routine Use="Target" Name="Example" Type="RLL" > 
                         < RLLContent > 
                             < Rung Number="0" Type="N" > 
                                 < Text > 
                                     < ![CDATA[XIC(bit1)OTE(bit2);]] > 
                                 < /Text > 
                             < /Rung > 
                         < /RLLContent > 
                     < /Routine > 
                 < /Routines > 
             < /Program > 
         < /Programs > 
     < /Controller > 
 < /RSLogix5000Content > 
L5X files always have the same root element – "RSLogix5000Content". Its attributes give us a better understanding of what we see. In the example above we see TargetType="Routine". That means that we have an export of routine. It is not a complete project. TargetName= "Example" means that routine has the name "Example." This is also indicated down the tree in the element "Routine." Its attribute "Name" has the same value – "Example." Type "RLL" means that routine is written in ladder logic.

If we go down to rung, we will find the rung logic: <![CDATA[XIC(bit1)OTE(bit2);]]>

Here is how it looks in Studio 5000:
You can get to the menu shown above by double-clicking on the rung's number in Studio 5000.

Surprise! So well-known Ladder Logic can be presented as text! In fact, any programming language in Studio 5000 can be converted to text and saved as L5X.

You may ask - what is CDATA? Logic in Studio 5000 is shorter and is missing all this CDATA stuff.
In short – CDATA is Character Data. Everything between "<![CDATA[" and "]]>" will be ignored by the parser (we will talk about parsers later). So if we exclude this structure we will see exactly what we see in Studio 5000 – "XIC(bit1)OTE(bit2);". CDATA is needed when special characters and structures have to be considered a text and not part of XML:

<Text><abc></Text> - incorrect. Missing </abc>.

<Text><![CDATA[<abc>]]></Text> - correct. "<abc>" is considered a text.

Keep in mind that ladder logic is presented as text and is written in Neutral Text format, not ASCII Text.

So ok, this is all boring theory. Where is the practical application?

The first and easiest thing that comes to mind is to use "Search" and "Replace" in the text. And this will work fine but has some limitations. You have to be very accurate when replacing multiple instances – the search mask may affect something you did not know even existed in the L5X body.

But the trick that brings the real benefit - text can be generated from pieces and injected into XML, or the whole XML can be automatically generated.

We will take a deeper look at it in Part 2.