Can Someone Please Walk Me Through Using the FSC Instruction?

LCbaseball22

Member
Join Date
Jun 2019
Location
Spokane, WA
Posts
3
Hello,

I'm brand new to the forum and I have a frustrating problem at work that I've been trying to find a solution to. I have scanned the Rockwell manuals and the RSLogix5000 instruction help to no avail.

Here's what I'm attempting to do:

-Create an array to record part data for serial #'s that fail spec
-Search array for empty positions to load data for next failed part
-When part is reworked search array for serial # match; if match found pull respective part data

The FSC instruction looks like an elegant solution for this but it's not working.

What I have tried so far:

Created a User-Defined Data Type-

Name: PartData
Member: Barcode , Data Type: STRING
Member: Weight, Data Type: REAL

Created Tag Array-

Name: PartRejectArray[5]
Data Type: PartData

FSC (to find next empty position)

Control: Not sure what to use here; tried using both my PartRejectArray as well as individual tags and other arrays, nothing was accepted
Length: Should this populate automatically? I tried entering 5, didn't work, said not supported or something
Position:
Mode: ALL
Expression: PartRejectArray[PartRejectArray.POS].Barcode = 0 (or should it be ''?)

FSC (to find match)

Control: Same issue
Length: Same issue
Position:
Mode: ALL
Expression: Barcode = PartRejectArray[PartRejectArray.POS].Barcode

I'm trying to recall from memory but I believe there was some errors I was getting about the argument and operand or parameter data type not matching, but I know for a fact the barcode tag is also a STRING...

Lastly, once I can actually get the FSC instruction to return a position for the empty/match how do I use that info to move/copy a barcode in/out of the array?

Any help is much appreciated. Thanks!
 
Welcome to the forum!


You're on the right track, I think, just a few minor hurdles to get you over the line.

First things first:

Created Tag Array-

Name: PartRejectArray[5]
Data Type: PartData
Small nitpick - your tag should be called PartRejectArray and it should be of data type PartData[5], not what you've stated above. I'm assuming this is actually what you've done, and you just made a small typo in your post (putting the [5] on the end of the tag name, not the data type) - but just making sure! Ultimately, what you should have is an array of five of your UDT's, named PartData[0] through PartData[4]. Within each of those UDT's there are two elements, Barcode and Weight, so if you open your tag browser you should be able to drill down e.g. PartData > PartData[3] > PartData[3].Weight

As long as that's the case, moving on!

FSC (to find next empty position)

Control: Not sure what to use here; tried using both my PartRejectArray as well as individual tags and other arrays, nothing was accepted
This is a Control tag that the FSC uses to perform its magic. You need to create a new tag, of data type Control, and put it here. Think of this tag as the FSC itself - whenever you refer to the FSC instruction, you refer to this tag, not your array data. So, I would call the tag something like RejectArraySearch or PartRejectFSC - that makes it easy for you (and other programmers) to distinguish between the data you're searching (your array and the data within it) and the method you're using to search for it (the Control tag and the FSC that uses it).
Length: Should this populate automatically? I tried entering 5, didn't work, said not supported or something
This will not populate automatically. You have to tell the FSC how far through the array to search. Sometimes you may not want to search the whole array, only the first, say, 100 elements. You should be able to put a 5 in there directly; it's likely just not being accepted right now because it doesn't have a valid Control tag assigned, and the Length parameter is actually part of that Control tag. So the FSC has nowhere to "store" your value of 5.

Unsolicited tip: if you were to put "6" in your length field, you would likely crash the PLC, as it will go looking for an array element that doesn't exist. For this reason, I always use a SIZE instruction immediately before the FSC instruction. The SIZE instruction gets the size of my array, which I then put into the Length of my FSC instruction. As well as ensuring I don't fault the PLC, if in the future I realise I need 10 array elements, not 5, I just have to increase the size of my array and the FSC instruction will automatically be updated. How do you get the result of the SIZE instruction into the FSC Position? Easy. Remember, the Length is part of the Control tag we discussed before. So, if your FSC Control tag is called PartRejectFSC, you would just make the Destination of your SIZE instruction PartRejectFSC.LEN

