Shifting an array in Logix 5000

shoelesscraig

Member
Join Date
Apr 2009
Location
LA
Posts
382
Ok, I'm trying to do something that I'm sure is very simple. I am missing something. I am using a CLX so this is in Logix 5000 software.

So I was thinking I could use a "copy" instruction for this, but I tried it and I guess I'm wrong. I have an array of 10 DINTs. Lets just call them DINT[0],DINT[1] and so on up to DINT[9].

In DINT[0] I have the number 1, next one is number 2 and so on up to 5 which would be in DINT[4]. The rest are zeroes.

I want to copy what is in DINT[1] with a length of 4 and paste it into DINT[2]. Basically shifting everything in DINT[1]-DINT[4] down one position. I realize that DINT[1] would still have the number 2 in it, and thats fine. It can remain unchanged. Then DINT[2] would have number 2, DINT[3] number 3, DINT[4] number 4, and DINT[5] number 5.

At least that is what I want. To be able to shift or "copy" part of an array on top of itself. Of course, this is just my example. What I actually need to use it on is arrays that are several hundred DINTs long, not just 10, but you get the point. I tried the COP instruction, but got undesirable results. What am I missing? Can the FAL instruction do this?
 
May I ask why you want to shift like that with copy instructions? I shift large amounts of data around (large UDT structures), but rather then copying the entire array around, I just use the FFL FFU instructions and keep a FIFO going.

With a FIFO, you only shift one element at a time, which might not matter if you only have a 10 slot array, but if you have a 2000 slot array, it does matter.
 
I tried the COP instruction, but got undesirable results

Think about what the COP would be doing. it would first copy DINT[1] into DINT[2]. Now it picks up DINT[2] to copy to DINT[3], but wait ... DINT[2] no longer has its original contents. They have been overwritten by DINT[1]'s contents. So you probably ended up with an array filled with DINT[1]'s contents.

There are two ways, if you have to use COP to move an array within itself. One is to copy the entire array to another, dummy, array then copy it back to the original but offset by one place.

The second is to copy UP. Place you newest information at the end of the array then do a copy of [1] to [0], [2] to [1] etc. For example - COP DINT[1], DINT[0], 10
 
Bernie covered the way I would do it if I "HAD" to use copy. Move it starting from the tail end of the array with a copy. That works, and it's ok for small arrays because you can live with an inefficient method.

But you want to handle large arrays. Shifting all that data around is a lot of busy work that doesn't actually do anything. Instead let the data sit where it is and change a pointer to indicate the start/end of the array. This is much faster. If you add one data item to a 100 element array using copy, 100 elements get read and written. If you use a pointer, one element gets written. The additional logic to manage the pointer is actually pretty trivial.
 
Only reason that I've used COP (going to a 2nd dummy array and back again) is for displaying purposes. I use FTView ME and have a cell type display for that 20 elements. FTView ME only allows 'pure' integers to be used as the element number compared to a reference integer... i.e. data[2] and not data[first_element].

I might be wrong with the limitations for FView ME, but it is the only way that I was able to display what I needed on the screen
 
and sometimes the "ripple" or "ratchet" effect is the best way to display the "marching bar graphs" that you often see on HMI/SCADA screens ...
 
What I actually need to use it on is arrays that are several hundred DINTs long, not just 10, but you get the point. I tried the COP instruction, but got undesirable results. What am I missing? Can the FAL instruction do this?

Rather than shifting huge amounts of data around you might consider using a circular queue. If one will work for you this thread http://www.plctalk.net/qanda/showthread.php?p=260919#post260919 has an example for a Micrologix I did some time ago.

I've attached a similar example for the ControlLogix (V16) that shows rolling storage for 300 data points for five minutes of data and once a second sampling.
 
If you want to use copy to shift arrays of integers using copy, you really need to do it backwards. So if you have an array of 10 DINTS, Copy DINT[1] to DINT[0] and set the COPY instruction's length parameter to the length of your array. So the 'top' of your table is actually DINT[10] and the 'bottom' is DINT[0]. If you are loading data into the 'Top' of the table write to DINT[10] then every time the COPY instruction runs it will shift one position closer to DINT[0].

