The Essentials of Structured PLC

This tutorial is an expansion of the CE September Back to Basics article.

By Dadla Ponizil, San Diego, Calif. September 1, 2001

Figure 1

L adder code, as any other software language, can–and should–follow principles of structured programming: modularity, top down design, single entry/exit points, bottom up testing. This tutorial will provide the essentials to do just that: develop PLC code that can be read and supported once the project is signed off. This methodology is called Station Mapped Programming (SMP) and the four steps are described on the following pages.

Step 1: Divide and Conquer: Separate the project into its sub-systems.

Unless a system is so basic (fewer than say 16 I/O) it can be segregated into modules or sub-tasks. Let’s use the graphic above, a part sorting and storage tool, for illustration. Keep in mind that the specifics of the system don’t matter; your system will be different, but the concepts still apply. Here, a conveyor feeds parts to a pick and place which moves the parts to a transfer conveyor. The large gantry-mounted pick and place receives the part from the transfer conveyor and places it in the appropriate tray. Once full, the part trays are put away by an elevator into transfer carts. This system has been divided into task areas or stations, numbered sequentially (0,9), beginning with the input stage(s) and progressing to the output stage(s). Using 10 stations will take care of most PLC-embedded systems, and the digits 0,9 readily map to memory allocation.

The reasons for doing this are:

It allows us to focus on each subsystem and define the specific functionality of each without the distraction of the whole. In other words, it enables us to get our arms around the project.

Defining the process requirements on the subsystem level will yield each station’s input and output variables.

As part of our ongoing system review, we can, at this early conceptual stage, take a pass at the key question: Will this do what the specification requires?

The following table is useful for organizing the station mapping process.

Station #

Feeds parts into the tool
Incoming part present
Part available to pick and place

Pick and place
Receives part from conveyor; places parts on appropriate transfer conveyor track

Part available from conveyor

Transfer conveyor empty

Part status

Part removed from conveyor

Transfer conveyor
Conveys parts to gantry pick and place
Part present at conveyor head

Removes part from transfer conveyor tracks and places part in appropriate tray.

Part present at pick position

Process tray is available

Process tray status

Receiving rack
Stores accumulated and sorted parts for further processing.
Process tray status
Process tray status

1. An actual conveyor would use some sort of part conveyance mechanism such as pallets or part singulation, however, for the sake of clarity, we’ll overlook these details

System division takes place along functional boundaries. If you find a particular station has more than say 4 inputs or outputs, that process may need to be divided further.

Note that the stations don’t need to be numbered in any particular order or be consecutive. But if the subsystems are serially dependent, such as a conveyor with multiple stopgates, sequential numbering leaving spares affords most flexibility.

Memory assignment:

Physical I/O and internal memory are mapped using the station number.

Since PLC designers use a variety of memory organizations and naming conventions, we’ll use A/B SLC500 as an illustration2. Your memory assignments will depend upon the particular platform; in any case, some method of memory allocation is needed so the code remains modular. Thereby, if you need to add a station later, its memory is not already in use somewhere else in the program. Although wasteful of memory, the cost of design time is far greater. How many times have you had to search for available words and bits to use for a new control function? Or worse, how many times have you had to search for addresses where multiple usage created unexpected behavior?

2In symbol-based systems such as Allen Bradley’s ControlLogix where I/O mapping is done for you, one should use a naming scheme, which embeds the station number in the symbol. For example, a pick and place end effector could be STAnGRIPPER_CLOSED, STAnCLOSE_GRIPPER, etc. where n is the station number. This way, sub-system separation, functionality and identification are still preserved.

The following table illustrates the memory map derivation for an Allen Bradley SLC 500.

Station #
Program File
Physical I/O3

I:1,3; O:2





I:5,7; O:6





I:9,11; O:10





I:13,15; O:14





I:17,19; O:18





3This is a loose assignment since actual I/O count and kind will vary; however, some organization should be considered. Typically, inputs to outputs run 2:1. We’ve also allowed for spare slots. As a minimum, like devices should use contiguous I/O since the ultimate consideration is: Can you move this process to a new location without re-wiring the entire rack

Notes on memory mapping:

The key concepts are each station gets 10 program files (subroutines.) Each subroutine is allocated word and bit memory according to the file number. Each receives 10 words of integers, timers, and counters; each receives 100 elements of bit memory, etc. Again, as long as there is no question of memory assignment when a new subroutine is inserted, the method you use is valid.

