Ladder Logic Programming Tutorials
Update! The free period is over but you can still get the book on Amazon.
The CIP series includes nine step-by-step videos that demonstrate the CIP process while creating the program that makes it work using ladder logic. CIP is an acronym for Clean In Place. CIP is an industry standard which is used in processing and manufacturing plants globally. Clean In Place means just that; automatically clean without disassembling various components such as valves, tanks, screens and other peripheral devices.
The CIP series is broken down into nine easily digestible video tutorials that step through creating a simple yet working CIP sequnce. To get the most out of the series start with tutorial one and follow along with the tutorials. If you don’t have a copy of RSLogix 5000 click here to get a copy. The lite version has some limitations, however it will work just fine to follow along with the tutorials.
The first video in the tutorial walks through creating a project using RSLogix 5000 software. The project is created using version 20 of the software. You can get a free lite version of the software here which will enable you to follow along. The free software is version 17; however any version will do, newer or older.
In this first tutorial we will create some Boolean tags which will serve as our inputs and outputs. In our case the I/O tags will communicate with an HMI program.
The HMI Program will be a graphical representation of our CIP_Tank, Valves, Pump, Agitator, Start and Cancel buttons. The ladder logic will actuate all the peripheral equipment seen on the HMI screen; the outputs of the ladder program. The ladder program inputs are the Start and Cancel push buttons.
The ladder logic project will be configured to run on an emulator. The emulator is nothing more than software that runs on a PC that emulates a PLC.
The following is the list of Boolean tags that will be used.
In the second tutorial we will be creating UDT’s or User Defined Types. Placing tags into UDT’s allows better tag organization, uses less memory and makes the code more portable. A User Defined Type is merely a logical collection of tags.
After creating the CIP data type we will create a new tag named TNK_1 of the data type CIP. Later if we decide to build another tank we can simply create another tag named TNK_2 of data type CIP. The data type CIP is a structure defined by its members. It is nothing more than a definition. The tag TNK_1 is an addressable tag of type CIP.
Our UDT will be named CIP and will contain the following members:
The .Control tag is a Pre-Defined tag required by the SQO instruction. The control tag contains 10 members. Our project makes use of the .LEN, .POS, and .DN members.
The Output_Array[x] tag is an array of 20 DINT’s. Addressing an element of an array is done by addressing the index number of the array. For instance addressing the fourth element in an array would look something like this: TNK_1.Output_Array. Remember, arrays start with the fist element which is the 0th element in the array, 0 through 19 makes up 20 elements.
TNK_1.Output_Array. 1st element
TNK_1.Output_Array. 2nd element
TNK_1.Output_Array. 3rd element
TNK_1.Output_Array. 4th element
TNK_1.Output_Array 20th element
The TNK_1.Output tag is the destination of the data that will be sequenced. Data is sequenced into this tag from the TNK_1.Output_Array[x].
The TNK_1.Mask is required by the SQO instruction. A mask is nothing more than a filter. In our case we will not be filtering anything so we will fill the mask with ones. Basically the instruction runs data from the output array through the mask and places the filtered data into the output word. Take a look at the following examples:
Array_ = 0010_0010
Mask = 0000_0000
Output Word = 0000_0000
Array_ = 0010_0010
Mask = 1111_1111
Output Word = 0010_0010
The filtering is done at the bit level. The data is checked bit by bit. This is nothing more than AND logic. Bit 1 AND bit 2 must true.
The TNK_1.Step tag is used to enable and disable the SQO instruction. Enabling and disabling the instruction increments the sequence by one step as indicated by the TNK_1.Control.Pos tag.
We are on the third video in the series and it’s finally time to start putting some ladder logic together. Rather than using the default main routine our ladder code will be placed in a routine called TNK_1_CIP. In order to call this routine we will need a JSR or Jump To Subroutine instruction placed in the main routine.
Ladder programs contain a main routine that is called automatically when the program is triggered. As a general rule I use the main routine only to call other routines in the program. This is done simply by placing a JSR instruction in the main routine which calls out subsequent routines.
At the heart of the CIP program is the SQO Sequencer Output instruction. The purpose of this instruction is to load data into an output word in a stepped sequence. The data loaded into the output word then turns on/off our various valves, pump and agitator.
In the previous video we created a database. The database is nothing more than an array of DINT’s 20 elements in length, 0 through 19. Each time the SQO instruction is enabled the control tag TNK_1.Control.Pos is incremented. Data from the array pointed to by the TNK_1.Control.Pos tag is loaded into the TNK_1.Output tag.
The first time the instruction is enabled the TNK_1.Control.pos member will increment from 0 to 1. The SQO instruction will load the data from the tag TNK_1.Output_Array into the output word TNK_1.Output. The data in the output word will then be used to turn our tank valves, pump and agitator on and off.
In the fourth video in the series we will add logic that will run our outputs. Once data is sequenced into the TNK_1.Ouput tag the data will be used to turn outputs on and off. This is done utilizing simple ladder logic. The output word will be examined at the bit level to turn the following outputs on and off: wash water valve, detergent valve, agitator, drain valve and drain pump.
To finish off this tutorial we will add a XIC Examine if Closed instruction that will enable and disable the SQO Sequencer Output Instruction. Every time the SQO is enabled the instruction will load data from the array to the output word at the position of the sequencer control position.
In this tutorial we will place data into our array of DINT’s. By default the Radix of our database is decimal; however we want to enter our data at the bit level. So first thing we will do is change the Radix of our database to Binary.
Next we will manually place 1’s and 0’s into the database to turn our outputs on and off. Remember the first five bits are the only ones we will be using for this project. Refer to the following table for the cross reference of output word to output:
TNK_1.Outpt.0 = TNK_1_WASH_WATER_VALVE
TNK_1.Outpt.1 = TNK_1_DETERGENT_VALVE
TNK_1.Outpt.2 = TNK_1_AGITATOR
TNK_1.Outpt.3 = TNK_1_DRAIN_VALVE
TNK_1.Outpt.4 = TNK_1_DRAIN_PUMP
In the previous tutorial we added data to our database and changed the Radix to make the data visible. This enabled us to manually step through the sequence and turn various outputs on and off.
In this tutorial a timer is added to automatically step through the sequence. We will use a simple recycling circuit to create a timed pulse. A TON Timer-On instruction preceded by an XIO Examine If Open instruction addressed to the timers done bit will complete the circuit. The idea is that the timer will run until the accumulator reaches the preset time triggering the done bit which resets the timer and the cycle restarts. What we end up with is a pulse every 1.5 seconds. This pulse is used to trigger the SQO instruction to sequence to the next step.
The next logical step in our project is to allow each step of the sequence to have a different time. Luckily for us we know exactly how to extract data from an array and use it to make things happen.
The first thing we will do is add another array to our CIP tag. Next we will add another SQO instruction in parallel with the original SQO instruction. The instruction will use the same control word (TNK_1.Control), this way the time and data files will stay synchronized.
Rather than loading time from the array into an output word we will configure the instruction to load the time directly into the timer preset.
The last thing we need to do is populate the time database and run the process. Each step now gets a different time loaded from the time array.
Our little program is looking good, there is just one problem and that is it never stop it just runs and runs. In this tutorial we will add a simple seal in circuit. The circuit will start and stop our process.
A Start push button on the HMI will start the process, and a Cancel push button will stop the wash cycle.
To finish up the tutorial the done bit from the sequencer control word is used to stop the circuit, and a RES Reset instruction is used to reset the sequencer control word TNK_1.Control
This program is shaping up, it now turns on and off when the sequence is complete and when canceled from the HMI.
In this tutorial some logic will be added that clears the output word TNK_1.Output as well as the timer preset.
When the timer is reset from either a cancel or a cycle completion the preset retains the last loaded value. When the program is started an appropriate time value will be loaded into the preset, however for demonstration purposes this program will clear the timer preset when the wash cycle is off.
The next thing to do is insure the output word TNK_1.Output is clear of data. This is especially important as the data turns outputs on and off.