Question about FIFO instructions

dcooper33

Lifetime Supporting Member + Moderator
Join Date
Jun 2011
Location
Rogers, AR
Posts
717
Hi all,

I have a question about using FIFO instructions. I'm wanting to time/date stamp "on change" events for certain settings that are changed on PV+ 1500 that communicates via DH+ to a PLC 5/40e. I had considered using enter tags on the numeric input buttons to trigger alarms on the HMI, and using a separate alarm list object to display the settings changes. The problem is losing the data when power is lost to PV+, or for plant shutdowns, outages, etc. The alternative is to tag the data in the PLC using system time stamps with dedicated FIFO tables for year, month, day, etc.

My question is can I create string tags to display the message data that I want and then load the strings into another FIFO table that loads and indexes with the time/date info? Or do I have to use AEX instructions to move the string data?

Cheers,
Bmac

🍻
 
I don't understand what advantage there would be in using a FIFO.
This instruction is helpful in applications where it is necessary to load and unload values in the same order. An example might be tracking parts through an assembly line where parts are represented by values that have a part number and assembly code.
Will you always be able to view and use your Time/Date Stamp Data in the same order that it was entered? If not, a FIFO would be difficult to use.

It seems that a simple PLC 2-dimensional data word array would be easier to use, and could store both Event and Date of Event. Then you can use indirect addressing to look at a list of Dates and Events.
 
I don't understand what advantage there would be in using a FIFO.
Will you always be able to view and use your Time/Date Stamp Data in the same order that it was entered? If not, a FIFO would be difficult to use.

I could build a table in the PV+ where each line monitors a different set of integers, i.e. the 1st line reads N7:10, 20, 30, 40, 50; the 2nd reads N7:11, 21, 31, 41, 51; and so on. I would need a FIFO of length 10 for each time variable which would index each time an enter tag is activated, and dump out the back end. The display would be able to monitor 10 events at a time, with the newest being first. I would use the FFL /DN bits to unload the tables. I just don't know if I can do the string tags the same way.

There are easier ways to do this I'm sure, I'm just not very experienced at all with indexed addressing and data arrays.
I'm always open to suggestions, though! ;)

Thanks,
Bmac

🍻
 
How about using COP and FLL. If you use N7:0 thru N7:10 then FLL N7:10 with your information and COP N7:1 to N7:0 for Lenth of 10. This would shift everything up one position. Then the next time your FLL would overwrite N7:10 and your COP would overwrite 0-9. Your Last 10 entries would be in N7:0 thru N7:9 and N7:0 would be your First in and First out and N7:10 would be you Display Register.
 
The display would be able to monitor 10 events at a time, with the newest being first.
What will be the use of these 10 Event Data? Will someone say "Show me the last 10 events, ALL AT ONCE?" If so, then your FIFO has to step through and unload each one.

A Data Table Array would allow viewing, moving, or replacing all 10 events in parallel, not in the series constraint of a FIFO. If you can handle FIFO, then indexed addressing should be easy.
 
Well I think I will look more into Copy and Fill instructions.

Besides the AB instruction set reference, can you guys recommend any good reading material on data arrays? Feel like I'm missing some basic info here.
My wife would call that a chronic condition...

Thanks guys,
Bmac
🍻
 
Data Arrays are not covered very well in the PLC literature. You can find basic information in a good college math textbook. Look in your local library for math books.

If you were using a newer PLC and software, you could use some other logic instuctions. For the PLC5, you are most likely limited to using indirect or indexed addressing. Using one of those methods, you can set up a 2-dimensional data array in memory to store your information.

You do have a few instructions in the PLC5 software RSLogix5 for handling word data. Look at these for possible clues about how to store and retrive your data: AVE, COP, FAL, FLL, FSC, and SRT.

The traditional method to find and retrieve data from a memory array is using a FOR-NEXT loop, or a DO WHILE loop. The RSLogix5 software does have the FOR, NXT, and BRK instructions that can be used to retrieve data. For a 2-dimensional data array D(x,y), use two nested (one inside the other) For-Next loops to retrieve data from any location of D(x,y).
 
