Subroutines and latching

mrowen

Member
Join Date
Dec 2003
Posts
28
Okay, Have been screwing with this for hours now. I am using RS500 to program a micrologix1000 16bwa. For the simple situation of having an output latch it self by providing a set of NO contacts (from same coil) in parallel to the coil. If it comes on it will latch itself.
Now if I do this in a main program, no problem. If I do it in a simple little subroutine, no problem. But when I do it in my real program, it fails to latch itself. If one of the other parrallel contacts breaks, it shuts off the output.

Now I have no doubt that this is my fault but I have looked and looked and looked to no avail for the problem. I am thinking that I simply am not FULLY understanding the scan procedure as it relates to subroutines.

Can anyone shed some much needed light on this.
 
The same logic should work fine in a subroutine so long as it is actually being called. Make sure you have a JSR for that routine, and that it is active. (If it is not active, outputs are effectively left in their last state).

Your problem might be that you are "double-coiling". Is that same output instruction used elsewhere in your code?

In any event, what is the actual code that you are using to seal-in or latch (note that these are different) your output?

Marc
 
I have the subroutine latched active. As for double coiling, I'm not sure exactly what you mean. I think I am allowed to have two separate logic Rungs feed the same output. As long as either or both rungs are true, that output would be True. Please correct me if I am wrong and not following what you are saying.

In anyevent, it is not currently double coiled except for showing up in two separate subroutines. In this case, the other rountine is disabled.

I think I may be screwing up with the XIC, XIO objects. I deleted some of the rung and simply reentered it again. It worked correctly. I think I may be messing up with the XIC/XIO found under the "USER" tab versus the ones found under the "BIT" tab.

Could someone explain the difference. I am guessing the User ones are meant strickly for hardwired inputs and the Bit ones are for interal control bits. Am I even close here?
 
Not even close.

As long as either or both rungs are true, that output would be True. Please correct me if I am wrong and not following what you are saying.

If you are talking about Latch instructions (OTL), then you are correct. Of couse, the same is true for unlatches. If you have multiple unlatches, then if either one is true, the bit will get unlatched. If you mix multiple Latches and Unlatches, each with different truths, well then, heaven help you. This will be almost impossible to debug. I know. I'm trying to fix just such a program today. Major rewrite time.

