5/05 FFL Question

grover1

Member
Join Date
Nov 2003
Location
Walnut Creek, CA
Posts
54
Greetings,

I am writing some code for a 5/05 project, but I do not have a 5/05 to play with to answer my own question meself. Can the FFL be truly used as a stack? I have a process with 15 or so states and approximately 15 or so events that cause the process to change states. I thought it would be neat to track state changes by storing them in a FIFO stack. The stack would serve only as a state history file, meaning if I ever had process problems, a check of the FIFO would show the last 20 or so states. Since I can't play with a real SLC, I'm not confident of my understanding.

I plan to keep the "SOURCE"(N7:2), "FIFO"(N35:0)and CONTROL"(R6:0) addresses constant and set the "LENGTH" to 20 elements. Each time a process state change occurs, another rung would update N7:2 with the new state value and toggle the FIFO rung false-to-true. What I am not sure about is whether the newest value is always loaded into the same FIFO address or if it is loaded into the next sequential FIFO address. I hope it is the former, meaning N35:0 is always the newest state and N35:19 is always the oldest state.

The HELP file states that "POSITION" is the next available location where the instruction loads data into the stack and that is what I am confused about. It makes it sound as if the latter was true, meaning I would have to know the current FIFO position in order to determine which N35 location has the newest state. I can see advantages to both, but prefer the former.

Any clarification would be appreciated.

Grover
 
Another way?

You can accomplish the same thing another way. When ever a state change occurs, move the values in registers, 1 to19, to registers 2 to 20, then store the latest value in register 1. See attached:

INDEX_STK.png
 
Ken's method is simpler. It will serve you better than the FIFO pair. The FIFO pair is more useful if you need all the extra control bits that go with it. But here's how the instruction operates if you're still curious:

Usually you would program a FFU first, conditioned by the DN bit and use the same control address for the FFL (r6:0).

I usually put the FFL on a branch directly below the FFU.
The first time you run it, the stack will be empty. R6:0.POS = 0. When the triggering logic goes true, the FFL will load the next available position: N35:0 and increment R6:0.POS.

ON the next trigger, it will load N35:[R6:0.POS].

When the POS equals the LENgth, the DN bit will be set.

On the next state change, the FFU branch conditioned by this DoNe bit will be true and it will unload N35:0 to the Unload destination, and move the data down one element from N35:[R6:0.LEN] to N35:0. Then the FFL will load the new data in N35:19 (if length is 20).

The most recent state will be N35:[R6:0.POS]. Once the stack gets full, R6:0.POS will always be equal to R6:0.LEN

Every time I have used FFU/FFL, i have to set up a test to get this all straight in my head first. I think I'll start using Ken's method exclusively.

Paul C
 
Ken,

Thanks very much for your suggestion, I will definitely put it to use in my program. It's funny, I've occasionally evaluated shift registers in packaging machines that employ similar logic and it never occurred to me to apply to this situation. I also noticed that the MOV instruction in which N7:2 is placed into N35:0 is on the same rung in a separate branch. Very simple, elegant and effective. I LIKE IT.

Does the following statement true for all ladder rungs having multiple output branches?
Instructions contained in true output branches of a single rung will be executed in top branch to bottom branch order.
I've seen it done all the time, but have been reluctant to do on my own unless I've seen it work. I definitely need to get a SLC or ML on my desk. I don't machine time for experimenting.

Again, thanks Ken, for sharing.

Paul,

I appreciate your taking the time to explain FFL-FFU. I think if I had the need to unload the data as well, I might try using that instruction. I completely agree with you that Ken's idea is a good one.

What a great forum.

Grover
 
oops! ...

my distinguished colleague Ken Moore has given you a good idea ... but there is a slight flaw in the example he posted ...

historystack.JPG


see if this arrangement works better ...

basic idea: you have to move from the HIGHER addresses to the LOWER addresses ... now if you decide that this "backwards" ordering is too confusing (maybe for others who come along behind you) then we can use another arrangement ... it's slightly less elegant ... and it uses more memory ... but it seems to make more sense to most people ...

stack.JPG
 
Last edited:
Ken, I dont think that is going to work.

I programmed a COPy as shown using the free running clock as a trigger and number source and got the following.

alaric203000.JPG


The COP instruction works from the front of the file towards the back. The value in N11:0 goes to N11:1, then N11:1, which has a new value, goes to N11:2, then N11:2 goes to N11:3. This method will result in a stack that is filled with the same number.

A quick way around this is to use two COPy operations; First to a scratch area then back to the stack.

alaric203001.JPG
 
Personally, I would use the method Ken Moore and Ron Beaufort show. But that is largely personal opinion and preference.


The conceptual function you are looking at is a LIFO ('LFL'- last in first out). The thing I don't know and can't test is whether the SLC treats data storage for a LIFO different than a FIFO or if it just uses the position value differently. With a FIFO the newest value will be at the end of the stack. Conceptually, a LIFO should have the opposite storage, that is the newest value at the top of the stack. This way the lowest stack location is alway unloaded.

