Tracking Parts on Continuously Moving Conveyor(No Indexing)

mithirich

Member
Join Date
Mar 2016
Location
Ohio
Posts
5
Hi everyone. Been banging my head against a wall trying to figure out tracking on a servo driven conveyor. I already have a tracking array setup with the correct size for the number of fixtures on the conveyor. So let's say my tag is TrackingData[X] where X in this case would be the position on the conveyor. Right now X is 15 since there are 15 fixtures on the conveyor with a spacing of 40" between each fixture. So I have the data shifting pretty well as the conveyor moves using a sensor that is triggered at the start of the conveyor every time a fixture passes it. Data shifts from TrackingData[1] to TrackingData[2] and then TrackingData[2] to TrackingData[3]; it actually starts from the end so as not to overwrite data but this part works and i'm not concerned about it.

Now for the challenging part(to me). There are certain operations being carried out by robots down the line. The robots track the servo position of the conveyor so they can work on the part as it moves down the line without stopping. The problem this causes for me is that a robot may not necessarily be finishing work on a certain part in the same position on the conveyor. For example, theres a robot that torques bolts on the part in the middle of the conveyor. Once it's done doing its work, it would turn on a complete bit in the respective TrackingData position. This could happen in TrackingData[7] or TrackingData[8] depending on if the line was paused or line speed.

Anyone ever had to implement tracking for some similar application? I have the servo position for the conveyor and i know the rough count limit for each position on the array but I'm not sure how to put these together to make it work. If the line was able to index a set distance, stop and allow work to be completed before indexing again I'd be done already. But unfortunately I guess this line needs to be moving continuously. Any help would be greatly appreciated. And of course i can elaborate further if necessary.

If it helps, the robots are Fanuc robots and the servo is actually a Fanuc Power Motion servo so the counts are going straight to the robots.
 
Yes I have. Thankfully the conveyor position is being fed to the robots to modify their work or tool frames, one less thing you have to worry about and speed changes or pauses won't change how the robot functions.

The way I would approach this is to put signalling outputs in the robot programs indicating its progress through their programs. When these outputs come on, I would compare them to the conveyor position and if any of them appear to be falling behind (an output is NOT on before a pre-determined conveyor position) I would slow the conveyor or in an extreme case pause it. Its going to be a little bit of work but its what I've used in the past and it worked well. I used this method to load instrument panels in cars on assembly lines. YMMV.
 
Assuming the robot "knows" it is working on the part at X=7:

  • Have the robot's code store that X=7 somewhere when it starts working on the part
  • Have the robot's code aware either of the sensor triggered by the fixture at the start of the conveyor, or of the code that does the shift.
    • So the robot's code detect a rising edge of of those bits
  • When the robot's code sees that rising edge e.g. the shift completes, add 1 to the saved X=7 so it becomes X=8.
I don't know if this is possible, but it seems a simple solution if it is.
 
I've done something very similar to this a number of times. What I've done is create two arrays. Array #1 is an array of DINTs that is basically a pointer to Array #2 index. Array #2 is an array of UDT's (data about my widget), like a circular queue. If there are 15 possible locations then array #1 would be of size 15 and hold a DINT to where it is inside of Array #2. Array #2 can be any size as long as it is larger than the total number of locations you have. So if a robot is working on a part send the pointer value from Array #1 to the robot so you know where it is in Array #2.

This also makes indexing array #1 very quick and efficient if there is a lot of data. You have to manage the roll over of Array #2, but that is easy. You don't really care where the part is in Array #2 because it is circular. For an added benefit, have one of the members in your UDT point back to the index in Array #1; then you can do some neat stuff.
 
Assuming the robot "knows" it is working on the part at X=7:

  • Have the robot's code store that X=7 somewhere when it starts working on the part
  • Have the robot's code aware either of the sensor triggered by the fixture at the start of the conveyor, or of the code that does the shift.
    • So the robot's code detect a rising edge of of those bits
  • When the robot's code sees that rising edge e.g. the shift completes, add 1 to the saved X=7 so it becomes X=8.
I don't know if this is possible, but it seems a simple solution if it is.
This is kind of the road I've started going down this morning. Seems like it should work. Whenever the fixture sensor is triggered, I have the PLC sending X to the robot in a register I call the "start register". When Robot starts a cycle, it looks at this "start register" and moves it to another register I call the "work register". This work register gets incremented by 1 every time the fixture sensor is triggered. Then at the end of the robot cycle, I have the PLC turn on the correct complete bits based on what number is in the "work register". So if "work register" is 9 then all the fixture_9 complete bits would turn on.