Position:
This will be automatically generated/updated. You should for the most part never need to write to the Position manually; only read it. If you need the FSC to go back to the start, use the RES instruction (again, directed the Control tag) which will set the Position back to zero, and reset all sorts of other flags that need resetting.
Mode: ALL
This should be fine - you can have the instruction search one array element per scan, or all of them - but with such a small array there's no need to do anything other than ALL
Expression: PartRejectArray[PartRejectArray.POS].Barcode = 0 (or should it be ''?)
After all my waffling above, hopefully you've gotten your head around the difference between the Control tag and your Array. This is where your array comes into play. You want to search each element of the array for a specific value. Effectively, you want to do:
Code:
PartRejectArray[0 through 4].Barcode = BarcodeYouWant
To get the "0 through 4" you are as you expected going to look at the Position of your FSC instruction - which is, as you can probably guess, part of the Control tag. So if you called your Control tag PartRejectFSC, then you need to use PartRejectFSC.LEN - giving you:
Code:
PartRejectArray[PartRejectFSC.LEN].Barcode = BarcodeYouWant
Now, your second issue is that you need to determine what constitutes an "empty" slot in your array.
It seems you're looking for a blank string in the Barcode UDT member, which is one way of doing it. How to achieve that? The latest versions of Logix will allow you to use a literal string, but earlier ones will not. You could create a new string tag, call it BlankString and use the DELETE instruction to ensure that it always stays empty. Then you can compare to that tag.

Alternatively, you could check the length of the Barcode string - if the length is zero, the barcode is obviously "blank":
Code:
PartRejectArray[PartRejectFSC.LEN].Barcode.LEN = 0
One other way might be to add a BOOL member to your UDT called, say, InUse. When you load your rejected part into the array, you'll presumably be copying a string and a number into the Barcode and Weight UDT members; at the same time use an OTL to turn on the InUse member. When you remove an item from the array, DELETE the Barcode string, CLR the Weight, and OTU the InUse.

Hopefully with that information you can also work through how to find the "matching" barcode.

Lastly, once I can actually get the FSC instruction to return a position for the empty/match how do I use that info to move/copy a barcode in/out of the array
Easy. Your position is once again part of your Control tag. So, assuming your control tag is called PartRejectFSC, you should first look for PartRejectFSC.FD (found) to be true. That means it's found a match. If PartRejectFSC.DN (done) is true but PartRejectFSC.FD is not, then the FSC reached the end of the array before finding a match.

Assuming you found a match, the FSC will halt with its position equal to the array element with the match. If you were looking for a blank space to copy your data into, simply use a COP for the Barcode and a MOV for the weight, with PartRejectFSC.POS as the pointer for the array element. e.g.:

Code:
COP
Source: FaultyBarcode
Destination: PartRejectArray[PartRejectFSC.POS].Barcode
Length: 1

MOV
Source: FaultyWeight
Destination: PartRejectArray[PartRejectFSC.POS].Weight
Then - IMPORTANT! - reset the FSC instruction. You want to make absolutely sure the next time you use the instruction, you're starting from the start!

Moving them out of the array will look exactly the same as moving them in, just with the source and destination reversed. However, remember that this doesn't remove the source data! i.e. you'll copy your Barcode and Weight data out of the array into some other tags, but they will still exist unchanged in the array. You will again need to use the PartRejectFSC.POS to delete that data from your array, using a DELETE instruction for the Barcode, and a CLR instruction for the Weight. Then, reset your FSC. Or, if you go down the track of using my "InUse" boolean idea from above, you could in theory just leave the values in there and solely use the InUse to determine whether that array element is in use or not. A word of caution - leaving old data in the array may be confusing for yourself or others looking at the array. Even more so if you can see the array contents on a HMI anywhere. Even if you don't need to delete the data from the array, you should consider whether it would be good practice to do so anyway.

Good luck!
 
Last edited:
Thank you so much ASF!

I've been pouring through the forum searching for any and all FSC related threads/posts and was still scratching my head.

Funny enough I noticed your username on a LOT of responses and thought I'd just try PM'ing you, if you were still an active member. :p

So anyways, I will see how far I can get now tomorrow with all the clarification and tips you've provided.

I believe my biggest error has been not realizing that there is a control data type, as I did also try creating a new tag to use for the control, but if I recall correctly set it as a string data type. I'm sure this is why I got all the error messages and could not populate a length.

Also I really appreciate the hint about resetting/deleting as I certainly would have been scratching my head once the array was filled why it stopped working...

Thanks again!
 
Last edited:
No worries! Yeah, I think once you have the Control tag in place you'll be all set.