Sorry I can't be more help, but the LFL/LFU instruction pair does exist in the SLC.

Keith
 
A FIFO will give you an upside down stack. It works like this:

alaric203002.JPG


This example also used the free running clock as both a trigger and a number generator.

Once the stack is full what you end up with is an upside down stack. The most recent data is pointed to by R6:0.POS and the oldest data is at N35:0. As you can see the smaller time values (oldest data) are at lower addresses while the more recent time values (newest) are at the top of the queue. The problem is that until the queue is full the position of the newest data is not at the end of the queue but at some point in between.

To make it work like a truly inverted stack you can preset R6:0.POS to point to the end of the queue. Then what you end up with is this:

alaric203003.JPG



And a moment later, the queue looks like this.

alaric203004.JPG


Once the stack is full the oldest data will drop off from the lowest postion N35:0 and everything will shift down.

(note, it may not be necessary to program a first scan set of R6:0.pos - I put it in for clarity. Just pre-set the value before you download the program and as long as R6:0 is never RESet then you should be good to go.)
 
Greetings Grover,



going a little bit further ...



you asked:



Does the following statement true for all ladder rungs having multiple output branches?


Instructions contained in true output branches of a single rung will be executed in top branch to bottom branch order.




the simple answer is “yes” ... but the fact that you asked the question means that you don’t fully understand the significance of this next little trick ...



let’s set the stage by asking this question ...



stack2.JPG





now for the answer ...



suppose that you have a rung in the “Edit” mode ... then suppose that you double-click on the rung number ... a new window with text in it will pop up ... you can edit the text to edit the rung ...



stack3.JPG





and ... (drum roll from orchestra) ... the ORDER of the instructions in that text will tell you EXACTLY/PRECISELY/UNERRINGLY which instruction on the rung the processor will execute first, second, third, and so on ... secret handshake: this text DEFINES the processor’s scan order ... golden nugget of truth: the PLC processor does NOT see rungs and branches ... what he REALLY sees is this ASCII text ...



and so ...



stack4.JPG





let’s see ... COP ... COP ... MOV ... yep, the MOV gets done last regardless of the “hanging/dangling” branch arrangement ... the story is all right there for anyone who wants to know the exact scan order of ANY rung ... regardless of how complicated said rung might appear ...



finally ... we’re all being a little bit “loose” with our definitions here ... it might help to use the correct terminology ...



suppose that we put things (such as shoeboxes) into a “stack” ... then the LAST one put IN the stack is the FIRST one taken OUT ... the term “LIFO” describes this “stack” type of arrangement ...



on the other hand ...



suppose that we put things (such as people waiting for a cafeteria to open) into a “queue” ... then the FIRST one put IN the line is the FIRST one taken OUT of the line ... the term “FIFO” describes this “queue” type of arrangement ...



(our British friends commonly use the word “queue” to describe an orderly lineup of people waiting for something ... it’s pronounced just like the letter “Q”) ...



sometimes just having a clear-cut way of expressing what we’re trying to program is a big step in the right direction ...



PS Edit ... I see that my distinguished colleague Alaric is on much the same wave length in describing the technical differences between "stacks" and "queues" ...
 
Too quick, without thinking

I wasn't thinking correctly this morning, I usually use the logic I posted for a running average routine, and I copy from high to low, so it works. I inverted the addressing this morning, without thinking it through.

Thanks to everyone for setting it straight.
 
Ron,

Your clarification as to how RSLogix parses rung instructions was quite helpful. I can immediately apply this newfound knowledge and simplify a few of my rungs. I appreciate the time you took to graphically explain it. I'm sure other readers were able to benefit from it as well.

Alaric and Ken, thanks for pointing out the problem with Ken's initial COP suggestion. I went back and re-examined one of our packaging machine shift registers and sure enough they first copied the data to a temporary file and then back to the original file (plus one element of course).

I'm not sure if which method I will use, but I am confident that either method will work.

As we used to say in the Navy, Bravo-Zulu (well done) guys!

Grover
 

Similar Topics

When executing a FFU to unload the oldest value the data in the file is shifted down and the position value is changed. Does this shifting take...
Replies
12
Views
3,380
I have a project that is loading pallets into 10 test bays and then unloading them when the test is complete. I am using an array to store which...
Replies
3
Views
170
EDIT: I suppose i should mention, RSLogix 500 V8.40, SLC 5/04 (1747-L542C) Is there is a way to use the FFL instruction in a way that doesn't...
Replies
4
Views
862
So once again i am trying to create a program in unity pro from an Ab program. i have an FFL and FFU in rslogix 500 and need to use something like...
Replies
2
Views
2,213
Hello everyone. Quick Newbie FFL question. As far as I understand from YouTube etc. FFL should be energized by True condition from the left...
Replies
5
Views
1,801
Back
Top Bottom