Last edited:
Attempts at a Timestamp Array

Hi all,

I've played around with this for a little while, trying to write a program that keeps track of the timestamp for the 10 most recent events of an HMI enter tag. I tried using a several FIFO tables, indirect addressing with an incremented counter value, and then just a simple, cumbersome series of MOV's approach.
The MOV approach was the only one that I could get to do exactly what I wanted, but I hate to use that many rungs and that many instructions to do something that is relatively trivial.

I also tried using COP and FLL instructions as cwal61 suggested but couldn't get that to work very well.

I'm posting three short attempts at this in RSLogix 500.
I'd appreciate any advice from anyone that has a chance to look at them.

Cheers,
Dustin

🍻
 
Rather than a FIFO, I would use a circular queue and never clear it out. It will always be able to show the most recent ten events...looking at the timestamp will inform the operator of the relevance.

The FFL/FFU pair are good choices when you need to vary the length of the stack, but you don't need that...yours will always be ten positions (until they ask for 100).

A circular queue is just a pointer that goes from 0-9 and back again. Whatever value it holds will be the most recent item in the list. When a new event happens, increment the pointer, if greater than 9, clear it (wraparound), and use indirect addressing to stuff all the values into your files:

N50:[x] "Month"
N51:[x] "Day"
N52:[x] "Hour"
N52:[x] "Minute'
N53:[x] "Second"
N54:[x] "Fault Code"
N55:[x] "Fault Data"

Where x is a pointer that identifies the index of the most recent event.

Then for strings, if you must do them in the PLC, then you would have a ST file with all the strings in it, so you fault code text could be ST56:[N54:[x]]

If you need to control the display order by logic in the PLC, then you can use a FIFO based on the COP instruction. This means that you have to shift all your files, so you need a COP instruction for each one.

Also, note that if you copy in the upward direction, you will need some interim storage location. If you COP N7:0 to N7:1 with a length of 10, the A/B PLC will put the value from N7:0 into all the locations, because it does them consecutively. If you COP N7:1 to N7:0, then you will shift all the values down one position, and then put the newest data into N7:9 without the need for an interim storage location.

I would recommend avoiding ST files in the PLC since communicating them to the PV is up to 40 times more work for the system than an integer which can point to a multi-state display object holding your texts.

Hope this helps, I have to run before I've had time to look at your examples.
 
Last edited:
Rather than a FIFO, I would use a circular queue and never clear it out. It will always be able to show the most recent ten events...looking at the timestamp will inform the operator of the relevance.

The FFL/FFU pair are good choices when you need to vary the length of the stack, but you don't need that...yours will always be ten positions (until they ask for 100).

A circular queue is just a pointer that goes from 0-9 and back again. Whatever value it holds will be the most recent item in the list. When a new event happens, increment the pointer, if greater than 9, clear it (wraparound), and use indirect addressing to stuff all the values into your files:

N50:[x] "Month"
N51:[x] "Day"
N52:[x] "Hour"
N52:[x] "Minute'
N53:[x] "Second"
N54:[x] "Fault Code"
N55:[x] "Fault Data"

Where x is a pointer that identifies the index of the most recent event.

Then for strings, if you must do them in the PLC, then you would have a ST file with all the strings in it, so you fault code text could be ST56:[N54:[x]]

If you need to control the display order by logic in the PLC, then you can use a FIFO based on the COP instruction. This means that you have to shift all your files, so you need a COP instruction for each one.

Also, note that if you copy in the upward direction, you will need some interim storage location. If you COP N7:0 to N7:1 with a length of 10, the A/B PLC will put the value from N7:0 into all the locations, because it does them consecutively. If you COP N7:1 to N7:0, then you will shift all the values down one position, and then put the newest data into N7:9 without the need for an interim storage location.

