FIFO with BOOLs

JLand

Member
Join Date
Apr 2019
Location
Madison, Wisconsin
Posts
114
Hi all,

Stupid question, is there a good way to get a FIFO where the FIFO array is an array of BOOLs (BOOL[32])?

I have a camera system that scans containers. The way I would like this system to work, is if the camera detects a pass condition it FFLs a 0 into the array, and if it detects a reject condition it FFLs a 1 into the BOOL array. A photoeye downstream by the reject pusher FFUs this array, triggering if it sees a high bit.

I could just set up a DINT[32], but that's not an insignificant amount of data just for what should be pretty simple. I get that a BOOL array is not listed as a supported datatype for the source or array in FFL/FFU documentation, but maybe I am missing something or maybe there's an easy way to duplicate FIFO functionality with other instructions.

This is on a a CompactLogix L27ERM version 28.12.

Thanks in advance.
 
Last edited:
I should say, I tried using a BSL and a DINT[1] (frustrating that BSL can't handle a DINT datatype, it has to be an array of size 1) and a CTU/CTD to track position, but that's just getting messy.
 
You should be able to use the BSL instruction without needing a counter to track anything. What functionality does the FFL have that the BSL is lacking?
 
You should be able to use the BSL instruction without needing a counter to track anything. What functionality does the FFL have that the BSL is lacking?

We considered this, but startup could cause issues. If you assume there is always 10 containers between the camera and the discharge photoeye (necessary if you don't use a counter to track how many in the system) and you get a reject on, for example, the 2nd container to go through the system, it'll incorrectly reject the 12th instead of the 2nd, because the system will think that there are 10 container ahead of this. You need to track how many constrainers are in the system. I also tried using a BSL and BSR together, but that ends up being a FILO.
 
Use your count value as an indirect reference to the bit number in the BSL array. That way if there are only 2 containers in the system you would be looking at the second bit.
BSL_Array.[Count]
 
Use your count value as an indirect reference to the bit number in the BSL array. That way if there are only 2 containers in the system you would be looking at the second bit.
BSL_Array.[Count]

Like I said in the initial post, I considered that but at that point it really isn't any better than just using a bunch of DINTs in a FIFO from a memory and a long-term support standpoint. I'll just use a FIFO and DINTs then.
 
The fundamental objection to BSL seems to be that the number of "containers" (bits) in its "FIFO" is constant (control_struct.LENGTH), so


  • the BSL synchronously
    • pushes a bit (1 or 0) onto the "FIFO"
    • AND
    • pops a bit off of the "FIFO;"
  • BUT
  • FFL and FFU can operate asynchronously, FFL-ing (pushing) when a container enters the system by triggering the upstream pass/reject camera, and FFU-ing (popping) when a container leaves the system by triggering the downstream photoeye.
  • Stated another way, the BSL model assumes there are some fixed number (control_struct.LENGTH) of containers in the system at all time,
    • but the line being modeled may actually have no containers in the system at startup.
    • and the number of containers between the sensors is variable
So basically a the fixed-length "FIFO" queue of the BSL is a poorer model for the process than the variable-length FIFO queue.


Is that about right?


It would of course be possible to get around this with BSL e.g.

  • Start a counter at 0 (i.e. assume no containers) at startup
  • CTU for every container that enters the system
  • CTD for every container thgnore control_s
  • Ignore ctl_struct.UL and instead use the post-CTD counter.ACCUM as the index of the bit to test for pass/reject.
but I am not sure that is worth it, when the FFL/FFU already has all of that built in, especially being able to independently detect rising edges in both FFL and FFU on the same (or successive) scans; that is something I think would be much more difficult to do with CTU/CTD since they must use the same counter struct.*


* Whoops, there is a CTUD instruction that can handle that, but it is still more work than what is built in with FFL/FFU.
 
Are the containers at fixed intervals, e.g. in between flights of a conveyor? If so you can just do your BSL on each "space" regardless of whether a container is there or not - zero equals no container in the space or good container in the space (no reject), and one equals a faulty container in the space (reject).


If the spacing between them is variable that obviously doesn't work and yes, your best bet is probably the FIFO. You could always use SINTs instead of DINTs to cut down on memory usage.
 
Like I said in the initial post, I considered that but at that point it really isn't any better than just using a bunch of DINTs in a FIFO from a memory and a long-term support standpoint. I'll just use a FIFO and DINTs then.

You also said in your initial post.

.....
I could just set up a DINT[32], but that's not an insignificant amount of data
.....

I thought you were trying to limit the amount of memory used?
Using a BSL you can get away with a single Dint and a single Int.
xyz.PNG
 
JLand, what are you planning to do to that poor L27 that 128 bytes is a concern??

The point that drbitboy made about the basic model type is important. A BSL works well in a case where you have a known increment of the model between the insertion of the state and the action of the state and the increment is triggered based on the "motion" of the item through the model. In this case there is no such relationship. The trigger of the model is item detections on either end of the path. Conceptually there may be only one item in the model from beginning to end of the cycle. A FIFO or rotary queue with a head and tail pointer are more appropriate here. Using a BSL would be trying to jam a square peg into a round hole.

Keith
 
That’s not difficult a all it reminds me on one of my first projects tracking bags on a conveyor from a bagging machine. 4 zones up to 4 bags per zone each bag was timed in each zone if any bag didn’t make through the zone on time, sound alarm and stop the conveyor
In your case
BSL is the best way to handle it
Use the container itself to index the BSL
If the camera detects a bas container set the input bit for the BSL
Just after the camera set up cross beam photo sensor. When this photo sensor sees the leading edge of the container it advances the index on the BSL and triggers an up counter as the container passes the photo sensor it clears the BSL input bit so it is ready for the next container.
The up / down counter tracks the number of containers in on conveyor between the camera and the reject point it will also give you number of the bit to look at for a reject tripper

At the reject point place another cross beam photo sensor as a container
When the container at the reject point detects a container the program looks t the bit pointed to by the counter .ACC if that bit is 1 (True) it trips the reject when the tripper photo sensor clears it riggers the down counter
The counter will always give you the number of containers on the conveyor and that would be the bit index you look at in BOOL array.
The only down side is that you cannot remove or add containers between the 2 photo sensors

Good luck let us know how you make out
 
If memory were an issue (unlikely) and/or I chose to do this with bits (likely;)), I would use a DINT as a circular buffer with two counters:

  1. next_test would be the bit position of the next bit to be written as a result of the next upstream camera test result event
  2. next_pass_reject would be the bit position to be read at the next photoeye detection event
Both counters and the DINT would start at 0 and assume no containers between the sensors*. Each counter would be incremented after its corresponding event + bit-read or -write. When either counter hits 32, it is reset to 0 e.g. an unconditional [AND counter 15] would do the trick.


The number of containers in the systems could be calculated via

  • [SUB next_test next_pass_reject container_count]
  • [AND container_count 15 container_count]
There would also be code to ensure next_test would never increment to the same value as next_pass_reject, with perhaps an alarm; if 32 was too small then use a DINT[2] array and the mask of 15 becomes 63, or DINT[4] and the mask becomes 127, etc.; I am pretty sure that the notation dint_array[0].[next_test] will work as expected for values of next_test beyond 31.


There might be some other ancillary bells and whistles, but that is the basic idea.



But again, this is basically no different than coding a FIFO/FFL/FFU (next_test is 0 and next_pass_reject is control_struct.POS-1), so either saving a few bits or proving it can be done would be the only rational motivations I can think of at present.


* requiring a procedure for operators to make a visual check and clearing any containers present before startup, or initializing next_pass_reject the count and putting -1 into the DINT(s).
 
@drbitboy
I don't understand the "AND 15". I actually never use counters, I prefer to add 1 or sub 1. How does AND 15 or and 63 reset the counter?
Is 15 Decimal or Hex?

.....
When either counter hits 32, it is reset to 0 e.g. an unconditional [AND counter 15] would do the trick.

There would also be code to ensure next_test would never increment to the same value as next_pass_reject, with perhaps an alarm; if 32 was too small then use a DINT[2] array and the mask of 15 becomes 63, or DINT[4] and the mask becomes 127, etc.; I am pretty sure that the notation dint_array[0].[next_test] will work as expected for values of next_test beyond 31.
 
[Whoops, that should be ANDing with 31 for a 32-bit buffer.]



@drbitboy
I don't understand the "AND 15". I actually never use counters, I prefer to add 1 or sub 1. How does AND 15 or and 63 reset the counter?
Is 15 Decimal or Hex?


A [bit-wise AND with 15 operation] is equivalent to [resetting a value to 0 when that value reaches 16], and also equivalent to a [MODULO 16 operation]; not all PLCs have a MOD instruction.


Bit-wise ANDing with 63 is equivalent to resetting the value to 0 when it reaches 64.


So all the rungs below do the same thing i.e.

  • increment an indirect reference value (indrf) into a circular buffer with 16 bits, and
  • reset indrf when it is incremented past 15 (15 is the indirect reference of the 16th bit):



Code:
      ______________
--+--[ADD           ]------------------------+---
  |  [SourceA  indrf]                        |
  |  [SourceB      1]                        |
  |  [Dest     indrf]                        |
  |   --------------                         |
  |   ______________     _____________       |
  +--[GEQ           ]---[MOV          ]------+
     [SourceA  indrf]   [Source      0]
     [SourceB     16]   [Dest    indrf]
      --------------     -------------
Code:
      ______________
--+--[ADD           ]------+---
  |  [SourceA  indrf]      |
  |  [SourceB      1]      |
  |  [Dest     indrf]      |
  |   --------------       |
  |   ______________       |
  +--[MOD           ]------+
     [SourceA  indrf]
     [SourceB     16]
     [Dest     indrf]
      --------------
Code:
      ______________
--+--[ADD           ]------+---
  |  [SourceA  indrf]      |
  |  [SourceB      1]      |
  |  [Dest     indrf]      |
  |   --------------       |
  |   ______________       |
  +--[AND           ]------+
     [SourceA  indrf]
     [SourceB     15]
     [Dest     indrf]
      --------------
N.B. replace 16 and 15 with 64 and 63, respectively to for the counter into a circular buffer with 64 bits.

N.B. the one-shot trigger for the increment is not shown, but would be the same on all rungs
 

Similar Topics

I am not sure if this is possible but if there is a way, you guys would be the ones to know. I am currently working on a project where we are...
Replies
7
Views
215
Hello all, I'm using a 5069-L330ER in a project and I need to essentially capture some data that will be shown as a trend on a screen. The data...
Replies
9
Views
958
Hello! I have a network of conveyors bringing raw product to 4 machines. A sensor in the hopper of each machine calls for more product. I'm...
Replies
15
Views
5,853
Hello everyone, has anyone out there ever made a FIFO using an FFL and FFU instructions on a Micro800? I have tried setting it up just as I would...
Replies
9
Views
3,110
I have a bottle capper that is using an encoder and FIFO logic to track the free standing bottles passing through a bottle capper. I have checked...
Replies
31
Views
11,661
Back
Top Bottom