Further refinements can be made to the assignment of subroutine files for functions recurring across stations. For example reset/homing routines can all be 1n5 files; fixturing controls can all be 1n1, etc. where n is the station number.

By tying memory space to functional blocks, we are making code objects which are portable in every way.

Step 2: Design each process using state machine representation.

This is where the rubber hits the road: the design of the actual controls. Taking one station at a time, bring together all available information, such as system specifications, truth tables, servo control protocols, network protocols, customer specifications, cut sheets, etc. and develop a state machine representation of each station’s function(s). Use multiple sequencers when station processing is complex. For example, a station which fixtures a part, wraps a flex circuit around it, then stakes it requires several subroutines/sequencer files to handle the operations in a modular fashion. In general, if the process takes more than 32 states, break it up into two (or more) sequencers.

If, during the development of state representation, your discover you’re repeating state/action segments between sequencers, isolate these into another program file/sequencer.

The reasons for using state machine modeling are:

Design decisions are made up front, before labor has been spent on coding.

The principals in the project can come together and make design decisions at the outset. Although they told you exactly what they wanted, when faced with a concrete design indicating precisely how the system will behave-what the startup conditions will be, what alarms will result, how the process will deal with unexpected stimuli or more important, what stimuli it will ignore-you’ll find lots of engineering changes taking place to this ‘hard and fast spec.’

The state machine representation holds a one to one correspondence with the ladder, so if you can come up with a logical design in state representation, your controls will work in the PLC.

The project is self-documenting since the state diagrams represent the control specification.

It’s easier to explain to those not intimate with the project what will take place using state diagrams.

FigurFigure 2: Conveyor control sequencer

Figure 2 shows a three-state sequencer to illustrate the development of a design using state machine modeling

State Diagram Symbols

not equal






Notes on Figure 2:

When defining a process, it’s often helpful to make a simple sketch indicating the primary control elements such as actuators, sensors, entry and exit points, etc. Here we’ve indicated the controlled device: a part singulator mounted on a conveyor.

Starting with the initial condition (no parts present) begin defining the states. You always begin with the idle state as the entry point. No actions take place at the idle state, and the process always resets/homes to this state.

This process is driven by parts entering the conveyor, therefore the first state change occurs when a part arrives at the singulation slides. Note that as part of this sequencer’s reset function, the singulator is initialized to the HOLD PART position (leading gate retracted and trailing gate extended.)

The transition from IDLE to STATE 2 is made when the conditions PART PRESENT AT CONVEYOR HEAD AND NO PART AT PICK AND SINGLE STEP are all true. This is indicated by using the Boolean operator ‘&’ representing an AND relationship. See Figure 3 for the corresponding ladder rung.

The SINGLE STEP condition is a bit address that allows this transition to be made in single step mode. Elsewhere in the program, this bit is turned on for one scan. By ANDing this bit with any state transitions where single stepping may be desirable or where the machine needs to halt processing, we gain two control modes: single step and halt. Typically, we want the tool to trigger a single step before any action involving a motion. Therefore, we add the single step here before the singulator is toggled (before States 2 and 4).

The State 2 to State 4 transition requires no part at the singulator AND a part to arrive at the pick position AND SINGLE STEP. By requiring the part to arrive at the downstream sensor, we make sure no parts are stranded or jammed on the conveyor.

Note that colors are used the make the state diagram more readable. In the next example, we’ll illustrate the use of flags for sequence to sequence handshaking.

Other Benefits of State Machine Programming:

Fault detection. In the sequencer of Figure 2, we can add a fault detect timer at State 2 to time the event and alert the operator if the part does not arrive at the pick position in a reasonable time frame. Fault detection is another important advantage of state machine programming. The state number becomes a condition of the fault detection mechanism. It is simple to add delays to any state transition condition(s).

Troubleshooting and setup. Using state machine sequencing also aids in troubleshooting and setup. By single stepping, adjustment of sensors, cylinders, homing flags, etc. becomes a methodical, controlled process with little chance of unexpected behavior.

Annunciation. By simply scanning the state words, the tool tells you ‘where it is.’ This is especially handy when designing MMI screens showing the state of the process.

Start, cycle stop, and single step functionality. This is built in by using the single step bit as part of any transition requiring a step point.

Determinism. State machine programming allows one to determine what the tool will do before it does it. This makes it safer and less likely to cause damage.

Changes. Modification can be made quicker with confidence of running again since the process is well defined and self-documenting. Specifically, transition conditions and actions can be readily modified since manipulation of a particular process or device is encapsulated in that sequencer’s action rungs (not all over the program.)

