ControlLogix copy instruction too long ?

Ken Roach

Lifetime Supporting Member + Moderator
Join Date
Apr 2002
Location
Seattle, WA
Posts
17,480
I am diagnosing a malfunctioning system that uses ControlLogix (L63 controllers, v16 firmware) and want to run an unusual data handling question past the community.

There is some logic that includes a single-dimensional arrray. The array elements are themselves a UDT.

UDT_AxisHistory_DATA is a UDT of 80 bytes length, made up of BOOLs and DINTs.
FH_Data_N10[51] is an array of 51 of those UDTs, so its datatype is UDT_AxisHistory_DATA[51].

There is logic that's supposed to take just one of those UDT_AxisHistory_DATA UDTs and move it to a single instance of the UDT for display on an HMI. That tag is "HMI_DataDisplay", and it is also a UDT of type UDT_AxisHistory_DATA.

Here, a picture's worth a thousand words:

The original programmer, for whatever reason, used the incorrect Length when he wrote the COP instruction. Because the Source and the Destination are both UDT data types, the Length should properly be 1. He typed in 56. I haven't changed it.

So the question is: When a COP instruction Length requires the COP instruction to get more data than is possible, or put that data somewhere it won't fit.... what happens to the excess data ?

Bonus fact: Axis_History_HMI_Display is a Program-scoped tag and it happens to alphabetically be the last Tag in the Tag Database.

So could the "extra data" go... right over the end of the Tag Database and... into another Tag ?

In a sane world, the COP instruction would stop when it reached the end of the destination datatype.

But I've been chasing so many weird problems on this machine that I'm willing to inquire into some very unlikely ideas.

Are any of you folks familiar enough with the guts of ControlLogix tag databases and the COP instruction to make a suggestion ?

I dimly recall years ago testing this and finding that the data appeared to go harmlessly into nowhere. But that was a test program, not my gremlin-plagued control system.

COP Instruction UDT.png
 
What is the principle that you always find an answer immediately after asking the question ?

An excerpt from RA Knowledgebase Article ID #19715:

The FLL, COP, and CPS instructions will copy data until they reach the end of the destination array OR the length (number of destination elements) is reached.

This prevents any of these instructions from ever exceeding an array boundary in the destination array.

However, if the Source data file is too small, (as with the COP or CPS) then the COP or CPS will take whatever is next in the controller memory and copy it into the destination address. This will continue until we reach the end of the destination array or we copy the number of elements as specified by the length field.
 
I actually not qualified to answer your question,

But I like to share what cross on my mind and I want to gain my knowledge,

Probably not an answer but more questions,

If the destination only goes to HMI for reading only, nothing will affect another function or data,

As you said change to 1 is the best value, it look logical.
(base on COP – limitation/error/scan/etc)


But for the UDT, I had read an article –

A UDT contained in a UDT

Array optimizations and UDT optimizations

Are this related with the UDT_AxisHistory_Data, FH_Data_N10[51]

Probably I miss-understand
 
Ken,

Interesting topic, daba will probably give you a better answer, but here is my take on it. This quote was actually from a recent post by daba

"COP, however, doesn't even look at the source and destination data-types, it simply copies a number of bytes of data. Using COP to copy a floating-point source to an integer destination will give, not unpredictable, but undesirable results."

Having said that when the COP instruction executes copying data from FH_Data_N10[51] to destination HMI_DataDisplay, both having the same data type being UDT_AxisHistory_DATA, and both also having a length of 80bytes, i believe you are right in that a length of 1 will copy the entire 80 bytes in size from one tag to another and achieve your desired result. Now i don't know if this is causing an issue for you as of now, but the current length being 56 i don't think will cause an issue. This is because once the copying is done copying byte by byte and reaches the end of the length specific in the UDT, the rest of the remaining 55 bytes of non existing data will be floating around somewhere in memory(i know that sounds vague but im sure their is a better explanation to it), not affecting your HMI_DataDisplay value, but probably using very little resource.


One way you can test this if you can is, make another integer tag, and use a COP instruction with a source being FH_Data_N10[51] and a destination being HMI_DataDisplay[Test_INT], then make the length 2. So i think when the COP executes, if you Test_INT value is 0 you will see the same data in both FH_Data_N10[51] & MI_DataDisplay[0], now if you change the Test_INT value to 1, and monitor what is copied, i think it will be 0 because after the first length is done copying their won't be any data to copy, or you can see if their is data.

Hope this helps
 
Last edited:
I saw this with my first Logix5k program during bench testing, using COP instructions, I was getting garbage in data in the destination until I got my length right, and the data was ordered from other tags since the project was freshly recompiled, it was easy to see the matching pattern appear in the tag data monitor. This was way before the UDT came along and further clouded the possibilities.
 
Ken,

I had some problems that sound very similar to yours in the field a couple of years ago where I was trying to assemble data into a single UDT that originated from other smaller UDT's. I had some crazy results that popped up from time to time. I'm not sure that I'm smart enough to explain it over the internets, but I may be able to explain over the phone if you want to chat.

