Sign in to follow this  
Followers 0
Joe Cody

Copying UDT Data In CLX

5 posts in this topic

I have a user-defined data-type that I need to move into a producer tag of the same UDT. The tag consists of various REAL, INT, DINT, and BOOL arrays. What is the best (read: most efficent and safest) way of moving the data from the base UDT into the producer UDT? I'm not the most suave on calculating the COP size, so I'm a bit wary on giving that a go, but if that's how it has to be then so be it. Thanks in advance, guys.

Share this post


Link to post
Share on other sites
COP source dest 1 Size is 1. Might not think that but it is, I think this is your question. No matter what is in that UDT if they have the same structure, and you just wan to copy from that UDT to the other UDT, copy size is 1. Just to be sure just put toggle some the data inside the SOURCE and execute the COP instruction and see it show up in the DEST.

Share this post


Link to post
Share on other sites
I'm reading a bit more on this now... Should I use CPS instead of COP, though, since this is going into a Producer tag?

Share this post


Link to post
Share on other sites
CPS is used if you do not want the data to change outside of that copy statement. Since comms run Async to the program this might be a good idea. My self I have not had too many problems with this as long as you buffer your data when it gets sent over the network. The buffering of data is move the data of the UDT structure into another structure once and then transmit this data. I believe this is what your describing above. Your not just using the tag that has data changing to use this also as a produce tag. Again test the use of CPS versus COP to see if the data is changing and also see if the data is stable in the other processor

Share this post


Link to post
Share on other sites
And pray tell how are you going to catch this one? The important thing to consider here is race conditions. If you write your logic such that tag A is dependent on tag B being synchronized, then you might be forced to use CPS. Otherwise, use COP since CPS will impact performance (global locks are always a bad thing performance-wise). If you have no race conditions (no synchronous dependencies) then this doesn't matter. First, let's dive into a common example so I can explain what a race condition is. For example, let's imagine a typical batch system and I want to record several measured variables when the batch completes. So imagine for a minute that I had this UDT: BatchNumber -- dint BatchTotalTime -- dint BatchFinalWeight -- dint BatchMixTime -- dint Now, I need to trigger something to record a batch record once for each batch. So I can simply monitor BatchNumber to know when to record all the values in the batch record. If you write code like this, make sure that the very LAST tag to get updated is the BatchNumber. That is the flag which indicates that the data record is up to date and that it is safe to record the batch record. This is very typical for a SCADA data logger, and you might imagine for instance doing some data aggregation/multiplexing. Now, this isn't exactly the most convenient way to do things. In addition, you need to make sure that the SCADA system has sufficient time to actually capture the data before you blank out the structure and start recording new data into it. So the best way to write this is to have a "working" and "LastBatch" tag. Make all the changes as the batch is running in the "working" tag. The very last thing to do when the batch completes is to COPy the data from the "working" to "lastbatch" tag. Then the SCADA sees BatchNumber in the "LastBatch" tag and knows that it is safe to record the data. However, all of the other tags in the LastBatch tag are synchronized to LastBatch.BatchNumber. If a packet (produced tag) goes out where BatchNumber has been updated but one or more of the other tags have NOT been updated yet by the COPy instruction, you are in big, big trouble because the wrong data will be recorded. The fact that correct function now depends on whether the communication processor acts first or the COP instruction completes first creates a race between the two. The actual probability of this happening is of course very small. Most race conditions are that way. But it's these little, tiny, very subtle bugs that will get you those strange phone calls every 6 months or so that you can't explain. See further information here: http://en.wikipedia.org/wiki/Race_condition There are three ways out of this quandry. First, you can use CPS. Second, you can set up two different data structures. The first data structure contains all the independent tags (ones that have to be updated first) and the second structure contains the dependent tags (the ones that have to be updated second). Then if you do two COPy instructions which are set up one right after the other in your code, you have prevented the race condition because you have guaranteed in logic that A happens before B. Third, if you put the dependent tag at the bottom of your UDT so that it is the last tag to be copied, then you can accomplish the same thing as long as you are careful to maintain the UDT in this form whenever you make changes. Think for a moment why you would use one or the other. With the CPS instruction, the communication and the logic solver processors have to specifically synchronize with each other to prevent a race condition from happening. CPS is a programmer convenience but you take a performance hit for using it (usually it means communication performance). Explicitly setting up your code to eliminate the race condition and the synchronization condition is the best and safest way. However, it does require some extra book keeping on your part. The same thing happens much more often with I/O. You can't assume that just because AuxContact is a "0" in one part of your program that it will still be "0" in another part on a single program scan. This is one of the most difficult things to get over with Logix 5000-based PLC's. The easy way to solve this is to simply COPy all of your I/O into separate tags and then use the indirect tags throughout your entire program. The race condition is avoided because you're not looking at the raw data values. However, you take two hits for doing this. First, your electricians will have to walk through the MOV/COPy instructions when tracing from your logic to the physical I/O location. Second, you take a performance hit for doing the COPy instruction on every single scan when it might not even be necessary. It is far better, just as above, to look carefully at any time you reference the same location more than once in your code and verify that you haven't created a race condition.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0