The circular queue that Alaric mentioned is waaaaay more efficient, but controllogix can definitely handle shifting relatively large arrays if you are stuck on the idea. We've got a system that uses copy to shift 4 separate 3000 position arrays of DINTS based on two incremental encoders at 60 some-odd pulses a second. Even despite moving 12,000 DINTs around 120 times a second, the scan times are still well below 1ms.
 
I tried the COP instruction, but got undesirable results. What am I missing? Can the FAL instruction do this?
The short answer is, "yes". The FAL instruction is more involved than COP but it's also more versatile in that you can, at run time, control the length and start position parameters.

If you're going this way, be sure to include some validation logic on the elements you're controlling. For example, if the defined file length is 100 and some faulty logic or algorithm gives the FAL a length of 237, there will be problems - as in the processor will fault.

Also, you'll need to insure that it gets a false-to-true transition when you want it to do its thing (be careful of subroutines in this regard). Two ways to guarantee this are: issue a RES* on the control element or; include an identical unconditionally false FAL immediately preceding the one which will actually perform the function.

* This undocumented feature works on the PLC-5. Don't know if it applies to CLX or not.
 
Unlike a COP which copies UP you could program the FAL to shift everything down one position by starting at the bottom of the array and working backwards using [Arraysize - control.pos] in your expression.

With a 200 DINT array
FAL ShiftControl 199 0 ALL DintArray[199-ShiftControl.pos] DintArray[198-ShiftControl.pos]
Moves DintArray[198] to DintArray[199], then DintArray[197] to DintArray[198], etc.
 
Rather than shifting huge amounts of data around you might consider using a circular queue. If one will work for you this thread http://www.plctalk.net/qanda/showthread.php?p=260919#post260919 has an example for a Micrologix I did some time ago.

I've attached a similar example for the ControlLogix (V16) that shows rolling storage for 300 data points for five minutes of data and once a second sampling.


In terms of level of complexity, is the FFL at all similar to the circular queue?
 
This worked for me. Thank you!


Unlike a COP which copies UP you could program the FAL to shift everything down one position by starting at the bottom of the array and working backwards using [Arraysize - control.pos] in your expression.

With a 200 DINT array
FAL ShiftControl 199 0 ALL DintArray[199-ShiftControl.pos] DintArray[198-ShiftControl.pos]
Moves DintArray[198] to DintArray[199], then DintArray[197] to DintArray[198], etc.
 
I'm going to resurrect this to point out that you can't load into a FIFO via FFL for two consecutive scans; there must be a dead scan for the FFL to see another rising edge and load another value. I battled that BS for a while trying to make a simple state trace and went with the COP method.

I also ran into the same issue as OP and ended up copying to a second array and then back into the first array. Overall memory usage is less than the FIFO approach for my array size, but very large array sizes will start to be more since you are making two arrays that large (well, the buffer array can be one index less) and scan time difference is small enough it can't be measured and I imagine array size has little impact unless the COP instruction is way less efficient than it should be.
 
I'm going to resurrect this to point out that you can't load into a FIFO via FFL for two consecutive scans;...


I am passing on this sweet hack that others passed to me; I don't know if it will work in your environment, but it certainly works in MicroLogix 1100/RSLogix Micro Starter Lite (freebie).

xxx.png
 
Last edited:

Similar Topics

Hey guys, Again, another question I have that I can't seem to find the answer in the search. I am writing a program to go along with my...
Replies
5
Views
16,229
Greetings, I am trying shift data in an array (such as Array[0] is shifted into Array[1], Array[1] is shifted into Array[2]......all...
Replies
10
Views
336
Hello Guys, I think I need to use SCL for the following task but am very weak using SCL in tia portal. I have results history data block. It is...
Replies
14
Views
2,951
Hey guys, What do you suggest for doing a shift of dints within an array like this? Thanks, Kevin
Replies
12
Views
2,540
Not sure if this is possible but thought I would put it out there. Using Rockwell Studio 5000, is it possible to shift the address of an array...
Replies
7
Views
2,044
Back
Top Bottom