OMRON | Mitsubishi
Home >> Articles >> Mitsubishi knowledge >> Text
>New Article
This month TOP10
Relays& PLC Part 2
http://www.saleplc.com
Articles Entry:LKong Source: Published Time:2011-5-20
Relays& PLC Part 2

We'll be using numbered as opposed to named I/O for the examples. Don't get used to it and definitely don't be discouraged by it. Numbers work best for showing you how the code works but they're terrible at showing you what it's actually doing. Your own code (with proper I/O names) will be much easier to follow.

Experienced programmers will find the initial stuff a bit on the basic side but please, keep reading. It gets better. The more advanced topics will rely upon terminology and phrases introduced in the basic ones so I suggest you don't skip. I can pretty much guarantee you'll find a knowledge nugget or two somewhere in the following pages (double your money back, void where prohibited). 


Our focus will be on the Mitsubishi FX series but the concepts apply more or less on all plc's. Before using anything you learn here though, do yourself a favour by checking your manuals and testing your code. Take anything I say (or anyone else says) with several grains of salt. My mistakes don't have to be yours too.

The Really Easy Stuff

Okay, let's see how List compares with Ladder while writing some code.


Feel free to try any of the examples in your editing software. Just be aware that if you switch between List and Ladder views without having an output on each rung (most of the examples don't), you'll receive an error. All you need to do is add an output to the end of the List code. AllRighty then... 


We'll start at the beginning of a rung (good choice huh?). 


First we type: LD  X0

 

No surprises there. As you can see, we have begun a new rung with a normally open contact. We always have to start with the LD (or LDI) command.

Now let's add:
AND  X1

 

The AND command places a contact in series with all of the preceding logic. So far "all" consists of that single X0 contact we previously placed.  


You can perform AND as many times as you like and every new contact will be placed in series with all of the preceding logic. That's because when the plc reads a contact, all of the preceding logic has already been reduced to a single result held in the accumulator (remember? Part 1?). The plc is simply going to perform a logical AND with the accumulator and your new contact.  


AND  X2

AND  X3

 

No mystery there, right?
 
At this point, the accumulator holds the value of the output of X3.

Now try: OR  X4

 

 

 

Whoa! What the heck happened there? Unlike a logical AND, an OR command will place a contact in parallel with all of the preceding logic or in other words, in parallel with your entire rung. We're back to that accumulator thing again. The plc performed a logical OR with the accumulator and your new contact. 


AND X5  ; places a contact in series with all of the preceding logic. 

The accumulator now holds the value of the output of X5.


OR X6  ; places a contact in parallel with all of the preceding logic.


 We could go on forever. I'm told I do sometimes.


Really Smart PLC Rule #1: 

 

 

 

AND, ANI, OR & ORI commands always operate on all of the preceding logic.  

 

ie. They are always in series or parallel with the entire rung up to the current point in the logic. 

So Far So Good 

 

If you've followed along patiently to this point, you will probably agree that so far it's embarrassingly simple. After all, you're pretty smart. I guess it's time to tackle the things that are not so obvious. First off, one of the most common things you'll encounter is the need to place a few contacts in series with each other followed by some contacts that are in parallel with each other but still in series with the first ones.

Like this:

 

X0 to X3 are in series. X4 to X6 are in parallel with each other and, as a group, are also in series with X0 to X3.

You simply can't do this in List using nothing but your basic AND and OR. In Part 1, we talked about using the ORB ("Or Block") and ANB ("And Block") commands. We'd have to use them here.
Something like:

LD  X0
AND X1
AND X2
AND X3
LD  X4
OR  X5
OR  X6
ANB

Note: Do a quick review of Part 1 if you don't understand the use of ANB... or what the heck, just read a bit further. 

This is where people start to complain. Such a simple construct in Ladder yet in List we are already having to resort to using 2 separate blocks of code joined by ANB�. (the complaints are occasionally followed by rioting in the streets,  looting, setting of fires, etc).

 Since this is in fact a common logic sequence, it's worth letting you in on a little secret. Although you have probably drawn exactly such a diagram in Ladder and would be just as likely to build it that way using relays, as far as the plc is concerned, you've been doing it backwards all along. Huh? Yup. Try putting the OR'd contacts first and see what happens.

 Like this:

 

Now write that in List and you get: 

 

LD  X4

OR  X5

OR  X6

AND X1

AND X2 

AND X3

 

See? No ANB. You just made it a lot more readable. You also made it shorter. It now requires less memory to store the program and you made it execute faster. Even more important, you learned one of the reasons why List might be a good idea. Using Ladder, you tend to think like a human (and that can't be good). If you are using List, you see what the plc sees and you have a better opportunity to write code that is efficient. Before anyone gets upset with me, I will quickly add that the efficiency of code is usually not that critical compared to readability, maintainability and other factors. On the other hand, it's never a bad thing. There are times when efficiency is very important. 


Everyone tends to make this AND before OR mistake. The good old 3-wire start/stop circuit taught in every electrical class is probably to blame. A good controls electrician has this seared into his brain. The series-wired stop buttons always came first followed by the parallel-wired start buttons & holding contacts. But now we are inside the plc.


In a plc, we need to take advantage of Rule #1 rather than being ruled by it. The following new rule helps us do just that. 

Really Smart PLC Rule #2:

If a string of logic contains a set of series contacts and a set of parallel contacts:

 add the series set last if you want the two sets to be in series;

 add the parallel set last if you want the two sets to be in parallel.

Note: This is really just an expansion of rule #1

 

In the previous example, we avoided the ANB by putting the series set last. We had a set of series contacts and a set of parallel contacts and we wanted them in series with each other. Exactly what Rule #2 said to do. If we had wanted them in parallel we would have reversed it like this:

 

ANB/ORB

Sooner or later we will have to resort to ANB/ORB. So let's do some practice with those. We'll minimize their use by keeping our Really Smart PLC Rule #2 in mind. 

First of all, remember that using LD will always begin a new "block" of code (what we called a "series" of statements in Part 1;  "block" is the official, tech term). In effect, using the LD command in the middle of a rung suspends the logic you are working on and temporarily begins a new rung at the left rail. You end up with two blocks; the old unfinished one and a new temporary one. The reason we want to do this is so that when something applies to "all of the preceding logic" it will only be referring to what's in this new block. For now, the old block will be ignored. When you are ready, the new one can be connected to the old by using ANB or ORB. 

Pictures! We need pictures! 

LD  X0 ;start block #1
OR  X1 

produces this:

 



Now let's add another LD statement (to get a new block) followed by OR.  

Altogether we have:   

 

 

 

LD  X0 ;start block #1. 

OR  X1 

LD  X2 ;start block #2. 

OR  X3


Note that both blocks were left "open" (ie. there are no OUT or other output type commands that would produce a connection to the right hand rail).

If  we add an ANB at the end of our code, the two blocks will be placed in series like this:


If we instead use an ORB, we'll parallel them like this:

Using ORB in this example was rather pointless. We could have just OR'd all the

contacts together in the first place and avoided the use of ORB.  

 Here's a better example showing the use of ORB:  

  LD     X0 ;start block #1.
AND  X1
LD     X2 ;start block #2.
AND  X3


 Now add ORB and you'll get: 



Common sense might have told you the last drawing could be coded as: 

 

LD  X0 

AND  X1 

OR  X2 

AND X3 

when in fact, that would have produced this:

 

 

 

  Just remember that common sense will also insist that the world is flat.

So if you're not exactly giving Ptolemy a run for his money, this would be a good time to go back and review (starting with Part 1). Assuming you are happy with the concept of a spherical planet, let's ride forth

 When do you need ANB/ORB?  

 Really Smart PLC Rule #3: 

Use ANB/ORB when you need to apply logic that only operates on some of the preceding logic.  

 

Identify the logic section of interest and then separate it out by surrounding it with LD & ANB/ORB.

 

If you need to do an AND but only want the contact to be in series with some of the preceding logic, you need an ORB.

 

If you need to do an OR but only want the contact to be in parallel with some of the preceding logic, you need an ANB.

Example of AND needing an ORB:

We only want X3 to be in series with some of the preceding logic

 

(ie. in series with  X2, but not X0 or X1). 

Here it is in List: 

LD     X0

AND  X1

 LD     X2 ;marks the start of the "some" stuff.

AND  X3 ;this AND tells us we need an ORB. 

ORB        ;places the X2-X3 block in parallel with the X0-X1 block.

Example of OR needing an ANB:

 

 

 

 

 We only want X4 to be in parallel with some of the preceding logic

 

 

 

(ie. in parallel with X3, but nothing else). 

 

Here it is in List: 

LD    X0 

OR    X1 

LD   X3 ;marks the start of the "some" stuff. 

OR   X4 ;this OR tells us we need an ANB. 

ANB      ;places the X3-X4 block in series with the X0-X1 block. 

AND X2

 

Notice I didn't include the 'AND X2' until after the ANB. I left it until the end as a separate operation. I didn't have to really but Rule #2 says I should. In more complex code, it'll help keep things clearer if you develop this habit. Keep the contents of blocks you'll be joining as short and simple as possible.

 

Okay, our next example is going to get nasty. I can almost guarantee your response will soon be "Holy Cow! This just isn't worth it" (actually, you may have been thinking that for a while now). I'll be the first to admit that learning to write clear, readable code is easier if "Ladder only". So why bother with all of this? Well, once you get used to it, you'll find that List has the following strengths:

 

1)   It's quicker to type than it is to draw (and in Ladder you still have to fill in names and constants anyway).   

2)   Comments, names and constants are clearer and more readable.  

