No announcement yet.

Time shifting reading on conveyor system

  • Filter
  • Time
  • Show
Clear All
new posts

  • Time shifting reading on conveyor system

    Apologies in advance, I suspect there are terms for what I'm trying to do that I don't know.
    I have a conveyor like application, with a sensor and actuator at various points. The conveyor speed varies, but there is an encoder providing total distance traveled information (direction never changes). Id like to store readings of sensors, and the position at which they were read, then have actuators act on a portion of the conveyor when the product that passed the sensor gets to the actuator. Or line up the readings from different sensors from different points so that relationships can be seen.
    I'm assuming the first step is to break the conveyor up into minimum discrete lengths. If there were only a few total places on the conveyor, I would get a new reading when the conveyor advances the minimum distance, move reading 9 to 10, 8 to 9, 7 to 8 etc and store the new reading in position one. Then the actuator can act on position 7 (assuming there are 7 distance units between sensor and actuator).
    Trouble is, I'm likely to have thousands of positions, so writing this one step at a time seems impractical. Perhaps I can use a MOVER command?
    If the values are all integers, what is a reasonable number of values to handle in such a structure? I'd like to update the system 100 times a second, but could probably live with 5-10 times a second
    Thanks in advance

  • #2
    Hi Ken,
    I believe you are looking for a shift register. Here is an example:
    This uses Factory IO to show how the shifting works for the conveyor belt, sorting.

    ACC Automation
    Connect with us on Facebook:


    • #3
      I have tried to decipher the memory of the do-more CPUs.

      Not sure how to look at it.
      Are you sure that the do-more has enough memory to support tracking thousands of datapoints (words???) 100 times per second?
      It seems that the (current) domore platform has 1.8MB that can be divided/allocated as you see fit, but you are working toward a lot of data.

      Click image for larger version  Name:	Domore-Address space.png Views:	0 Size:	135.5 KB ID:	129540


      • #4
        I suppose one important factor is, just what is "thousands"? 2,000 is "thousands" and is much easier to handle than 500,000 (which is also "thousands") note that by default, the DOMORE allocates 4096 words of V-memory, which is already a fairly significant number and it can be adjusted to be more.
        I have no idea how fast MOVER is with a large block, 100 times a second might be difficult, or maybe not.


        • #5
          Do-more supports FIFO and LIFO LOAD/UNLOAD instructions. You can have a FIFO of WORDs (easily 5000, 10000, 50000 - even 100000 if you reduce the size of some of the predefined data blocks that you won't be using). What's good is that these are implemented as "circular buffers", so the data is not "shifted" around, but the "head" and "tail" of the queues are maintained.

          You could do it the old-fashioned way with MOVER (where you are constantly shifting the 5000 elements) if that mental model makes more sense.

          Circular buffers have 1 level of indirection, but Do-more supports "arrays".

          Not sure what event you would need to FIFOLOAD. How precise? You may want to stick the FIFOLOAD in a timed base ISR to get accurate time events.

          Not sure if this is helpful or not.
          There are 10 kinds of people in this world, those who know binary, and those who do not.


          • #6
            Franji1, Can you elaborate how such a task would be done with with fifo/lifo? My first instinct was to use something like that, but I ran into two difficulties (haven't tried yet, just reading the help files). First is that the stack has a limited size (which is fine) and when it fills up, no more can be written to it (which is not, I'd want to loose the end as I keep writing in the front). The second is how do I read a deeper location in the stack? The sensor data is getting written into the stack, so the actuator would need to act on location 5,000 (just as an example). From my reading of the help file, I'd have to unload the previous 5,000 items to read it, loosing them in the process.
            Shift registers would work for actuators. They require limiting the stored data to bits (so I can store pass/fail, or bin1/bin2/bin3 if I wanted to write multiple stacks). but that's not good enough for data shifting since I need to store words instead of bits. I can see how to do that with MOVER. Just concerned about about what that will do to scan times. I've been warned that PLCs don't have the near infinite processing capabilities of computers but have never actually run into this as a physical limitation before.


            • #7
              Say you had a buffer called MyData 10,000 WORDs long.

              If the FIFO got full, you would just need to do a FIFOUNLOAD to remove the "first in" from 10,000 FIFOLOADs ago.

              So the code in an ISR running every 500microseconds (20 times a second) might look like

              FIFOLOAD MyFIFOStruct MyData V42 // where V42 you want to put in the queue, MyFIFOStruct maintains the state of the FIFO queue
              // and the next rung optionally removes the oldest entry once once the queue gets full
              STR MyFIFOStruct.Full
              FIFOUNLOAD MyFIFOStruct MyData V99 // where V99 is the "bit" bucket

              That's it. Not sure what "V42" is in your actual application (an analog value?).

              Now, to figure out where your data actually is, you have to do some MATH on MyFIFOStruct.Head or MyFIFOStruct.Tail. The .Head is the circular buffer index where the newest data is going to go in on FIFOLOAD. .Tail is the circular buffer index where the oldest data exists that would be coming out on a FIFOUNLOAD.

              You will have to watch the status to get an idea of the behavior of .Head and .Tail to do your calculations (e.g. where is the 7th newest element? it's not @ 7, it's at .Head-7, but you have to see if it goes negative due to wrap-around (add 10,000 if it is negative). I may be off by one. This is the nature of a circular buffer - you adjust the head/tail indexes vs. shifting the data in the queue, which is S-L-O-W for 10,000 elements. Circular buffers are FAST since they just increment/wrap around the .Head and .Tail. The data stays put in memory.

              To indirectly reference MyData, use array indexes, which is any V locations, so do something like
              MATH D3 "(MyFIFOStruct.Head - 7)" // using D99 as a temporary to see if we've gone negative since D is signed, but V is unsigned; we want the final "7th index" in V3
              -] D99 >= 0 [-----[MOVE D99 V3]
              -] D99 < 0 [-------[MATH V3 "D99 + 10000"]
              So then
              MyData[V3] is the value @ "index 7". But you also have to make sure MyFIFOStruct.Depth is more than 7, because the 7th element does not exist in the queue until the depth is beyond 7.

              Play with it in the Simulator to get a feel for it. Set it up for 100 DWORD elements, and push the 1970 Epoch value in DST22 or something (Data View has a display format for 1970 epoch). Push a new value once a second. It will take 100 seconds to fill up (make sure you FIFOUNLOAD when it gets full).

              Eh, I wrote it just to make sure it works (it did). It's a little different than what I described above (I used a NOT contact instead of two relationals calculating V3). Note that the "7th" value in the Data View MyData[V3] is 6 seconds behind DST22 ($LocalTime as 1970 Epoch DWORD).

              Click image for larger version

Name:	FIFOTime1.png
Views:	52
Size:	169.0 KB
ID:	129584
              There are 10 kinds of people in this world, those who know binary, and those who do not.


              • #8
                So with FIFO, .Head is the index where the next LOAD will occur, and .Tail is the index where the next UNLOAD will occur. When we FIFOUNLOAD, even though it technically does not matter, we go ahead and clear the memory location at the .Tail. So once we got full, we did a FIFOUNLOAD (from the .Tail), which was at index 1 of the block. So if you look at the Data View, MyData1 is January 1, 1970 at Midnight, which is the 1970 Epoch value for 0 (.Tail should now be 2 after executing the FIFOUNLOAD, since this is the new "oldest" entry). .Head is 1, so MyData1 is where the next FIFOLOAD value will go.

                So basically, for FIFOLOAD, the data gets added @ .Head and .Head increments but .Tail stays the same. FIFOUNLOAD will return the value @ .Tail and .Tail increments, but .Head stays the same. The data never moves, the .Head and .Tail point to the "head" and "tail" and are adjusted. This is way faster than MOVER, since scan time is critical. You could have 100,000 entries in your table, and FIFO/LIFO is super fast, just as fast as if it had 100 entries.
                There are 10 kinds of people in this world, those who know binary, and those who do not.


                • #9
                  Franji1: So many thanks, this is extremely helpful!
                  Just to be clear, I can still read any location in the stack, anytime I want, without unloading, anything correct? I just have to do some math to figure out which location I need to read.


                  • #10
                    Originally posted by Ken_M View Post
                    Franji1: So many thanks, this is extremely helpful!
                    You're welcome!

                    Just to be clear, I can still read any location in the stack, anytime I want, without unloading, anything correct? I just have to do some math to figure out which location I need to read.

                    You technically could manipulate the values in the queue also, through the same index math. You just cannot manipulate the state of the queue without using the FIFOLOAD/FIFOUNLOAD (i.e. the .Head and .Tail members). There is also a FIFORESET instruction to clear the whole thing (with an option to clear the data values also, but technically that is not necessary).
                    There are 10 kinds of people in this world, those who know binary, and those who do not.