Basically:
Source was UDT "A"
Destination was UDT "A" and UDT "B"
Obviously Destination was larger than the source
Data in UDT "B" was overwritten with strange data when we performed the copy
We ended up performing the copy, then overwriting the the UDT "B" tags with it's original data again to get around the problem.
 
The RA text quoted makes no reference to whether the destination array is a single tag, or an array element of a UDT tag.

It has always been my understanding that a COP, CPS, or FLL simply stops copying if the end of the destination tag is reached. That is where the protection is set.

This means that if the destination is part of a UDT tag, then elements following the desired destination area, within the same tag, are vulnerable if the length is specified incorrectly.

COP CPS and FLL use the "length" you specify, multiplied by the number of bytes of the destination data-type, to determine the number of bytes to copy. Then it just gets on with it with no further boundary checking except for when the end of the destination tag is reached. The bold text indicates why strange data will populate the destination if the source size is less than the destination size.

P.S. I've seen this actually used to "an advantage", although it was many years ago.... The application had a UDT that contained multiple arrays, and a single FLL was used to clear the contents of all the arrays in one go. The programmer was sloppy, and for the 10 arrays of 30 DINTs each, he had put a length of 1000 !!, obviously relying on the destination tag boundary check. The correct length should have been 300. In doing this short-cut, however, he made the UDT unchangeable without correcting his FLLs, so I would not advocate using this practice, no-one will have a clue what is going where. Much better to put separate FLLs for each array, which gives Mr. Maint Tech a fighting chance of understanding what is being done.
 
Last edited:
I can't say that I can explain all the specifics of how this all works, but I can say that I had a similar issue 2 years ago on an L73, v19 controller.

If our process logic was "idle", we clear down a bunch of parameters. Theses parameters were part of a larger UDT, and the parameters reside in an Array.

Example:
UDT_Tag.Parameters_Real[0]
.
.
.
UDT_Tag.Parameters_Real[49]

UDT_Tag.Parameters_Ints[0]
.
.
.
UDT_Tag.Parameters_Ints[49]

So to clear them down we would use a FLL instruction to populate each element with a "0".

In this example, the array size is 50, my FLL instruction had an incorrect length of 51. This in-fact, caused me problems as "0" cleared down data OUTSIDE of the defined UDT. It had me frustrated for a few days until I figured it out.

Now, some more on that UDT tag structure. In my example, the UDT tag was also an array.

UDT_Tag[0].Parameters_Real[0]
.
.
.
UDT_Tag[0].Parameters_Real[49]

UDT_Tag[0].Parameters_Ints[0]
.
.
.
UDT_Tag[0].Parameters_Ints[49]

UDT_Tag[1].Parameters_Real[0]
.
.
.
UDT_Tag[1].Parameters_Real[49]

UDT_Tag[1].Parameters_Ints[0]
.
.
.
UDT_Tag[1].Parameters_Ints[49]


I don't recall how exactly this affected data in my UDT tag, did it overwrite data in my Parameters_Ints[x] elements? or if it jumped to overwrite data in my UDT_Tag[x] elements? Ether case, it caused problems.

Ultimately, we now use the SIZE instruction to validate the length of the destination location that is an array to ensure that we don't run into the same issue. Should it really be a Rockwell issue? I'm not sure.
 
You learn something new every day. I didn't know the Logix engine checked for exceeding a destination tag boundary on a COP. One less thing to worry about I guess. I just assumed it would continue on and pollute whatever was next in physical memory.

In the case of an array of UDTs your array is at risk of pollution but any data outside of the array is not. If you write over the boundary of a single UDT inside of an array of UDTs (assuming it is not the last element) you will start polluting the next UDT instance in line beginning with the first element of the UDT, whatever that may be.

Keith
 
Haven't had this happen to me, but seems can be a problem within a UDT from above. You could maybe test spillage outside a UDT, or tag to tag by generating a few different types, and filling up the rest of the memory with a large array, and seeing if any values change as a result of an incorrectly sized copy ??
 

Similar Topics

I am trying to Copy 50 DINT to 100 INT. Another engineer said it should be a move. Will a Move handle DINT to INT? (The DINT numbers are all...
Replies
26
Views
7,038
How do you copy the contents of a dint256 tag to another dint256 tag in Controllogix while offline? I've done it online with a copy statement...
Replies
3
Views
6,019
Why does the controllogix redundancy modules use a single mode fiber vs multimode fiber?
Replies
1
Views
80
Hello, I have two 16 point input cards and 1 16 point output card showing module faulted on my IO tree in Logix Designer. The fault code is...
Replies
7
Views
214
Hello, My associate and I are trying to sync up two ControlLogix racks (7-slot chassis) with identical modules. We are able to see the secondary...
Replies
4
Views
193
Back
Top Bottom