PLC: Programming in List on a Mitsubishi
PLC – Part I
by Jim Rowell - www.mrplc.com
Posted 12-29-03
This is a tutorial written for 2 sets of people. First its
intended for those just starting out who have at least learned
how to use the basics of their editing software in order to
enter a simple program. They should already understand the
basic concepts such as x0 is an input, y0 is an output. It’s
also intended for advanced users of Ladder who are curious
about List. Hopefully it’s not too difficult for the
former or too simplistic for the latter. I'm not an experienced
tutorial writer, so apologies in advance! ;)
You're bound to have a better grasp of PLC coding and the
best ways to approach problems if you understand how the PLC
reads and executes your code.
RELAYS VS THE PLC
First of all, despite
the fact that the PLC was designed as a direct replacement
for relays, its logic is actually quite
different. Relays are 100% parallel logic. Every single part
of a relay control system operates simultaneously. If you were
to draw several rungs on a relay diagram and put one coil on
each line with no contacts on any of the lines, every relay
would energize at the same time when power was applied. If
you add contacts to each line and the contacts on a line change
at some time, the coil on that line is instantly affected.
This makes relay logic blindingly fast by nature (its only
the relay's mechanical limitations that make it slow) but it’s
often a source of trouble. There can be a race effect where
different logic states occur if this relay closes faster than
that relay this time but not the next time. On the other hand,
the PLC is sequential in operation. One thing happens at a
time. In happens in the order you dictate and its the same
order every time. In fact, the entire PLC program doesn't exist
as far as the PLC itself is concerned. Only the single piece
of code that it happens to be examining at any one time matters.
Here's how it works:
First the PLC's operating system examines the state of all
of the external wiring inputs. It records this data to an area
of memory called the "input image". This image or
record of the inputs is what will be used for input reference
while executing your code. The real inputs are not used. The
PLC then looks at your code starting at the beginning and progresses
through it. The PLC only keeps track of a single logic result
as it’s reading your code. This result will be equal
to 1 (true) or 0 (false). There are complications to this such
as when the operating system must read ahead during complex
logic or when certain things require stacked results but its
true for the most part. As it reads your code, it will update
any changes to the outputs by writing to an area of memory
called the "output image" rather than the actual
outputs themselves. When it reaches the end of your code, it
then turns the real outputs on or off by copying the output
image memory to the actual output registers. This start to
finish cycle is called a "scan" and repeats endlessly
over and over. In summary, the inputs are read once as a group,
then your code is executed and then the outputs are updated
as a group. Without this cycle method, inputs changing midway
during your program could cause strange results and you couldn't
change your mind about outputs before finally turning them
on or off for real. With the scan method, we have an almost
imaginary world inside the program where we can do what we
want with no interference or consequences. It’s only
at the end of each scan that we have to worry about reality.
BOOLEAN LOGIC
This is at the heart of the PLC's operation. You need to know
this.
There are other ways of looking at PLC logic that perhaps
are more intuitive than the pure Boolean method but you still
must understand it and have it in your arsenal of tools if
you are going to have more than a basic ability with PLC's.
Unfortunately, this is a scary subject to the uninitiated but
stand fast! It’s really not that hard to grasp. Just
remember, it’s the basis of all things digital. Even
good old relays are digital devices that lend themselves well
to Boolean logic.
Boolean logic uses 2 states to represent things. Something
can be on (equal to 1) or it can be off (equal to 0).
We perform what are known as "logical" operations
in Boolean. Things like "logical AND" and "logical
OR" (I'll use uppercase to denote a logical operation).
logical AND means "if both things equal 1 then the answer
is 1"
or in other words:
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1
Logical OR means "if either thing equals 1 then the answer
is 1"
or in other words:
0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1
Logical NOT (also called "invert") means "invert
the item, make it the opposite, the current value is NOT what
I want"
or in other words:
NOT 0 = 1
NOT 1 = 0
You perform a logical NOT on something when you know you want
the opposite result.
So now if we said given that X=1 and Y=1, you'd know that
X AND Y = 1 and also that X OR Y = 1
or given that X=0 and Y=1, you'd know that X AND Y = 0 but
X OR Y = 1.
Or, to get tricky, given that X=0 and Y=1, you'd know that
NOT X AND Y = 1 but X OR NOT Y = 0
You should read and re-read this until you understand it.
It’s important.
When something is equal to 1 we say that the result is "true".
When something is equal to 0 we say that the result is "false".
In proper Boolean, there is a defined order for performing
operations just like in math where multiplication is performed
before addition. In Boolean, AND operations are performed before
any OR operations. In fact, the short form method of writing
Boolean uses the times symbols "x" or "*" to
represent AND while the plus sign "+" is used for
OR. (eg. 1+0=1 is the same as writing 1 OR 0 =1). The "times" symbol
expresses the fact that AND has precedence over OR. You don't
have to worry about this in the PLC. It simply performs the
operations in the order they are presented. Just be aware that
it’s a deviation from what goes on outside of the PLC
arena.
PROGRAMMING
To program the PLC we have several options in the way of languages.
The two common ones are Ladder and Instruction List. There
are many tutorials that discuss Ladder so we'll stick with
the one most near and dear to my heart: "Instruction List".
List is a "mnemonic" or text-based language. It’s
exactly like the Assembler languages used to program microprocessors
in their native language. A native language is one that the
processor directly understands. You type a "mnemonic" which
is simply an abbreviation consisting of a few letters to represent
a command, and the editing software on the PC sends the corresponding
code number to the PLC. There are no interpretations or changes
made other than the fact that you type in letters and symbols
and the PLC reads numbers. When working with a PLC, you are
not really programming the processor. There is a high-level
operating system on-board that is programmed to “be” a
PLC but the net affect to you as a programmer is identical
to working directly with a processor. In other words, you are
about to become an Assembler programmer! Pretty exciting, right?
;)
Mitsubishi uses mostly obvious mnemonics such as LD to mean "load
the accumulator", AND to mean "AND", OR to mean "OR" and
OUT to mean "send the result to the output image".
These and the following may seem like gibberish to you at first
but plough through it. There is a bit of a learning curve and
then the sun breaks through the clouds!
LDI (Load Inverted; more commonly thought of as Load Not)
means "perform a NOT operation on the following value,
then load the accumulator with the result".
AND means "perform an AND operation".
ANI (And Not) means "perform a NOT operation on the following
value, then do an AND"
eg. given that X1=1 and Y1=0, X1 ANI Y1 =1 because although
Y1 contains a zero, it is first inverted to a 1. The AND operation
is performed as 1 AND 1 which = 1.
ORI (Or Not) means "perform a NOT operation on the following
value, then do an OR
eg. given that X1=0 and Y1=0, X1 ORI Y1 =1 because although
both contain zeros, Y1 has first been inverted to a 1. The
OR operation is performed as 0 OR 1 which = 1.
WHAT THE PLC SEES
People generally think of the PLC as being more complex in
its method of reading lines than it really is. They picture
it reading an entire Ladder rung like they would and then making
a decision at the end as to whether or not to turn on the output.
It actually never makes a decision when performing basic logic
such as AND, ANI, OR, ORI. It just keeps track of the current
state of affairs in a reserved memory location known as the
Accumulator or just "A" for short. This is an old,
tried and true processor method that the PLC's operating system
emulates.
Example:
If we were to write some standard English control logic as
such:
if x1 is on and x2 is on or y1 is on and y2 is off then turn
on y10 else turn y10 off.
and then rewrote the same thing for the PLC it would look
like the code below. The comments show how the PLC executes
it.
LD x1 ;the PLC "loads" the Accumulator (A) with
the value of x1 (ie. the value of x1 is moved into A).
AND x2 ;the PLC performs A AND x2. The result is placed in
A.
OR y1 ;the PLC performs A OR y1. The result is placed in A.
ANI y2 ;the PLC performs A AND NOT y2. Result is placed in
A.
OUT y10 ;the PLC "outputs" the value of A into the
output image memory location reserved for y10.
As you can see, no decisions were made. The PLC didn't even
turn the output on or off. It just moved the result to the
output image when it was told to! Later, at the end of the
scan, the entire output image will be copied to the real output
registers. If there ends up being a 1 in a register, the associated
output will magically turn on. If it contains a zero, it will
turn off. The turning on, turning off part is done by the hardware.
The operating system has nothing to do with it.
The PLC doesn't even perform the operations in the proper
order according to the rules of Boolean logic. It simply AND's
and OR's things as presented.
This is how the PLC with a simple and comparatively slow processor
can scream through your code at such speed. Its efficient and
only concerned with simplicity.
When we start a new "series" or collection of statements
in List or begin a new rung in Ladder, what we are really doing
is telling the PLC that we want to start over and it should
not use any previous results. In other words, we want it to "Load
the accumulator" with the first value rather than perform
an operation with the old value from the previous line. Loading
the accumulator with the new value overwrites whatever was
already there.
STARTING SIMPLE
Okay, so now lets back up and start simple:
You want a motor to come on but only if you turn on a selector
switch. So you connect a switch to x0 on the PLC and you connect
the motor's contactor coil to y0.
Now what? First we name the inputs and outputs. Never, ever,
ever, use the raw I/O names in a program. Its fine for describing
things to your friends in snippets of code about how to do
something... but don't use x0, y0, etc in a real program. It’s
hard to read, it’s hard to debug and it’s hard
to change. Okay, so we'll call x0 "switch" and y0 "motor".
Right?
Here's how your program will look:
LD SWITCH
OUT MOTOR
That was pretty easy, no? To make it easy to read, instead
of thinking "LD", think "IF" and instead
of OUT, think "then" or "turn on".
In your head it becomes:
if switch
then motor
What if you want the motor to shut off if it gets too hot?
Oops, that's right, we have overload contacts we have to monitor.
So lets put them into x1 and call them "overload".
Typically, we want the motor to only turn on if the overload
contacts are closed. Same as the switch. So now we have:
LD SWITCH
AND OVERLOAD
OUT MOTOR
Now someone adds a special sensor on the machine and tells
you the motor must turn off if the sensor turns on.
LD SWITCH
AND OVERLOAD
ANI SENSOR
OUT MOTOR
So now in English, this would read...
If switch (was that supposed to be open or closed?) and we
have an overload... no, wait! If we don't have an overload...
and the sensor is not on (not open or not closed?)... hmmm....
this is getting confusing!!
We've only got 4 lines of code and already its unclear exactly
what we are trying to do. Time for some more RULES!
NAMING CONVENTIONS
Name your inputs and outputs according to what they do when
they are "active". That's an important word. Forget "open" and "closed" for
a minute. Think "active" and "inactive".
Every item has a purpose or you wouldn't be connecting it in
the first place. You must always name an item according to
its purpose. It will be “active” when its fufilling
its intended purpose. The purpose of the switch we used was
to turn on the motor or make it run. We should have called
it something like "RUN". Even better would be to
call it "RUN'SEL" (for Run Selector). Notice I used
2 words separated by an apostrophe. We are only allowed a single
word but often two or three make the purpose clearer. The apostrophe
is a good way of cheating your 1 word into several. The more
traditional underscore also works but it’s easy for your
eye to miss it and a tired and worn printer will often drop
it. Now you know the following about RUN'SEL:
If the real switch in the field is active then our input called
RUN'SEL is active (x0=on),and its
name tells you what the intended result should be (RUN).
It doesn't matter how that was achieved in the field ie. normally-open
or normally-closed contacts. An input is only active if you
have a live electrical signal coming to it.
Now, how about our overload contacts. Their purpose in life
is to detect overloads. They become "active" when
an overload occurs. So they can properly be called "Overload" contacts.
Since we have decided to use normally-closed contacts from
the overloads, we have a problem. The signal into the PLC will
be OFF (inactive) when the overloads are active. In other words,
the input should be named "NO'OVERLOAD" because when
the input is active, the overload contacts are inactive and
there is no overload.
A better method is to use a slash in front of the name which
is read as "NOT". This is just my personal idea,
stolen from Boolean, but it works really well. The slash tells
you that the input is inverted (inactive when the input is
on). So "/OVERLOAD” is read as "not overload".
The field device is called "Overload" but the input
on the PLC is called /OVERLOAD. When you see the slash, it
tells you the field device is using normally-closed contacts.
Otherwise, everything is from normally-open contacts. Beautiful,
no?
Let's see where we are now (the comments show how YOU would
read it):
LD RUN'SEL ;”if run’sel”
AND /OVERLOAD ;”and not overload”
OUT MOTOR ;”out motor”
That's better. We need a name for the sensor. Let's say that
when its active, it’s telling us that the machine is
busy and the motor must remain off. Let's call it BUSY.
LD RUN'SEL ;”if run’sel
AND /OVERLOAD ;”and not overload”
ANI BUSY ;”and not busy”
OUT MOTOR ;”out motor”
In English: If the run selector switch is on and there is
no overload and the machine is not busy then turn on the motor.
You can see how important the names are when reading List.
They are everything. Another benefit of the "slash" is
when you have a line like "LDI /OVERLOAD", you can
cancel out the 2 "NOTS" in your head and it makes
more sense. Instead of saying "If-not not-overload",
its just "If overload". It means the same thing!
ORDER OF OPERATIONS
I suspect this is the area where most people give up. They
don't understand how combinations of OR and AND are seen by
the PLC. And it can soon become very confusing to read. Complex
Boolean is actually more clearly displayed in Ladder format
than it is in List. But List can manage it, and Ladder is not
very useful for displaying non-Boolean operations such as math
and the higher functions. So the challenge is to make your
List readable when doing Boolean so that you can take advantage
of the rest.
First thing to remember is that the PLC completes each statement
as it reads them. It doesn't read the entire collection of
lines at one go. For those familiar with Ladder, its like saying
that the PLC reads one contact and adds it to its sum in the
Accumulator, forgets that the contact exists and goes on to
the next contact. It doesn't read the entire rung at once.
If it encounters an AND, its the same as if you have a contact
in series with everything that came before. If it encounters
an OR, it’s like a contact in parallel with everything
that came before. On a Ladder diagram, the AND is always in
series with the ENTIRE rung. The OR is always in parallel with
the ENTIRE rung (in other words, its a new line that starts
back at the left rail). That being the case, how the heck can
we do anything?!
There are a couple of methods for telling the PLC to hang
on to a result for later use. Just like on your calculator
where you have the Memory feature. On your calculator you might
add some figures together, place the result into the Memory,
do some multiplying with new figures and then finally add the
result to what you previously put in the Memory. We can do
the same thing on the PLC in several different ways.
Write out a series of statements such as follows:
LD RUN'SEL
AND /OVERLOAD
ANI BUSY
Don't complete the series by using an OUT statement. Now start
a new series:
LD HIGH'SEL ;high-speed selector switch
The PLC knows you are not done with the first series because
you haven’t "used" the result yet in an output
type of statement. When it encounters the new LD statement,
it puts the old result into a temporary storage area called
a stack. It knows you will need it later.
Now carry on:
LD HIGH'SEL ;high-speed selector switch
OR LOW'TEMP ;low temperature sensor
ANB
That last command was "AND BLOCK". It means pull
the old value from storage and then AND it with the current
value in the Accumulator. In other words, "I want the
old series (the old block of code) to be true AND I want the
new series (new block of code) to be true before performing
any outputs. You could also have used ORB. It means "If
the old series is true OR if the new series is true then...").
Now, you follow with whatever output code you wish. Let's put
it all together:
LD RUN'SEL
AND /OVERLOAD
ANI BUSY
LD HIGH'SEL
OR LOW'TEMP
ANB
OUT MOTOR
In English: If the run selector switch is active and we have
no overload and the machine is not busy... if the high selector
switch is active or the low temp sensor is active... if both
of those series of things are true then turn on the motor.
Make sure you use a blank line to separate the two series.
It keeps things readable.
When you have seriously twisted logic to express, and even
the handy ANB, ORB won't manage it, there is an all-powerful
stand-by at your disposal. Its called MPS for "Memory
Point Store". It’s exactly like the one on your
calculator. No different. You should avoid it like the plague
in most cases because it can lead to code that’s difficult
to read. There are times, however, when it’s exactly
what the doctor ordered. Usually, it’s better if you
repeat sections of code or store your own result with its own
descriptive name rather than using MPS.
That's all for Part 1. We'll try out some more examples and
look at some more advanced topics in Part 2.
Happy coding!
|