I would recommend avoiding ST files in the PLC since communicating them to the PV is up to 40 times more work for the system than an integer which can point to a multi-state display object holding your texts.

Hope this helps, I have to run before I've had time to look at your examples.

Thanks for the good info there.

I realized the problem I was having with trying to use the COP instruction to shift the data was that I wasn't putting the "#" indicator on the source address, so it was just copying the same data across the array, rather than shifting it. This method accomplishes the same thing as the third method I posted above, but it's a lot cleaner. Of course, it does display the chronological order of events horizontally in the PLC data table, rather than vertically, but that's not really a problem, since the HMI is the only place you'd really be looking at the data.

The problem with using a pointer is that they want a list-type display on the HMI that will show the 10 most recent events in order, so with a wrap-around pointer, once you got over 10 events, the log wouldn't shift, just write over the events at the beginning of the list.

I could just go ahead and add a string array that would load and shift the same way as the timestamp data, unless there's a way that the texts can be stored on the PV+, and loaded into the display table with the appropriate event (and still be retained in event of power loss). o_O

Could you elaborate a little on how you would use the multi-state object w/ integer for the messages?

Thanks again,
Dustin
 
Thanks for the good info there.
Yer' Welcome!



bmacattack33 said:
I realized the problem I was having with trying to use the COP instruction to shift the data was that I wasn't putting the "#" indicator on the source address, so it was just copying the same data across the array, rather than shifting it.

It was likely the direction of the copy, not the lack of index symbols that messed it up.


bmacattack33 said:
This method accomplishes the same thing as the third method I posted above, but it's a lot cleaner. Of course, it does display the chronological order of events horizontally in the PLC data table, rather than vertically, but that's not really a problem, since the HMI is the only place you'd really be looking at the data.

How much free memory do you have in the PLC? Plenty, I am guessing.

Create 6 or 10 new consecutive files and name them LOG_Hour LOG_Min LOG_Code, etc and so forth. Make them all the max size (256 in a SLC)

Here's how I typically craft these type of low level alarms/lists using a circular queue:

How ever many low level parameters there are for the record, make that many (usually integer) files and make them all 256 elements.

You will store the most recent 256 events and associated data and show them as many as you want in whatever order they want.

Heck you can even share the Last_Alarm pointer with the HMI so it could read all the ones it missed and write them to CF even after being disconnected for up to the amount of time it takes to get 255 events.

In the SLC, On commissioning, FLL them all with -1. Don't do that afterward. Don't do anything to the data on powerup or first scan.

Use logic to move as many pointers as you need through the file. One for next alarm which you will paint with -1 each time you get a new Alarm_Last Alarm_Last will always be one position lower than Alarm_Next pointer, but calculate them both once, in one place, and keep them in the range 0-255.

So, your PV+ takes the pointer, and through an expression, paints the alarm fields that are presently requested for viewing on screen with the correct consecutive data. If the PV+ can't do that type of indirection with HMI array tags and some EOF detection for the -1 stripe, then you may have to write a little map routine in the SLC. NO bigge, and its a good exercise. This is actually a good case for a conditional subroutine in a SLC...

Have a couple of pointers also for the range to be displayed. When the range pointer(s) change, run a subroutine that maps them to the tags seen on the screen.

Your pointer, just rolls, and each time it moves, it paints the oldest data with a "stripe" of -1, then paints the new data right behind it. This is easy to identify from a remote and even very intermittent connection to the user/HMI, historian, SCADA, or whatever.

The cool thing about the circular queue, is that you can have a dozen different sets of pointers looking at different ranges of it, without much PLC overhead...no copying unless a limited HMI requires it...just a tad bit extra indirect addressing to have all the numbers you need and more, preserved predictably and reliably right there in the SLC.

Now that I have talked you into doing it that way, you can remap and re-orient the display order on the HMI. Remapping also gives you the discretion to apply filters, sort, range check the time, etc.

On the HMI, you could make the text color animation visibility dependent on != -1

