08-20-2013 03:57 PM
I have a producer/consumer structure.In the producer, I have 2 different queus, q1 and q2 (which is a cluster of arrays since I wanted to avoid the for-loop of enquing single elements as it would slow down my main program)
Based on a certain condition, I enqueue my array of data, D1, only into one of the queues in each iteration of the producer loop.
D1 has variable length, but in the range of 5-10 elements.
In the consumer loop, I want to wait for this condition:
If all 2 queues (q1, q2) have at least 5 elements, then dequeue(these 5 elements) and place it into a 2d array (the data for each queue would be in a row - so the 2d array would be 2x5)
If not, then wait until all 2 queues have at least 5 elements.
I use Get QueueStatus to check for the condition, and since the "elements" output is an array, I index the array to get the last row(the most recent value), which results in a cluster. I then use unbundle cluster to get the array and check the size.
The problem is if the condition is not met (for example I only have 4 elements id D1), in the next iteration I want the new data to be added(enqueued) to the same array of the cluster which contains the other elements, and not to create a new array.
so basically I want to it to act the same as if I were enquing single elements into my queue.
So if D1 has size 4(iteration 1) and D2 has size 3(iteration 2), q1 should have 7 elements in a single row of the cluster, not 2 rows.
I have attached my producer/comsumer vi. There will be real time data coming in, in the form of an array.
08-20-2013 04:57 PM
This is some very strange code. It is also pretty inefficient. A better way would be to use a single queue for the consumer and create a simple message. The message would be a cluster containing a message type (string or ENUM) and an array. The producer would send a message corresponding to the channel or whatever is driving your choice to determine the row with whatever data is remaining. The consumer would get this message, immediately dequeue it and process it. It would update your 2x5 array when you have enough data from each source. In addtion, the consumer will buffer any data so you do not lose any data that had arrived earlier. Here is what the consumer would look like.
You will also notice that I have add a Stop message (not visible in the snippet above) to control when your consumer should exit.
08-21-2013 10:37 AM
Thanks!
I tried it out, and added the producer loop in it too.
But isnt the 2x5 output array supposed to have channel 0 data in row 0 and channel 1 data in row1?
I added timers in the loops to slow it down a bit but what I can see is that both rows have the same values...or perhaps I'm missing something?
I change the 0/1 condition of the producer loop manually.
08-21-2013 11:21 AM
I modified your VI a bit and included the producer loop. I also made it event driven which is much better than polling like your code. In addtion, you actually uncovered a bug in LabVIEW. I didn't execute the code before I tested. It turns out that simply forking the wire after the Initialze Array doesn't work. The compile has a bug in it which I will submit. The work around is to have two Initialize Arrays, one for each shift register. It now works as expected.
08-21-2013 11:35 AM
thanks again!
I actually just got it working by initializing the array twice!
But the event structure is much better than polling.
I just get an error when trying to run the code: the NewVal in cases 0,1,2 seems to be invalid.This is the error:
Event Data Node:Cluster is invalid or empty.
The input to this Bundle or Unbundle function is not a cluster, or is a cluster with no elements.
08-21-2013 11:42 AM
Oops! I forgot I had to add the actual event.
So I chose value changes for the arrays Real time data 0 and real time data 1...but Im not sure what to use for case 2...where it stops.
08-21-2013 12:04 PM
Actually the event I should be waiting for is when my condition variable is either "0" or "1". How do I add this to the event structure?
08-21-2013 01:31 PM
You right click on the event structure and select "Add Events Cases". Then select the control or event you want to be handled by that case. You can have a case handle multiple events as well.
And yes, you do not want to use the Value change for the arrays since an event will be generated for every element added/deleted. You could clear the corresponding array control for the channel once you queued the value. This is just a convenience feature for the user. However, I figured you would be getting the data from some other source such as HW rather than by the user.
08-21-2013 01:59 PM - edited 08-21-2013 02:00 PM
I dont quite understand what you mean by "You could clear the corresponding array control for the channel once you queued the value."
Do you mean like using a sequence structure, so after enqueing then set Real time data to 0?
But what would be the event structure value to monitor?
Actually the variable condition I am moitoring is a counter, which goes from 0-100 and resets again.and yes the data is coming in from hardware.
Thanks a lot!! It is working perfectly with the case structure butI would really like to get it working with these event structures too!
08-21-2013 03:08 PM
How will your data channels be passing the data to your producer? Do you have 100 controls/indicators on your front panel? This can be a nightmare to maintain and extend. There are more efficient ways to do this. In my example you can initialize an MxN 2D array and based on the message ID you can select the correct row and update it. This would require you to split the array and rebuild it replacing the one row. This can be done inside a in-place element structure.