3)   You can see more of your program at one time on the screen and have more control over the layout. 

4)   Printouts are more compact and can be edited in any word processor quite easily. 

5)   More efficient code. Faster execution. Less memory required . 

6)      Complex functions are more readable. 

7)      Women will find you more attractive.

 

None of these will make much of an impression (well, maybe the last one), until you start to use a lot of advanced functions. Let me give you an example. I recently wrote a program to control a rolling tube bender. There was nothing extraordinary about it yet there were sections that contained over fifty math functions in a row. In Ladder, these appeared as endless horizontal lines, each one ending way over on the right-hand side of the screen in a box full of misarranged numbers. In List, it was very clear and obvious what was going on. It looked and read more like proper math. It's also worth pointing out that although the program was over 3000 steps in length, it contained only 15 block joins and a single MPS/MPP pair. That's because it was written in List. You shouldn't judge List by the mess you sometimes see when you auto-convert Ladder into it. 

 

Regardless of the type or level of programming you are doing today, chances are you'll be doing different things tomorrow. Being able to comfortably switch between List and Ladder will allow you to take advantage of the strengths of each.

 

Personally, I write everything in List and use Ladder to double-check sections that don't "feel" right. I get a second perspective from Ladder that can be invaluable. You may end up using the opposite approach or perhaps you'll write Boolean in Ladder and switch to List for math and similar functions. Regardless, if you wish to have List available to you, you need an understanding of its features and rules. Besides, I'll be really ticked if after all the typing I just did, you decide it would be a great time to try out the delete key on your new keyboard. 

 

