Eric Nelson
Lifetime Supporting Member + Moderator
I often have applications where I need to inspect products on a conveyor belt, and reject the failed ones downstream. Seems simple enough, but I still run into issues...
The inspection system consists of products moving down a conveyor belt. I have a sensor to detect the product, a camera to do the inspection, and a reject station (usually just an air blast). Basically like this:
>>> DETECT >>>>>>> INSPECT >>>>>>> REJECT >>>
I have an encoder on the conveyor to track the products with 0.01" resolution (100 counts per inch). Product enters at random. Therefore, the number of products between the sensor, camera, and reject varies (but there is always a gap between products, and products don't slip on the conveyor).
The product detect sensor is considered the zero location, and I can preset the location of the camera (N10:0) and reject station (N10:1). When a product is detected, I increment two 'queue' pointers which I call 'Camera' and 'Reject'. The 'Camera' queue tracks the product all the way to the reject station (accumulating the encoder value for each product), while the 'reject' queue only tracks the product to the camera location (I should probably swap their names... ). This program has the capacity for 16 products between the detect and reject, and 8 products between the detect and camera. When a product reaches the camera location, I trigger the camera to inspect the product, and decrement the 'reject' queue. When the product reaches the reject station (and has failed), I reject that product, shift the camera accumulators, and decrement the 'Camera' queue.
The way I keep track of failed inspections is with individual bits within a 16-bit shift register (#B3:2). I determine which product is in front of the camera by looking at the current value of the 'Camera' and 'Reject' queues (Rungs 58 thru 73 in the Camera subroutine), and then SET the appropriate bit when the inspection passes. The BSL occurs each time I reject.
In my opinion (and probably many of yours), this program is WAY too complicated. It 'works' for the most part, but I'm sure there is a MUCH better approach. I have had to add patches to fix some issues. For example, if the conveyor is not moving and the detect sensor is triggered more than once, the queue gets incremented, which causes identical values to get loaded into multiple accumulator registers. My 'patch' was to prevent more than one trigger when the conveyor is stationary (rungs at the end of the Main subroutine).
The biggest issue I have not solved yet is my 'Camera' queue pointer not decrementing all the way back to zero when all products have exited. It will work for a while, but then end up with a '1' in it with the conveyor empty. Run for a while longer, and it now has a '2'. I re-zero these on the first scan as a temporary fix when it gets screwed up, but I need to figure out why it gets screwed up in the first place! Of course, this occurs much more often on the faster (~200 parts per minute) systems.
I realize the attached program is difficult to follow. I have trouble wrapping my head around it too. I'm sure I have made it way too convoluted, but I don't see any other approach that will work (for me). It's probably better to simply ask how YOU would tackle this, rather than trying to figure out what's wrong with my program.
So, how would YOU program this application? Note: I need to be able to add multiple cameras at different locations, but still with a single reject station (I currently have one system with 4 cameras). Also, I mainly use ML1100 and 1400s for these systems.
-Eric
The inspection system consists of products moving down a conveyor belt. I have a sensor to detect the product, a camera to do the inspection, and a reject station (usually just an air blast). Basically like this:
>>> DETECT >>>>>>> INSPECT >>>>>>> REJECT >>>
I have an encoder on the conveyor to track the products with 0.01" resolution (100 counts per inch). Product enters at random. Therefore, the number of products between the sensor, camera, and reject varies (but there is always a gap between products, and products don't slip on the conveyor).
The product detect sensor is considered the zero location, and I can preset the location of the camera (N10:0) and reject station (N10:1). When a product is detected, I increment two 'queue' pointers which I call 'Camera' and 'Reject'. The 'Camera' queue tracks the product all the way to the reject station (accumulating the encoder value for each product), while the 'reject' queue only tracks the product to the camera location (I should probably swap their names... ). This program has the capacity for 16 products between the detect and reject, and 8 products between the detect and camera. When a product reaches the camera location, I trigger the camera to inspect the product, and decrement the 'reject' queue. When the product reaches the reject station (and has failed), I reject that product, shift the camera accumulators, and decrement the 'Camera' queue.
The way I keep track of failed inspections is with individual bits within a 16-bit shift register (#B3:2). I determine which product is in front of the camera by looking at the current value of the 'Camera' and 'Reject' queues (Rungs 58 thru 73 in the Camera subroutine), and then SET the appropriate bit when the inspection passes. The BSL occurs each time I reject.
In my opinion (and probably many of yours), this program is WAY too complicated. It 'works' for the most part, but I'm sure there is a MUCH better approach. I have had to add patches to fix some issues. For example, if the conveyor is not moving and the detect sensor is triggered more than once, the queue gets incremented, which causes identical values to get loaded into multiple accumulator registers. My 'patch' was to prevent more than one trigger when the conveyor is stationary (rungs at the end of the Main subroutine).
The biggest issue I have not solved yet is my 'Camera' queue pointer not decrementing all the way back to zero when all products have exited. It will work for a while, but then end up with a '1' in it with the conveyor empty. Run for a while longer, and it now has a '2'. I re-zero these on the first scan as a temporary fix when it gets screwed up, but I need to figure out why it gets screwed up in the first place! Of course, this occurs much more often on the faster (~200 parts per minute) systems.
I realize the attached program is difficult to follow. I have trouble wrapping my head around it too. I'm sure I have made it way too convoluted, but I don't see any other approach that will work (for me). It's probably better to simply ask how YOU would tackle this, rather than trying to figure out what's wrong with my program.
So, how would YOU program this application? Note: I need to be able to add multiple cameras at different locations, but still with a single reject station (I currently have one system with 4 cameras). Also, I mainly use ML1100 and 1400s for these systems.
-Eric