If you are talking about coils (OTE), then you are dead wrong. Whenever a coil instruction is scanned, the address referenced there gets updated as TRUE or FALSE at that moment. If you have several coils with the same address in a program ("double coiling"), and they evaluate differently, then the address (internal (e.g., B3/0) or external (O:1/0) will have the value for whichever coil was last scanned. Since external (output) addresses don't get proceessed until the end of logic scan, whichever coil is scanned last will be the one that controlles the real-world device.



Could someone explain the difference. I am guessing the User ones are meant strickly for hardwired inputs and the Bit ones are for interal control bits. Am I even close here?

An XIO is an XIO is an XIO. It doesn't matter which menu you pulled it off of, or whether you copied it, or typed it in yourself.

Little known tip: The reason that tab is called USER is that you, the user, can configure just which instructions you want on that tab. I always remove the ABL and ABS instruction, and add OSR, EQU, MOV and TON. This is done via the menu View | Toolbars... and selecting the Instructions menu and pressing the Customize button.

This way I never have to leave the User tab. If I need a NEQ or GRT instead of the EQU, I just drag the EQU down, and then select the text EQU on the block, type in NEQ, and I'm off. It helps that I know all the 3 letter codes for all the instructions.



sry double post

You can delete any reply. Click on the Edit icon below your post, check the Delete? box at the top left of the window, and press the Delete Now button at the top right.

You only have a one hour window to do this though.
 
Last edited:
Double coiling is when you have the same output specified on multiple rungs within your program. It is legal in the AB world, but can really make troubleshooting difficult. I always advise against it. The simple explanation (which is not 100% true) is that the "last rung wins". If I understand your question correctly, it is certainly not an "either/or".

As far as the XIC and XIO instructions go - XIC and XIO are the same whether you type them, select from USER toolbar tab, or from BIT toolbar tab. The USER toolbar tab, is kind of like a frequently used list that you can customize.

Again, if you post your code, someone here will likely help you resolve the unexpected behavior that you are seeing.

Marc


Shucks! Allen beat me to it. His comments about OTL/OTU are worth listening to. My comments are largely echoing his OTE comments.
 
Last edited:
I think I am allowed to have two separate logic Rungs feed the same output. As long as either or both rungs are true, that output would be True.

Not true. The output will be set to the result of the rung that is scanned last.

As far as the xic and xio icons in the user and bit areas, they're the same.

Darn, everybody beat me to it!
 
Okay, good to be low/dumb man on the totem pole "AGAIN".

So I think I have learned something today. At a minimum, I can now delete my post within one hour. LOL.

Seriously, the double coil and last in line thing is a biggy. Thank you guys. Now, is it completely okay to double coil across subroutines that can only run one at a time. Meaning, if one subroutine is running, the other is automatically disabled.
 
Is OK OK?

Now, is it completely okay to double coil across subroutines that can only run one at a time.

Define "OK".

Can it be done? Yes. The PLC code will compile, and the PLC will execute it without crashing.

Is it good programming practice? No. Because you now have to keep track (mentally, while debugging) of not only what the last state of the bit is, but the last state of the conditions that enable/disable the supposedly mutually-exclusive JSR calls.

Are the subroutines mutually exclusive (one JRS rung using an XIC and the other an XIO of the same bit, and nothing else?). Or can they both be enabled, even for one scan? Can they both be disabled at the same time, even for one scan?

Have you fully documented what you are trying to accomplish (lots of rung comments, both in the JSR rungs and in the two coil rungs), so that someone (like you, in 2 months, after you've had a Christmas break to forget about things) can figure out what is going on?

It's really, REALLY, REALLY not a good idea. Find some other way. Control two seperate internal bits in each subroutine, and have them drive the output in the main routine. This gives you control of the output. The way you are doing it, you don't have control.
 
Herrrreeeee's Duuuummmmmy!!!!!!!

Okay, perhaps I am stuck in the old days of programming fortran and C programs.

Here's basically what I got. A simple manual switch that can be turned on, and then turned off at any time.
My main file, has this switch. 2 things have to happen when the switch in turned on.
First, we have a controlled start up of some process just to get things going smoothly. Once start up is successful, we then have to go to a normal run mode. At anytime the switch can be turned off which must trigger a shut down mode.

My thinking, three modes, three subroutines. Each routine controls the same set of I/O but just makes things work a little differently each time.

on my main file, I monitor the switch. When it goes true, that sets the start routine Only. At the end of the start routine, I have two parrallel coils (OTU and OTL). One disables(OTU) the routine at the main and the other(OTL) enables the next rountine at the main. Now we go to routine 2.

Routine one can not be enabled. Routine three is enabled only from the main and in the same line disables the second routine, regardless of where it is.

My first action in this routine is to set my outputs in a desired position immediately using direct wire one shot within the routine. Then I proceed to shut the system down. The last rung disables this routine.

So, my main file is extremely simple. A switch being monitored for Off/on OR On/off transitions. Then one subroutine and only one subroutine can be active at any time. It seemed to be to be an extremely efficient way to look at the code and trouble shoot if needed. Simply look at the main, see which sub is running, pull up that sub and don't worry about anything else.

Now if I understand what you are suggesting, you would have me equate each output (and input?) to an internal variable on the main. Then let each routine do exactly the same thing but go through the main to do it. I don't see any advantage to this. Am I missing something.
 
Last edited:
You're not a dummy.

Like others have said before, I really wish you'd post your code. It would make this process much easier. Don't worry about intellectual property. I guarentee that there's nothing that you have that I haven't seen before (and without a P&ID or mechanical drawing, there's only so much the ladder logic will tell you about how the machine works).

I see what you are trying to do, and the approach is reasonable. Let me ask you, though. If the design is so sound, why are you having trouble figuring out what's wrong?

This line is curious:
The last rung disables this routine.

So this routine is active for only one scan, is that right? When this routine is disabled, do you have ANY routines running, or is this routine re-enable in the next scan by the same conditions in the logic that latched in the bit that called it in the first place?



Looking back at your first post, you have something like the following code in one subroutines:

A B OUT
---| |---+---|/|----( )
|
OUT |
---| |---+



IF the subroutine is being scanned at all, and
IF no other subroutine which uses that bit is being scanned, and,
IF either OUT was ON before the subroutine was called, or condition(s) "A" is/are true.
IF condition(s) "B" are not happening (at least during the part of the scan that the rung is being evaluated),

THEN, yes, the OUT bit should "latch" (I prefer the term "seal itself in" to avoid confusion with the OTL instruction.)

But without more info, I can't say.
 
mrowen:

I would advise you to follow Allen's suggestion. Here's what I might do for something like you describe for your main program:

Switch Shutdown Startup
---| |---------|\|-----------+----|\|---+------------+
In Progress | Done | JSR |
| | |
| | Startup |
| +------------+
|
|
| Startup
+----| |---+------------+
| Done | JSR |
| | |
| | Run |
| +------------+
|
|
| Startup
+----------------( )----
Done

Switch
-+----|\|----+--------------+----------+------------+
| | | | JSR |
| | | | |
| Shutdown | | | Shutdown|
+----| |----+ | +------------+
In Progress |
| Shutdown Shutdown
+---|\|----------( )----
Done In Progress


And for outputs, something like:

Switch Internal Startup Output 1
-+-| |-------| |-------|\|--+---------------( )-----
| Bit From 3 Done |
| |
| |
|Switch Internal Startup|
+-| |-------| |-------| |--+
| Bit From 4 Done |
| |
| |
|Switch Internal |
+-|\|-------| |------------+
Bit From 5



There are a lot of ways to do what you want - this is just a quick thought on my part. You may want to further condition the routines based on additional startup conditions. Double coiling (while legal) opens up a host of problems, so I always recommend against it.

Again, post your code and someone will likely be able to help you out.

Hope that helps,

Marc


Darn it Allen - That's twice you beat me to the punch. I'm going to have to learn to type faster . . .
 
I guess what might be happening here is my I/O is small enough to manage like this. Where I originally got into trouble was running the outputs in the main and running them directly inside subs. I fully see my failures on that one thanks to a little insight from you guys. Once I moved everything inside mutually exclusive subs, all is well and I really like the structure of the whole thing.

msinclair:
I think that is pretty much what I got except for actually placing the outputs in the main. Seems to complicate it. Now I would have a maze of Subroutine contacts leading to each output. Then if I wanted to see what was wrong with the output, I'd have to follow this maze on the main, and then go into a sub. Still not clear on why I would want to do this.

Okay, gonna try and post. What you have is a main, file 6,7,8. Oh, yeah, that'll probably be my next question. The file structure. But one thing at a time.

File 6 is startup, 7 is normal run, and 8 is an incomplete shutdown sequence. Number 8 is not complete and doesn't stop or return.
 
I have looked at this program for an hour or so now and I dont see why you need the subroutines. The whole program as is uses 3 inputs and 4 outputs, 2 of these are used in alarms not for the run of the system.

It looks like O:0/1 Powerselect and O:0/2 Direction are the only 2 outputs being controlled. In the start and run subroutines they are enabled at same time by same conditions.

I have no idea what this controls but from what I see all this could be done in LAD2 with about half or less of the rungs used now.

I hate searching for an UNLATCH when it doesnt follow the LATCH, this makes their use so confusing, especially when used many times.

I also dont understand the concept..why have a start routine that stops and then have to start the run routine?
 
Well....



...I've looked at your code......



...........I see why you've been having such trouble....


Since it's not a very big program, I'm going to post it here as a picture so that anyone without RSLogix can follow it.

[attachment]

Soooooo...... where to begin? The first rung, I guess:

1. Generally, when internal bits are used, most programmers use bits in B3, not R6.EN. That's not to say that you can't, it just that it usually isn't done. R6 is called a "Control" file because there are certain instructions that need some memory for internal bookkeeping, and use R6 elements for it. Each R6 'element' is 3 words (=48 bits) long. You are using one bit out of the 48. This may be considered wasteful (not that you don't have lots of memory to play with).

2. A cross-reference reveals that R6:3.EN is latched on the very first rung, but never unlatched. I'm surprised that it is currently reset. Either you are doing that by hand, or this is a stripped-down version of the code.

3. You need to give some annotation to R6:6.EN. Since it's directly driven by I:0/0, you could call it "ON_SWITCH IS ACTIVE". Or you could replace it with I:0/0 everywhere you use it in the code.

Subroutine 6

4. You have latched R6:5.EN when the ON_SWITCH is set, and don't reset it until either a) the switch is reset, or b) the startup sequence timer is done. All well and good. But you have serveral problems with how you've coded it.
-- A. The Startup timer, once done, has no way to reset. It should reset if R6:5.EN is not enabled, but that is the very bit that calls the subroutine in the first place. Since the timer is not being scanned after you leave startup mode, the next time that you go into startup, the timer will ALREADY BE DONE, and so you'll leave startup mode as soon as you start.
-- B. You run the startup timer while switch_1 is not true. What happens if it becomes true (and stays true?) before the timer times out? You'll stay in startup mode, waiting for switch_1 to drop out.
Since you don't leave startup mode until that switch is true, I assume that being true is a desirable state. Without a P&ID or equivalent, I can't tell if this is a problem or not. But it bothers me.


Subroutine 7.

I can't tell just what you are trying to accomplish here, but I have my doubts that this routine works at all.

You start this routine with Switch_1 made (Rung 6:3 sets the bit that enables the JSR). Therefore R6:1.EN gets set (but won't seal, because the outputs are still on from the Startup Subroutine). i will seal on the second scan of this routine, though (see below), so that's probably good enough. Maybe. This could be another bit that remains true regardless of conditions. It get's set when first scanned, and will never be scanned when the conditions are false.

Rung 1 doesn't do anything, since the bit isn't used anywhere else in the program.

Rung 2 waits for Switch_1 to drop out. The problem is that on rung 3, all the conditions that drive the two outputs will be false (the timer will not be true, and switch_1 won't be true). So the outputs turn off, which may mean that switch_1 will never be untrue, unless the outputs were fighting nature in order to make it true.

Subroutine 8.

An unconditioned OSR will fire the first time it is scanned, and then never again until the PLC is put in program mode. Fortunately, you could delete that rung and all places where you use R6:7.EN and it wouldn't affect your code one bit.



I hope you take all of the above in the spirit of constructive criticism, and not an attack on your programming technique. You are new at programming these things, and it takes time to master them.

plc code.gif
 

Similar Topics

I have been asked to extensively modify a piece of machinery that is very mission critical to the operation, thus not allowed much downtime or...
Replies
4
Views
2,274
We have an application where we need to indicate a piece of machinery needs maintenance. I have created a routine which resets a value of "days...
Replies
12
Views
3,704
Hi all. Please see attached. Tried to google the error with absolutely no results. I did the same at payed version and real PLC so I'm almost...
Replies
7
Views
2,332
hello all is there a rule of thumb as to using or not using subroutines when writing a program ? i am using an Allen Bradley slc 500 thank you...
Replies
5
Views
1,725
All, Using RSLogix 5000. I was wondering if there is a way to quickly check to see if all subroutines are being called by the Main Routine (in...
Replies
3
Views
1,589
Back
Top Bottom