So, assuming both you and this document still exist

Let's try a complex example.  

First we'll translate the ladder diagram shown below exactly as it's drawn. We'll even do it in the order suggested by the contact numbers (X0, X1, X2, etc).


 

 

 

  Here's the List:

 

 

 

 LD  X0 

AND  X1

LD  X2 

AND  X3 

ORB ; see J1 (joins the X2-X3 block with the X0-X1 block). 

LD  X4 

AND  X5 

LD  X6 

AND  X7 

LD  X10 

OR  X11 

ANB  ; see J2 (joins X10-X11 block with the X6-X7 block). 

ORB  ; see J3 (joins the block created by J2 with the X4-X5 block).  

ANB  ; see J4 (joins the block created by J3 with the one created by J1).   

OUT  Y0   

You'll note that we held off using some of the block commands until the end. We had to in order to join blocks in the correct order. ANB/ORB always operate on the two most recently created blocks. You are allowed to have several blocks outstanding before you have to perform a join. The FX series allows a maximum of eight. Doing it this way, you have to be careful not to join the wrong blocks together. It's also rather confusing.

By re-arranging things, w, , e could have kept most of the block commands "inline" and made things a little easier to read (and less error prone). This is a much better technique.   

 

Like this:

LD  X0

AND  X1

LD  X2

AND  X3

