How to compare PART of a UDT Array

TheWaterboy

Lifetime Supporting Member + Moderator
Join Date
May 2006
Location
-27.9679796,153.419016
Posts
1,908
I have a UDT that has 3 UDT's inside it. One is used for control and two are used for status.

UDT.jpg

In the polling PLC I need to examine the CMD portion of UDT for changes that would then enable a Write MSG.

FSC.jpg

I have used FSC on arrays, but never tried on part of a UDT.

I cant find a way to examine the entire CMD section of the UDT for changes so if I keep using this idea It appears that I need to use an FSC for each section of the CMD portion?

Perhaps I am barking up the wrong tree in this effort?

Anyone got a better idea?
 
Check out the DTR instruction (Data Transition). It's designed to do exactly what you're looking at, and can operate on Arrays. Although you'll still need one for each array, it's much simpler than an FSC.

It might be too far gone to think about this now, but one thing to consider is using DINT's instead of BOOL arrays. I've beaten my head against walls for hours with BOOL arrays, in general they just don't play nice. You can use a lot more instructions on the 32 bits of a DINT than you can on 32 BOOL's in an array. Addressing is just as easy (or actually simpler: Bool_Array_Faults[0] becomes Dint_Faults.0
 
Yea, I'm just noticing that Bools are not playing the same way as the other data types. Its not too late to change, thats what this exercise is for.

DTR looks like it only works on ONE element at a time, not the entire array of similar elements.
 
What about the idea of doing an AOI that takes the UDT in and does the searching for you? That way, even though you may need to do a few different comparisons, you still only have one bit of logic to work with and make work.
 
If it's not too late, I'd definitely be changing everything over to DINT's.

From there, I'd be making an AOI as keshik suggested - if structured text is an option for you, it would likely be quite a simple "for each element in [D/R/S], if not equal to last scan then set bit" (I've not done enough structured text programming to give you correct syntax, but it shouldn't be difficult). The single DINT containing your 31 bits would just be a straight NEQ operation. After your AOI finishes executing, COP your UDT to a UDT "last scan" tag, trigger your MSG if required, and reset your trigger.

If structured text is not an option, then it looks like you'll be stuck with the FSC or a NEQ with JMP/LBL and incrementing pointers.

You may already know all about it, but just to save you the headbanging if you don't - to reference a UDT inside an AOI you'll have to define it as an InOut parameter.
 
Oh you don't need to change the reals and strings over, sorry, that was a bit misleading. Yes, reals and strings are fine as they are - you can use most standard instructions on them without issue. It's just the BOOL arrays that are a royal PITA.

My standard comms UDT has one DINT called BinaryData, 20 REALS called AnalogData, and a connection status called Status. I haven't ever needed strings but you get the idea!
 
a tip for testing
use a COP of your CMD into a DINT array and then you can use FSC
also use the SIZE function to help you get the COP the correct size
 
Some Progress

Well this is where I am so far...

attempt1.jpg

This works, but depends on a timer to alternate the COP's between scans of the FSC.
I would prefer it worked by alternating the COP strings each scan so that the FSC could run every scan.
I made that happen once by using the ToggleEveryScan bit, but then I couldn't figure out how to retoggle the FSC once a match was found.
And I'm on my 14th hour at the desk today so I'm out of grey matter.

In addition and no real surprise, COP-ing a string to a Dint behaves just as badly as I anticipated.
Essentially a buffer overrun occurs. "popcorn" becomes three elements of numbers starting at [66].
I wonder what happens if I copy it into the last element of the array . . . :oops:

popcorn.jpgPopcorn Converted.jpg

I get why this happens, so this was not unexpected.
I wish there was a hash function I could use here to compare strings.
Is there a way to compare an array of 20 strings that doesn't require a separate Array and FSC?

My goal is to get this into a periodic task so I can just set the task period to the response time I need to detect changes.
 
I can't quite read your logic screenshot, but from what you've written...

Do you understand that the COP length is in terms of destination elements? If not, have a read up on that, there are hundreds of threads mentioning this as it's a common mistake to think that the length is in terms of source elements.

You can use the RES (reset) instruction on an FSC. I typically put a RES right before the FSC itself, to ensure I know exactly where things are before I start. That way you can run the FSC every scan; each time you just reset it, check the array to see if there's been a change, and COP the current values across to the last scan tag for the next time around.

There is also some info in the help file about which bits to unlatch to continue from the current position, vs starting again from the start. From memory, if your FSC finds a match, it sets the .IN tag. If you unlatch this tag, next scan it will continue from the next element in the array, without going back to the start. Not sure if that will do what you want or not.

The FSC should be fine to compare strings, I use it quite often to e.g. search an array of barcode strings for a string I just received from a barcode scanner. Obviously the expression would be slightly different, but it should work the same way.

Does any of that help you?
 
I didn't know that caveat about the COP instruction, but I also can't envision how that would ever be a problem. Certainly not in this code anyway.
I got this working but had to use 2 FSC. Using the (RES) works but is not documented in the FSC help file as being a valid use.

Take a look at the PDF and see if you can see anything wrong with this approach. I could certainly hardcode the indexes but I don't think it would save too many cycles and I'm not hurting for those. Takes up to 850uS to run which is among the longer running routines I have created.
Its in a periodic task at 250ms and detects every change so far.
View attachment Change Detect.pdf
 
TheWaterboy said:
I didn't know that caveat about the COP instruction, but I also can't envision how that would ever be a problem. Certainly not in this code anyway.
The time this becomes a problem is if you're copying different data types. For example, it's quite common for some devices to send a 32-bit REAL value over comms as two 16-bit integers, which then needs to be reassembled. If you COP the first INT into the REAL with a length of one, it'll actually copy the two INT's into the REAL, as the destination type is 32 bits, so it goes and gets 32 bits worth of data. But say you were to think "no, I need to copy both INT's into the REAL", and set your COP instruction to COP the first INT into the REAL with a length of 2, well, it'll copy your two INT's into the REAL, and then copy another two INT's into the next 32 bits of memory. And that can cause you to have a whole lot of fun, because who knows what that next 32 bits of memory might be?

But I digress. Glad it's working, and just a couple of tips:

You don't need to specify the array element on a SIZE instruction. I.e., instead of running a size instruction on Real_Array[0], you just run it on Real_Array. I'm not sure offhand whether you're (correctly) returning 32 because the instruction is clever enough to ignore you putting the [0] on the end and inspecting the array anyway, which just so happens to have a size of 32, or whether it's then looking at Real_Array[0] as a single REAL, and saying "this REAL has 32 bits". Might be worth trialling changing the size of your array to 33, and seeing what the SIZE instruction gives back!

The CPS instruction is quite processor intensive, and in most cases unneccessary when a COP will do the same job. There's a technote on the subject but I haven't been able to find it just now; essentially the COP is just a straight out dumb copy, whereas the CPS does a whole lot of interrupting other processes and cross checking and double checking to make sure exactly what was intended to be copied has in fact been copied. The place you may need to use this is where you could have an asynchronous operation update the source data partway through the operation, and where doing so would have an adverse effect on what you're trying to do with the copy. So on rung 2, perhaps it's necessary to use CPS as (I'm guessing) it could be possible for the produced tags to update your source data partway through the operation (if they did, what would the consequences be?). But on rung 7, where you're just copying data from one internal tag to another internal tag, where nothing else writes to the source tag, there's no need.

It's not the technote I was looking for, but technote 46251 (TechConnect Required) gives a very brief "where to use COP or CPS" table, which ultimately comes down to "in this very specific circumstance, use CPS; otherwise or if you're not sure, just use COP".

Other than that, your logic looks very much like how I would have done it!
 
Any little or big endian stuff I would handle on the remote side, so swapping bytes is a non issue at this point in the stream. I knew CPS would be a little more intensive. I'll read your note and look into it more. Probably try both again just to nail it down. I would have thought the FCS would be the processor hog here. :)

Next to pack this into an AOI 'cause I gotta use it a LOT.

Thanks for the feedback.
 

Similar Topics

What is a good method to take a floating point number and strip off the numbers to the right of the decimal so they can be use in a compare...
Replies
17
Views
4,382
Hello, I know this will be easy for most. I currently scan a barcode on a part and it returns a string value with a mix of numbers and letters. I...
Replies
1
Views
1,352
Help please. Im new to Omron and have a machine down. I have a compare = for barcode label scan. I've attached two pics. On the Mnemonics you can...
Replies
4
Views
602
Hi everyone! Accidentally closed it and it wont appear again. Checked and unchecked the option and seem to make no difference. Running v7.10.00...
Replies
16
Views
1,816
I'm working on an array that contains a UDT of 5 Items Array[4] DataType[0] - Part 1 - Part 2 - Part 3 - Part 4...
Replies
1
Views
814
Back
Top Bottom