One more tip for you that might help you in future scenarios. Instead of creating a new tag in the tag browser, just type the name into where it's going to be used, then right click and pick "New Tag" (or Ctrl+W is the shortcut). It'll automatically select the correct data type based on where you put it. If you put it on an XIC/OTE/other binary instruction, it'll select BOOL. If you put it on a TON/TOF/RTO/other timer, it'll select TIMER. And if you put it on the FSC in the Control position, it'll select CONTROL. If you're not sure what type of tag you need, that's a quick and easy way to find out.

Of course, it's not foolproof - it'll default to DINT on all your math/comparator instructions, and sometimes you need a REAL. And when you're using COP, well, you can copy just about any data type so it's really up to you at that point. But it's a helpful trick to know!

Just to mention, too - most people on this forum (including myself) don't respond to requests for help via PM. We prefer it to be posted publicly on the forum (as you did) so that others in the future can have the knowledge is shared and to avoid answering the same question over and over. But in any case, glad I was able to help!
 
ASF you stated this:
To get the "0 through 4" you are as you expected going to look at the Position of your FSC instruction- which is, as you can probably guess, part of the Control tag. So if you called your Control tag PartRejectFSC, then you need to use PartRejectFSC.LEN - giving you:

I think you meant this:
Code:
PartRejectArray[PartRejectFSC.POS].Barcode = BarcodeYouWant
 
Ah. Yes. Yes, I did, in all cases. Good catch - can't edit the post now but hopefully LC has worked out what I was getting at and corrected accordingly!
 
Ah. Yes. Yes, I did, in all cases. Good catch - can't edit the post now but hopefully LC has worked out what I was getting at and corrected accordingly!

Yes, I figured that was a typo.

Well the complexity of the solution grew as I now have three FSC instructions and needed to figure out how/when I wanted to trigger them and when to clear/not clear the data array.

I think the difficulty was due to all three FSC referencing the same Reject part data array, which meant I really had to keep track of which bits I toggled at which times when testing and monitoring. I also had to add a bunch of NEQ’s for barcode not equal to null_string because blank barcodes were being copied/overwriting array values at times.

I tested all day today and while initially data was being copied or deleted at the wrong times, I think I finally have it working as I intend! :) ASF all of your tips were super helpful in getting to this point. Thanks again.

In terms of clearing the array I landed on only clearing the data from the Reject array after the full rework cycle has been completed, meaning the 3rd FSC finds a match between the barcode of the part at the outgoing weigh station and the parts in the array. Once the part has completed its re-weigh and the barcode is null_string this triggers a COP null_string and CLR weight for Reject[ReworkOutFSC.POS].Barcode and Reject[ReworkOutFSC.POS].Weight, respectively.

One thing I’ll note and I’m confused about is that the RES bits didn’t seem to reset the .IN bit for some reason. Perhaps I had something wrong but I ended up using a OTU as suggested in a different thread I found on this forum!
 
Last edited:
One thing I’ll note and I’m confused about is that the RES bits didn’t seem to reset the .IN bit for some reason. Perhaps I had something wrong but I ended up using a OTU as suggested in a different thread I found on this forum!
I *think* (but am not 100%) that this bit won't reset if the rung-in condition to the FSC instruction stays true. Typically, I only trigger the FSC instruction for one scan, e.g. when the operator presses "search" on the HMI, or when I receive a barcode to search for. I've never had to unlatch the .IN, and if my assumption is correct, that may be why.

In any case, as long as you've got it working, and documented it clearly, then it really doesn't matter how you got the skin off this particular cat!
 

Similar Topics

If a programmable controller controls the operation of a motor, what connects motor control to the PC? A) Line voltage B) I/O device C) Modem D)...
Replies
27
Views
6,960
I recently started getting "corrupted or low disk space" errors on all my backup panelbuilder32 files seemingly out of no where (been running ver...
Replies
2
Views
1,581
Hi, I only have the RSLogix Micro starter edition and cannot save as .SLC for the micrologix to micro800 conversion tool on CCW. I would be very...
Replies
9
Views
3,646
How can the address in the picture work in the Fuji D 0304-E and not work with the Weintek HMI how does it use the -E because in the PLC program...
Replies
10
Views
2,959
First time writing and for some reason I can not get this to connect the my Mitsubishi PLC all the parameters in the PLC and in the HMI are the...
Replies
82
Views
15,546
Back
Top Bottom