bmacattack33 said:
The problem with using a pointer is that they want a list-type display on the HMI that will show the 10 most recent events in order, so with a wrap-around pointer, once you got over 10 events, the log wouldn't shift, just write over the events at the beginning of the list.

I could just go ahead and add a string array that would load and shift the same way as the timestamp data, unless there's a way that the texts can be stored on the PV+, and loaded into the display table with the appropriate event (and still be retained in event of power loss). o_O

Could you elaborate a little on how you would use the multi-state object w/ integer for the messages?

Thanks again,
Dustin

In FTView Studio, look at the Multistate indicator properties. When the condition is true which can be a value or range of values, the state changes, each one has its own appearances, colors, texts, the whole she-bang. Great place to store text that shouldn't change very often (Alarm names, that is).

Paul
 
Last edited:
OkiePC said:
Now that I have talked you into doing it that way, you can remap and re-orient the display order on the HMI. Remapping also gives you the discretion to apply filters, sort, range check the time, etc.

You may have talked me into it, but whether I can pull that off is another story, at least at this point in my career...

OkiePC said:
How much free memory do you have in the PLC? Plenty, I am guessing.

The machine I'm working on actually uses an AB PLC 5/40. I just posted the examples in SLC because I have micro starter 500 at home to play around with, but, yes, I believe memory on the PLC is not an issue.

I already have a functioning program for tracking the value changes on the PV+ using numeric input enter tags and a dedicated alarm list on the setpoint screen, so even though I like your method a lot better, not to mention what a good learning experience implementing it would be, getting downtime for adding integer files and subroutines is highly doubtful.

OkiePC said:
So, your PV+ takes the pointer, and through an expression, paints the alarm fields that are presently requested for viewing on screen with the correct consecutive data. If the PV+ can't do that type of indirection with HMI array tags and some EOF detection for the -1 stripe, then you may have to write a little map routine in the SLC. NO bigge, and its a good exercise. This is actually a good case for a conditional subroutine in a SLC...

not sure about what you mean by "EOF detection"?

OkiePC said:
Have a couple of pointers also for the range to be displayed. When the range pointer(s) change, run a subroutine that maps them to the tags seen on the screen.

I'm assuming here you're talking about using, say, up/down buttons on the display to increment/decrement range pointers?

I'm in a training position at work right now, so most of the projects I get to work on I have to pitch myself, and they have to take a backseat to putting out fires on the floor. Plus, if I want to make any changes to programming on existing equipment, I have to have my ducks in a row before I start clickin' keys.

So I will have to work on this during my downtime, and get a working model I can show to my bosses before I can take it online. Hope you won't mind if I bug you with more questions if (when) I get stuck.

Dustin

🍻
 
bmacattack33 said:
You may have talked me into it, but whether I can pull that off is another story, at least at this point in my career...

The machine I'm working on actually uses an AB PLC 5/40. I just posted the examples in SLC because I have micro starter 500 at home to play around with, but, yes, I believe memory on the PLC is not an issue.

Good, so your alarm lists can hold 1023 items (plus the EOF indicated by all -1 values)

bmacattack33 said:
I already have a functioning program for tracking the value changes on the PV+ using numeric input enter tags and a dedicated alarm list on the setpoint screen, so even though I like your method a lot better, not to mention what a good learning experience implementing it would be, getting downtime for adding integer files and subroutines is highly doubtful.

Yes, I understand how that goes...sometimes I have to wait months just to blow out data tables...I tend to try to create lots of spare LAD and data files when the rare opportunity presents itself. I always leave plent of memory for lots of added ladder too, but ladder instructions are pretty compact, so you don't really need more than a few k words free for that.

bmacattack33 said:
not sure about what you mean by "EOF detection"?

The -1 values in all the fields (files) of at least one record (index) represent end of file. The very first time it runs, your queue will be filled with -1, but after filling it up once, only one position in the file will always contain the -1, or EOF (End Of File) indicators.

