In this article we are going to look at one of the more “advanced” capabilities of the Studio 5000/Logix platform of programmable automation controllers (PAC’s). Specifically, how we can create and configure Studio 5000 Add-On Instructions.
I used the term “advanced” in quotes, because to create simple Studio 5000 Add-on Instructions is not a difficult task, more, it’s an understanding of what they are, when to use them, and how to use them that is the more difficult piece.
If you’ve ever wondered what this extremely important and powerful feature is, then I encourage you to keep reading. I assure you, once you complete this article you will be looking to leverage Studio 5000 Add-On Instructions in your next automation project.
What are Studio 5000 Add-On Instructions?
Studio 5000 Add-on Instructions provide a mechanism to optimize and encapsulate reusable code or logic. Once the instruction is created, you can add it to your rung logic just like you would any other pre-defined instruction in the controller.
The key to making good Studio 5000 Add-On Instructions is to think of those scenarios where you find you are duplicating logic over and over again in your controller. What I typically do, is try to abstract away from any specific application of a device and look at how I can make it as generic as possible.
For example, typical automation systems will use many valves to control different cylinders. Valve’s come in all different types, single-solenoid, double-solenoid, detent, spring return, two-position, three-position, and I can go on and on. Likewise, cylinders come in a variety of shapes and sizes all with varying mounting and applications in any given automation project.
That said, there are some very common elements to every valve-cylinder combination that you will deploy in the field. This is a perfect opportunity to make use of Studio 5000 Add-On Instructions.
Studio 5000 Add-On Instructions – A Simple Example
Using the valve-cylinder example above, one way by which you could use Studio 5000 Add-On Instructions to generate a generic, reusable AOI is to do something like the following.
Before we do, let’s make a few assumption to keep things simple.
- The cylinders we will be controlling are double-solenoid (have two discrete coils).
- Every cylinder we will deploy to the field will have both an Advanced and Returned proximity sensor (two prox. switches).
Remember, the end goal here is to make Studio 5000 Add-On Instructions as generic as possible, this means that a common algorithm or logic will be encapsulated inside the AOI. If we carefully design the AOI with this generic quality we will be able to reuse this instruction over and over again for every cylinder we deploy in our automation projects.
Step #1 – Create a New AOI:
Create a new AOI by right clicking the Add-On Instructions folder and clicking New Add-On Instruction…

Once you click the New Add-On Instruction dialogue box will appear. Fill in the appropriate fields as shown.

Notice that the Open Definition checkbox is still checked. This will open the Add-On Instruction Definition dialogue box where we can begin to create a definition for our cylinder AOI.
Step #2 – Add Required Parameter and Local Tags:
Once in the Open Definition dialogue, navigate to the Parameters tab as shown. Here we will define all the parameters that will be required to control our cylinder. Make your parameters look exactly like mine.

Once you have all the parameter tags created, navigate to the Local Tags tab and create the following tags.

Click Apply and then click OK to close the dialogue box.
Step #3 – Add AOI Logic:
You’ll want to navigate back to the Controller Organizer Window and double click the Logic routine appearing under your newly create AOI.

We will now proceed to add the require AOI logic.
Step #3a – Add Command Logic:
These next parts are certainly subject to debate and full disclaimer – These routines are for educational purposes only. I do not warrant the use of this AOI or any other logic in a production environment.
Phew, okay now that we have that out of the way, let’s add some command logic. Add the following rungs as shown below.

Notice here that I am sealing-in the Cmd_Adv and Cmd_Ret bits with their respective output bits so they only have to be toggled once to initiate the motion.
Also notice that I have interlocked the Cmd_Adv and Cmd_Ret bits so they cannot be enabled at the same time. This is a little extra protection in case the user logic has an error and mistakenly tries to energize both outputs at the same time.
Lastly, notice that I have a Fault_Present bit in-line with both outputs to ensure that if any faults are detected the outputs are de-energized. Otherwise, the respective output will stay energized until the respective input is made. For example, if the Out_Adv is energized it will stay energized until either the In_Adv is true, or the Fault_Present bit is true, or the Cmd_Ret is true.
Step #3b – Add Status Logic:
This logic is intended to give the user-program a visual output to easily determine where the cylinder is with respect to its position or if it’s in motion. These outputs can be referenced in user-defined code to build logic.