The "start register" would be 8 at this point if there's a part in fixture 8 that doesn't have its complete bits on. The robot would start a new cycle again and move that 8 into the "work register".

I think this should work. Still kind of writing all the logic. Thanks for the suggestion, this definitely seems like the simplest way to go about it. I'm a little concerned about timing between everything and the off chance data gets put in the wrong fixture in the middle of a transition of the trigger sensor. But i'll cross that bridge when i get to it.
 
I've done something very similar to this a number of times. What I've done is create two arrays. Array #1 is an array of DINTs that is basically a pointer to Array #2 index. Array #2 is an array of UDT's (data about my widget), like a circular queue. If there are 15 possible locations then array #1 would be of size 15 and hold a DINT to where it is inside of Array #2. Array #2 can be any size as long as it is larger than the total number of locations you have. So if a robot is working on a part send the pointer value from Array #1 to the robot so you know where it is in Array #2.

This also makes indexing array #1 very quick and efficient if there is a lot of data. You have to manage the roll over of Array #2, but that is easy. You don't really care where the part is in Array #2 because it is circular. For an added benefit, have one of the members in your UDT point back to the index in Array #1; then you can do some neat stuff.
i've done this in the past on rotary dial table indexer and it worked great. The problem i had with this is the pointer incrementing logic gets to be tedious the more stations you have. So in the past at 6 stations it wasn't too bad but at 15 stations I decided to try and do it with just COP instrctions and shifting the data instead of using a pointer. I also was unsure about how this would work on a continuously indexing conveyor since this is new to me. I really like how efficient using pointers is because going backwards and having the data in the right spot becomes trivial; no need to write code to shift everything backwards. If what i'm trying to do doesn't work out I might just start from scratch and use pointers. The other thing I have to be careful about is to not make logic too hard to understand, and I've had some complaints in the past from maintenance when using indirect addressing like i would be doing with these pointers.
 
Incrementing the pointer array is easy in structured text with a FOR loop.
So I'm revisiting this and thinking about using a circular queue like you mentioned. I'm not quite understanding how you are using array #1 inside array #2. For example, lets say the pointer array is Tracking_Pointer[X] and the actual data array is Conveyor_Tracking[X]. Would you reference the data in an array as:

Conveyor_Tracking[Tracking_Pointer[X]]? I tried this in logix and it doesn't like it(invalid array subscript specifier). Does this just need to be individual DINTs not in an array to work?

I also just discovered you can do addition with indirect addressing but it will cause a major fault when trying to do tracking since eventually it will try and reference a negative array(if there's a way for this to work someone let me know). If there's a way to do tracking with this method somehow that would be much simpler. For example, lets use the same tags from above except Tracking_Pointer is now just a DINT instead of an array:

Conveyor_Tracking[Tracking_Pointer] is valid
Conveyor_Tracking[Tracking_Pointer+1] is also valid

The problem is if Tracking_Pointer becomes negative then PLC goes crash and there's not really a way to handle this that I can see.

So if you can shed light on how you've done this before or better have sample code i can reference to understand it better I would greatly appreciate it. Thanks!
 
For the invalid array subscript I assign a variable. So in your case.
for X := 1 to 20 do
Y := Tracking_Pointer[X];
Converyor_Tracking[Y] := (insert your logic here)
end_for;
You do have to do some error proofing for negative or too large of indexes. Use the first scan bit to make sure the index valid. I also tend to let my circular array be larger than I actually need. So if I need 500 elements I'll make an array that is 510 and not use the last couple or the first zero.
 
Ohhh i see. That makes sense. And then just run your for loop every time you need to increment your pointer right?
 

Similar Topics

As a training exercise I am learning to alternate parts while tracking them in VersaPro. I am new to this forum and new to VersaPro.I will be...
Replies
7
Views
3,548
I'm currently using a PLC to get results from a tester, and mark the part if its bad like 34 parts down the line. This is working great, but I...
Replies
26
Views
14,420
Recently, I was asked to track product moving thru our machines, and reject them based on an existing input signal. This didn't seem horribly hard...
Replies
4
Views
12,750
I am attempting to reject a bottle If the label fails. The rejection works fine at normal line speed but at low speed the rejector fires (air...
Replies
35
Views
1,150
Is it possible to gather OPC data through a 1783-NATR? Searching around, it sounds like OPC data might be blocked by any NAT... Is there any work...
Replies
2
Views
248
Back
Top Bottom