bmacattack33 said:
I'm assuming here you're talking about using, say, up/down buttons on the display to increment/decrement range pointers?

Yes.

bmacattack33 said:
I'm in a training position at work right now, so most of the projects I get to work on I have to pitch myself, and they have to take a backseat to putting out fires on the floor. Plus, if I want to make any changes to programming on existing equipment, I have to have my ducks in a row before I start clickin' keys.

This is one that you can experiment with RSEmulate500 with minor differences when you add the code to a PLC-5. Using indirect addressing is always a good reason to test offline and try to blow it up in a safe setting, getting all those ducks lined up is one thing, but then you should try to blow their heads off before you put the work into production. I also believe it is possible to run a FTView Studio app on your development machine and have it "connect" to your emulated SLC or Micrologix PLC.

bmacattack33 said:
So I will have to work on this during my downtime, and get a working model I can show to my bosses before I can take it online. Hope you won't mind if I bug you with more questions if (when) I get stuck.

Dustin
🍻

Use RSEmulate500. Read the limitations. Understand that your max file size for data tables is different between the SLC and PLC5, as well as (depending on model) that there are subtle differences in the inline 1-shot instructions between the two platforms, that PID and MSG instructions don't work in Emulate and they are different in how you code them, and that the scan timing is not exact in Emulate.

I enjoy trying to help, so you're not buggin' me at all.
 
Last edited:
Hi all,

Sorry for reviving the stale-ish thread, but I've done some more work on this exercise of alarm tracking/timestamping, and I think I've got the loading of the stacks more or less functional, but the problem comes in when I try to clear the stacks.

I'm using FFL/FFU instructions to load the stacks simultaneously, and then a counter as a pointer to my display stack (N9). Now, the FIFO instructions increment S:24 every time an alarm occurs. I believe that in the attached file the index register is at 32.

So when I execute the "clear stack" request, all the FLL's start their work from the indexed location, rather than the beginning of the stack. So I only overwrite what I haven't written yet o_O and worse, fault out the processor because FLL N9:0 tries to clear the entire table, but actually overwrites the file boundary.

I have tried clearing S:24 with a zero MOV, CLR instruction, and a SUB, but the program won't allow status bits to be written to. I'm thinking that you can do this on PLC5's?

So there's my question: Is there a way to clear the index register before clearing my stacks? Or do I have to use other instructions (COP/FLL?) to load my stacks that don't hog the index register?

I'm sure this question has been covered ad nauseum on this forum, but I haven't been able to find any direct reference to it.

Thanks again, in advance, for the help guys.

Cheers,
Dustin
 
but the program won't allow status bits to be written to. I'm thinking that you can do this on PLC5's?

well, I know that you CAN write to S:24 on an SLC-5/04 system – and I'd be willing to bet (substantially more than pocket change) that you CAN do it on the MicroLogix-1100 system that you're trying to program ...

BUT ...

I've got a hunch (no bet – just a hunch) that you can't write into S:24 using the EMULATOR that it looks like you're working with ...

suggestion: (a STRONG suggestion) get yourself a spare hardware system (NOT just an emulator) to test your programming on ... there are many differences between an actual (hardware) processor and a (software) emulator that just "pretends" it's a piece of hardware ...

good luck with your project ...

 

Similar Topics

Hey! I'm currently in the process of making a simple queuing system for an elevator model, it technically is nothing big, but I'm having an...
Replies
2
Views
1,718
Hi, Just starting to code a new project. Not used FIFO's before. I have read the instruction help file in RSLogix, and think I have got it...
Replies
13
Views
11,857
Hello again..trying something on an existing poorly written program and just wanted to double check something system is an A-B MicroLogix 1200 In...
Replies
5
Views
169
Good morning! Let me start by saying, I am still learning about this type of HMI programming. I recently watched a video about recipes and how it...
Replies
0
Views
71
I have some logic that I have written within a 5380 series controller that tracks the time an event is started, while the event is running an RTO...
Replies
2
Views
93
Back
Top Bottom