These translate to the bottom line: efficiently designed firmware that is safe, reliable, and supportable .

Step 3: Ladder Coding.

This is almost an afterthought since the state diagram IS THE LADDER. Once you convert the state diagram to ladder, it is only a matter of adding the state word/bit descriptions to reflect actions, and coding the state transitions/actions. With a sequencer template and station-mapped memory, you just do an indexed cut and paste to create sequencers for new inter-station files or other station files. Your time is spent designing the process, not laboring over complex rung structures. Figures 3 and 4 show the ladder corresponding to the process of Figure 2.

Figure 3: Transition rungs for the conveyor process

Figure 4: Action rungs for the conveyor process


Each bit of the state word N107:10 has a one to one correspondence to each state of the state diagram. Likewise, each transition condition is coded using combinational logic to match what the state diagram specifies. Hence the information on the state diagram contains all the information to write the corresponding sequencer.

Note the use of one-shot instructions and output latch/unlatch instructions. The purpose is to leave the addressed devices (or memory elements) manipulated only once upon entering the state. It is then possible to write to these elements using an MMI device or debug screens.

What is left for this code to run our conveyor is the code to advance the sequencer once the transition conditions decode to true. This is accomplished by the following rung:

Figure 5: Sequencer state advance rung

The essence here is simplicity. Whenever a sequencer’s transition conditions decode to TRUE, the New State Bits Word 0 or Word 1 become non-zero. This rung, which follows the last transition rung and precedes the action rungs, copies the next state bit to the local state words (here N107:10, N107:11). The New State Bits Word 0 and Word 1 are then cleared.


A given state will remain active (its bit value will be 1) for at least one scan. This is important because other sequencers may be looking for the state later in your program. Also, only one state may be true during any one scan cycle. This is done to avoid ambiguity in the state machine algorithm and should be strictly adhered to by you the programmer. Since this rung uses rudimentary instructions, it can be coded on any PLC platform.

What remains of the control code for this particular process is largely up to you. The sequencer handles all the sequential logic and control. Typically one would add error/fault decoding and a reset rung. The former would handle fault conditions such as part jams on the conveyor or singulator sensor conflicts, etc. The latter initializes the sequencer to the idle state and puts the singulator in the HOLD PART condition.

Step 4: Test and Debug

An important advantage to sequencer control is the ease of bottom-up test and debug. First, one isolates the common files-utility files, driver files, etc.-and tests them separately. Then, having confidence in these, one enables the larger more complex process files one at a time. (Use selective jump to subroutine instructions to do this.) Sequencers allow you to single step through the code so race conditions and logic errors can be identified methodically rather than the less predictable (though more exciting): ‘OK folks, I’m going to put it in RUN mode. Stand back!’

More Examples

To expand upon these concepts, we’ve added two more state machine diagrams. The first (Figure 6) controls a 3-axis pick and place. The second (Figure 7) is a utility file which is ‘called’ by the first every time a servo move is required. Note that the functions performed by the servo driver could have been built into the main pick and place file but we chose to separate them. Since the operation of setting up a target address, delaying, then triggering the move are repeated, the entire sequence is best handled in a separate routine (or function ). This way the routine may be tested separately, other sequencers can use it, the main program is more compact, and should a change to the driver be needed, it would be done in only one place.

Figure 6: Servo actuated pick and place sequencer

Notes on figure 6:

Here a pick and place moves a part from the end of the conveyor to a holding tray. State 2 initializes the Z-axis down move by writing the move ID or address into the servo execute subroutine’s input register. It then latches a flag (SERVO EXECUTE FLAG) and waits until the flag is reset. The handling routine (see Figure 7) uses this flag to trigger the sequence to actually execute the move. Note that only one flag is used to accomplish all handshaking between the two routines. When the move is done and the flag is cleared, this sequence advances to State 4, which closes the gripper. At State 4 we look for the gripper sensors to indicate the closed condition and we advance to State 6, and so on.

At State 6 we illustrate the use of an exception handling path. If the tray is not ready to receive the part within the time set on the State 6 delay timer, then control passes to State 7 (instead of 8) and the part is rejected into a dump chute.

Whether the process time expires or not, the sequence still returns to the idle state and waits for the next part. It is highly desirable, from the system control point of view, to have single entry and exit points for all processes.

Figure 7: Pick and place servo control driver sequencer

For more information on this tutorial or any other PLC or embedded control issues, contact Dadla Ponizil, ControlWare. Phone 760-436-5362

Comments? E-mail