The logic works as follows:
- If either Out_Adv or Out_Ret is true then write output Status_Moving to indicate the cylinder has been commanded to move.
- If the In_Adv is true and In_Ret is false then update output Status_Adv indicating the cylinder is advanced.
- If the In_Ret is true and In_Adv is false then update output Status_Ret indicating the cylinder is returned.
These will become outputs on our AOI_Cylinder instruction.
Step #3c – Add Fault Logic:
Now it’s time to add some fault logic to our AOI. This will ensure that if we command the cylinder to move that it must get to its final destination within a preset amount of time. Remember, we added a parameter that will allow the user-program to enter a Time_msec which will be interpolated as the maximum time the cylinder has to reach its fully advanced or fully returned positions.
For this step we will make use of the Local Tags we created in Step #2. Namely, we will use the Time_msec, Fault_Timer_Adv, and Fault_Timer_Adv tags. Let’s look at the logic and the walk through it.

Rung 5 – We perform two move commands to move the user-configured Time_msec into the two local fault timers that we setup under the Local Tags definition. Notice we are moving this time value into the preset (.PRE) attribute of both the Fault_Timer_Adv and Fault_Timer_Ret timers.
Rung 6 – This is where we setup motion monitoring on the cylinder advance action. Simply put, when the Out_Adv output is true we or going to be looking for the In_Adv input to be true within the preset time of the Fault_Timer_Adv timer that we defined in Rung 5. If the timer finishes timing (in other words the done bit .DN is set) then we will latch in our Adv_Fault output.
Rung 7 – Similarly, we will setup motion monitoring on the cylinder retract action. Simply put, when the Out_Ret output is true we or going to be looking for the In_Ret input to be true within the preset time of the Fault_Timer_Ret timer that we defined in Rung 5. If the timer finishes timing (in other words the done bit .DN is set) then we will latch in our Ret_Fault output.
Rung 8 – If either the Adv_Fault or Ret_Fault outputs are energized then we are going to set a generic Fault_Present bit that, if you recall from Step #3a, we will use to de-energize our outputs.
Rung 9 – Lastly, we need a means to clear any faults that occur. This will be handled using the Clr_Fault input that we created in our Parameter Definition.
Step #5 – Add The AOI To Your User Program:
Okay, if you’re at this point and completed all the previous steps…way to go! Now it’s time to add your newly created AOI to your user program.
Before you do be sure to save all your work to this point. Okay, to add your newly created AOI to your ladder routine navigate to the Add-On tab in your instruction toolbar. Once you’ve located it drag it onto your designer surface and place it on your rung as shown.

Spend a few minutes looking at your AOI instruction and correlate everything you see to the Parameter and Local Tag Definitions we created previously.
Step #6 – Populate Your User-Defined AOI Parameters:
Now it’s time to populate your instruction. This part is going to largely depend on your specific application and control requirements. For the purpose of this tutorial, and if you’ve been following along in our Studio 5000 Essentials video training series, you’ll know that I am simulating everything in an Emulator.
Therefore, to keep things simple I am going to directly populate these fields using my simulated I/O as shown.

Conclusion
That’s it, you’ve now completed the necessary steps to start using your AOI in a simulated environment.
Want to see it all in action. Watch it now right here on PLCGurus.NET as part of our Studio 5000 Essentials video series.
Exclusive Offer! Get the complete AOI now right here!
- Simply follow 2-Position Cylinder AOI.
Not a registered user on PLCGurus.NET. No problem! Registration is, and will always remain completely free. Simply click Register Now! and you’ll be brought to our registration page.
I certainly hope you’ve enjoyed this article and I do encourage you to become a member of our growing community of professional engineers, technicians and technologists, Register Here!
Also, check out our YouTube Channel to see some great videos…and don’t forget to like and subscribe to our channel!
If you enjoyed this article be sure to check out some of these good reads too:
- How To Become A PLC Programmer
- Difference Between DCS And PLC
- How Much Does A PLC Programmer Make
- PLC Versus Microcontroller – What’s In Your Plant?
- Essential Tools Every PLC Programmer Needs
- How To Implement A ControlLogix PID Controller
Lastly, if you run into any problems in your day-to-day engineering activities please be sure to check out our Live and Interactive PLC Forum!
And if you so desire, assist other community members by replying or offering helpful information to the questions or challenges they may be facing right now!