ORB  ; see J1 (joins the X2-X3 block with the X0-X1 block) 

LD  X6 

AND  X7 

LD  X10 

OR  X11 

ANB  ; see J2 (joins X10-X11 block with the X6-X7 block). 

LD  X4 

AND  X5 

ORB  ; see J3 (joins the X4-X5 block with the one created by #J2). 

ANB  ; see J4 (joins the block created by #J1 with the one created by J3). 

OUT  Y0

 

We still have an area that could be improved. Have a close look at X6, X7, X10, & X11 on the drawing. Look familiar? Remember our Really Smart PLC Rule #2? Oh, you already saw that and were just being polite? I'm impressed. The rule tells us that by placing X6 & X7 after X10 & X11 we can eliminate the J2 block command. Very nice.

 

 

Here's the final version (you don't really believe that do you?). 

LD  X0 

AND  X1 

LD  X2 

AND  X3 

ORB  ;see J1 (joins the X2-X3 block with the X0-X1 block). 

LD  X10 

OR  X11 

AND  X6 

AND  X7 ;we no longer need the block join at J2. 

LD  X4 

AND  X5 

ORB  ;see J3 (joins the X4-X5 block with the X10-X7 block).  

ANB  ;see J4 (joins the block created by J1 with the one created by J3). 

OUT  Y0

 

This version will work the same as the other two but they'll each produce different diagrams in your Ladder editor (go ahead, fire up Medoc , GX or whatever and play). 

Notice the blocks joined by ANB both end in ORB and the blocks joined by ORB all end in AND. This tells us we've done a good job (according to the next rule).  

 

Really Smart PLC Rule #4:

Both blocks being joined by ANB should end in OR, ORI  or a block join (ANB/ORB). 

Both blocks being joined by ORB should end in AND, ANI or a block join (ANB/ORB).

 

Notice it says that both of the blocks being joined must qualify. That's a key point. Breaking Rule #4 doesn't make your code illegal. It just means you haven't written it in the best possible way. You might be using a block join when it's not needed. You could even be including an AND that would be better added after the join is completed. The rule is unforgiving. Also note it doesn't recognize LD as a proper block end so you know at least two contacts are needed in each block you are attempting to join. 

If we had followed this rule in the first place, the last version of our example would have appeared automatically without requiring the two revisions. Interestingly enough, Rule #4 even insists that you obey rule #2. Could be a conspiracy.

There is still the issue of that final ANB in our last version. A bit confusing isn't it?  

When quickly scanning the code, you have no idea what that ANB is referring to.

 

Here's a method that is a lot more readable (never believe that "final" version stuff). 

LD  X0
AND  X1
LD  X2
AND  X3
ORB ;combine this block with the previous one.
OUT  M0 ;assign an internal relay to record the result so far.
LD  X4 ;start over fresh.
AND  X5
LD  X10
OR  X11
AND  X6
AND  X7
ORB ;combine this block with the previous one.
AND  M0 ;add in the result from way back.
OUT  Y0

In the real world, you'd give M0 a nice, descriptive name so that when you use it, you'll know exactly what it refers to. You can't give ANB a name at all. It's well worth flipping back to the page with the first version and comparing. There's a pretty dramatic difference isn't there? Which one would you rather work with five years from now when you've forgotten what this machine even looks like?  

 

OUTPUTS  

We haven't yet dealt with outputs in Part 2. It's hard to write a program that does anything without them. It's even harder to use them properly unless you know a few tricks. I'll now take you to the grand heights of advanced output design. Or not

There are three types of output connections that one can make.

I call these Simple, Cascaded and Divergent outputs.

 

So, you're saying to yourself "Oh Gawd. He's making up terms and definitions now. He just wants this to be complicated" (yeah, I heard you). There is a purpose here. Many people, when writing in List, don't even realize that cascaded outputs are legal. Also, if you don't know the difference between cascaded and divergent outputs, you'll often create divergent ones by mistake. And divergent outputs can lead to horrors such as MPS which should be avoided like prison time or processed cheese. 

Simple Outputs 

You have a simple output when you have only one or, if there are several, they are directly connected together. There are no contacts between any of the outputs. Nothing mysterious here.


 

 

 Cascaded Outputs   

You have cascaded outputs when you have more than one output and each uses all of the logic of the preceding output and then extends that logic with more of its own.

 

 

 

  X1 extends the logic of Y0. X2 extends the logic of Y1. Note the extension logic leading to each lower coil from the upper coil connects directly to the upper coil. There are no contacts between that connection point and the upper coil (see arrows).  

The logic leading up to a set of cascading outputs can be built without resorting to anything other than LD/AND/OR, etc and, if needed, ANB/ORB. The extension logic added for each new output is built using only AND/ANI. (once you place even 1 output, you are no longer allowed to use ANB/ORB). In reality, you should be able to also use OR in the extension logic but the ability has been disabled in the plc. For a look at why, see Water Flows Downhill (in the Other Stuff section at the end of this document).

 

Divergent Outputs 

You have divergent outputs when you have more than one output and each uses only some of the logic of the preceding output. Each output may, but is not required to, extend that logic with more of its own (remember this last part, Rule #6 is all about it).  

 

Note that X3 is sitting between the higher coil (Y0) and the connection point leading to a lower coil (Y1). Y1 does not use all of the logic that Y0 does. Y1 totally ignores X3. The output of the X0 contact is what I call a "point of divergence". It's like a fork in the road. The logic splits into 2 different routes. Each half of the fork ends in a coil that is not seen by the other. 

So what? Well picture the plc merrily processing everything in your program up to and including X0 in the normal manner. Then it looks at X3 and outputs Y0. Everything is rosy. Remember, at this point (like all points) none of the preceding logic exists anymore. All we have is the current result in the accumulator. This result includes the effect of X3. Unfortunately, we still have to process the logic leading up to Y1 but that's not supposed to include X3! Basically, we now need the plc to back up a bit (to the point of divergence) and then execute the branch to Y1. Hmmm. Sorry... plc's don't do that.   

 

 

Really Smart PLC Rule #5: 
PLC logic never flows backwards. 
 

 In order to build a set of divergent outputs, you have to use MPS (Memory Point Store) or some other method of saving the value of the accumulator when you come to the place where the multiple output paths separate (the point of divergence). Later, when it's time to execute the second branch, you can recall that value from storage and use it to modify the accumulator. Whenever you see a point of divergence in your code, you know you need to stick an MPS there (or similar). This is the only time MPS is used in a program.

 The Evil MPS   

I'm not going to go into too much detail on MPS since it's all in the manual. If you don't understand it, don't worry about it; use the alternate method described below. Let's just quickly say this: If you write MPS, the plc will store the value of the accumulator at that point in the program. MPS operates on a stack that is 12 storage locations deep (in the FX series). Each time you write MPS (Memory Point Store), you shove the previous values deeper into the stack. You read the topmost value with MRD (Memory Read). This loads the accumulator with the value read. If instead you read the stack using MPP (Memory Point Pop), you load the accumulator with the current value and then bring the next value up to the top. Subsequent uses of MRD will read that "next value". You must completely empty the stack before leaving a rung or you'll generate an error. In other words, for every MPS there must also be a MPP. You can have any number of MRD's.  

 Having said that, you shouldn't use MPS except in very obvious circumstances. All too often, you'll see MRD or MPP used many lines below the MPS. Now you have to search up through the code to figure out what is being referenced. A better method is to assign an internal relay (eg. OUT M0) to that point in the logic instead of using MPS at all. End the rung right there and start over using a contact from the internal relay. You can now give that relay a very descriptive name and refer to it as often as you wish without worrying about matching MPP's with MPS's. Your rungs will be shorter and simpler too.  

 The main reason that MPS exists is for use by the Ladder editing software itself. When you write in Ladder, the editor must convert your code into List because that's what gets sent to the plc. The editor's conversion makes grand use of MPS (especially since unlike you, most people don't know about divergent versus cascaded outputs). It needs a temporary method like MPS because it's not at liberty to use internal relays (they belong to you) and it would do a lousy job of naming them anyway.  

The Point of all of this 

 

Simple outputs are obvious. They'll usually take care of themselves. Cascaded outputs are nice. The code looks good and it executes quickly. Divergents are not really devil spawn but we do want to know when we've made them by mistake. If you start looking, you'll be surprised how many times they could have been written as cascades with just a little bit of effort. Especially when written in Ladder. Which brings us to:  

 Really Smart PLC Rule #6:

If a divergent output does not have logic between itself and the point of divergence, it's an indication that things could have been re-ordered as a cascade.

Proper divergent outputs.

 

 

 

 It codes as: 

 

 

LD X0
MPS
AND  X1
OUT  Y0
MPP
AND  X2
OUT  Y1  

Divergent outputs that should be rewritten as cascaded:


 It codes as:

LD  X0
MPS
AND  X1
OUT  Y0
MPP
OUT  Y1

Note that MPP is followed immediately by OUT.

 

 

 

 

This is an indication that it should be rewritten as:

Same as above but with cascaded outputs.


   

 

 

 

 

It codes as:
LD  X0
OUT  Y1
AND  X1
OUT  Y0

Not only can some divergents be re-written as cascades, simple outputs need looking at too. For instance, when first exposed to List, many people are tempted to write code with repetitive logic such as:

 They wouldn't have done it like that in Ladder and there's no rule that says they have to do it that way in List. We could have accomplished the same result like this:

 

 

 

  You don't have to end a block of code just because you've reached an output.
You CAN keep going! Of course, there are many times when repeating some of the logic (perhaps via an internal relay) will actually be a good idea. It allows you to break things up into sections and separates ideas. Knowing what your options are is the first step towards writing optimal code.

 

 

 

 -  OTHER STUFF -

 Reversing Your Logic or "What I really meant was..."  

Let's say you've just completed a long, involved piece of artwork (a masterpiece of logic) that views things from the perspective of "if all things are on then do something". After looking at it, you realize that although the result is correct, it doesn't explain things in the best possible way. What you really wish you'd written was the same logic but expressed as "if some things are off then don't do anything". Before you start a mind-numbing revision (or worse, start unloading the dishwasher) there is a simple "no thinking required" method for doing it. Which leads us to...  
 

 

Really Smart PLC Rule #7:  
If you invert every contact, logical operation and output in a logic sequence, there will be no change in the operation of the outputs. 

 A full inverse is where you invert both the contact and the operation in one shot.  

It works like this:  
 

LD    & LDI  are the full inverse of each other (we only have a contact). 
AND & ORI  are the full inverse of each other (both a contact and an operation).  
OR    & ANI  are the full inverse of each other (both a contact and an operation).
ANB & ORB are the full inverse of each other (we only have an operation).
OUT & INV OUT are the full inverse of each other (we only have an output).
example: 
LD     X0 ;if x0 is on
AND  X1 ;and x1 is on
OR     X2 ;or x2 is on
OUT  Y0 ;then turn on y0.

is the same as... 

LDI   X0 ;if x0 is off (full inverse of LD)
ORI   X1 ;or x1 is off (full inverse of AND)
ANI   X2 ;and x2 is off (full inverse of OR)
INV         ;then don't
OUT  Y0 ;                 turn on y0.
 

Note the use of INV ("Invert"). It takes the value of the accumulator and inverts it. Some plc's offer a ready-to-go inverted version of OUT (usually called something similar to OUT_NOT) but it's NOT there in the FX series (pun intended). Fortunately, we can mimic it by using INV followed by OUT. Having to use INV may not be as efficient as OUT_NOT but it is very versatile since we can use it for other things anywhere in our code. The bad news is it's NOT available on the FXON & FXOS.
 

As you can see, this type of logic reversal is quite easy to perform in List. If you try the same thing in Ladder, you'll find it's a lot more difficult especially with complex logic. 

 

IF/THEN/ELSE 

If/then/else is a very heavily used feature in almost every computer language ever developed.  

eg. in Pascal one could write this: 

If (Beer = 0) or (Chips = 0) then GetGroceries
Else WatchTV; 

If the first line is true (ie. beer & chips really are equal to 0), the statement following the word "then" will execute but the statement following "Else" will not. If the first line is not true, then only the statement following "Else" will execute.

We can do similar on the plc using INV. In fact, you can quite literally think "else" when using INV in this manner. 

LDI    BEER                       ;if no beer 

ORI   CHIPS                      ;or no chips
OUT  GET_GROCERIES  ;then get groceries
INV                                    ;else
OUT  WATCH_TV            ;      watch TV
As a side note, the above is a good example of cascaded outputs. Nonetheless, I don't recommend using it on your next job application. 

An alternative to using INV here would be to replace it with LDI GET_GROCERIES. I prefer INV as it more closely associates the two possible results together. Instead of a cascade, LDI would start a new rung.

Notice how easy it is to read the code when you put meaningful names in place of the I/O numbers we've been using. It works well. I'll refrain from comments such as "Ladders are for changing light bulbs" if you'll admit List is not as bad as you thought. 

Water Flows Downhill (but Ladder doesn't know that)


I mentioned earlier that you are not allowed to use OR (or ORI) with cascaded outputs. I'll try and explain that here.

Have a look at the following diagram.




If this were wired with real relays in the real world, both Y0 and Y1 would always be on. It doesn't matter whether X0 is on or off; one of the contacts will always power up both coils. There is no point to this circuit but it illustrates the idea. 

This is how you would code it in order to obtain the same behavior:  

LD X0   

 

 

 

 

OUT Y0
OUT Y1

Now check out this code. It's a set of cascaded outputs where the upper output is extended using ORI.


LD  X0
OUT Y0
ORI  X0
OUT Y1 
Under the current rules of engagement, this should convert into the same drawing as we have above but its operation is very different from the relay version.

Remember that once something is executed, the plc forgets about it. All it keeps is the current result in the accumulator. If X0 is on, it will turn on Y0. After that, in line 3 of the List, we are in effect saying "if the accumulator is on OR if X0 is off then turn on Y1. No matter what it decides to do about Y1, it will never go back and change Y0. Y0 has been handled and forgotten about. Y0 will only go on if X0 is on. Y1 will go on no matter what. Guess what? Kaboom! One major pitfall for someone translating a relay diagram into a plc program. Rather, I should say, it's only a pitfall for someone who thinks that just because both versions will convert in their head to the same ladder diagram, he can use either version of List to represent the relays. However, if you let your editor auto-convert this List into Ladder, it will either "correct" it for you (Medoc Dos) or get very confused (GX Developer). 

Medoc will change the cascaded outputs into simple ones as in the first example. 

LD X0 
ORI X0
OUT Y0
OUT Y1 

This should convert back again into the same drawing as we have above (it does).
 

Written this way, Y0 & Y1 will operate the same as the real relays. But it has a different meaning than what we told it we wanted. Personally, I think it's unforgivable that Medoc has the audacity to change this code without so much as a warning. GX is not much better. It refuses to convert it but doesn't tell you why or what the problem is. Just sort of hangs there in limbo. Not exactly good behavior. 
 

If you send the cascaded version to the plc without converting it to Ladder, it will generate an error that makes no sense ("Number of LD/LDI instructions is more than ANB/ORB instructions"). It really should operate the way we described above (the Kaboom method). It is correct and might even be a useful bit of logic for you. On the other hand it could be quite the opposite of what you (or the next guy to read your code) were expecting. Worse, viewing it in Ladder will either cause changes that may become permanent or, make you look unprofessional when it fails to convert. Mitsubishi simply made it an illegal combination without fully dealing with the situation. In any event, it's good to be aware of the issue. It also illustrates something I've been gently hinting at for some time:

 PLC logic never flows backwards. Did I mention that? 

 

 

 

 

While we're on the subject, take note that if you had a different situation and needed to use an ANI instead of the ORI in the cascaded version, you'd avoid all of the problems. The Ladder editors would be happy and all will work exactly like everyone expects. Y1 would never go on in this particular example but you get the point. 
 

This whole cascaded OR thing is not really the fault of List, the plc or even the Ladder language. The problem lies with the Ladder editing software. Current editors have no way to draw it that isn't misleading. They could easily have used a downward pointing arrow (or a diode) instead of a solid vertical line. Until they figure this out and make cascaded OR's legal, you have no choice in the matter. You can't use them. Not something you'll miss anyway.
 

The moral of this is that it's worth having a plc in the shop for testing purposes. If you don't have access to one, before heading out to a client's site, at least attempt a conversion in GX before deciding that everything is hunky-dory. Medoc users have no recourse other than caution.

 

Related Articles More about Articles