02-23-2010 11:28 AM
Ok, Now I get your point. But even with the same program, when I use elapsed time vi, it looks like it works as I want it to. But I have accuracy problems with it. Specifically, when I give 50ms for elapsed time, it takes close to 140ms instead. Sometimes it takes about 90ms.
Do you think this accuracy can be improved if I seperated my analysis from the DAQ code as you suggested? I will anyways give it a try when I get a chance. Let me know what you think.
02-23-2010 12:11 PM
02-23-2010 12:20 PM
02-23-2010 01:08 PM
It may be due to the misuse/abuse of your local variables causing a race condition, namely the one called X-Y. The decision on whether to stop the loop occurs with either the stop button (which is probably read very early in the loop iteration, or when X-Y < 0. This decision is also made early in the loop because the value in that variable is already available. But in reality, you don't assign a value to that indicator until much later in the loop after your mathlab code runs where the value gets incremented or decremented by way of local variables.
Instead of using a local variable, you should be using a shift register to store the value of X-Y from iteration. And the comparison to stop the loop should probably be made after the value is updated after the mathlab code has analyzed the data.
02-23-2010 01:18 PM
I must admit I did not understand your post completely. But, I think the bottom line is the use of local variable might be causing the delay to be more than what I want (140s V/S 50ms). The possible remedy can be to implement the same logic but to use shift registers instead of local variables. I will try this and let you know.
Please comment if I got you wrong.
02-27-2010 04:03 PM
Now it is making a more sense to me. I will looked at the stuff you asked me to. Then, I will modify my present code according to two paraller loop structure.
Thanks, jyang72211
03-31-2010 09:39 PM
Hello,
As discussed earlier, I had my whole VI in serial fashion but since it
was not efficient way, I decided to approach my problem using producer
consumer loop. To check the basic functionality of this framework, I
have cut down on most of the computation stuff in my producer and
consumer loops to keep things simple.
My first objective was to see if all the loops in the VI stop when I
press the stop button in my producer loop. I believe there is lots of
documentation about stopping parallel loops in LabVIEW. I will summarize
the most relevant methods for my need.
1) Using local variable. But online I found a lot of discouragement
for using this method. I tried using this but I get the error 1122 (Refnum
became invalid while node waited for it). I think I understand
the error but not sure how to overcome it.
2) Connect the error terminal in the consumer loop to the stop
button. I tried this and I get the same error 1122.
3) I tried
one more thing. This is saved as the file attached. In my final VI, I
will be passing boolean values using queues. So, I just made a array of
boolean to verify if the communication takes place properly. In addition
to the hard coded boolean values, I connected the stopped output of the
DAQ assistant to the queue and used this value in the consumer loops to
stop the respective loops.
Using this approach, I am able to stop the producer loop and one
consumer loop (any one of the two; randomly). The other consumer loops
does not stopped. I conclude this based on the iteration value indicator
on the front panel. I tried playing around some more but did not help.
Can you help me with this?
Thank you,
03-31-2010 10:21 PM - edited 03-31-2010 10:23 PM
Don't post a VI where the front panel is enlarged to such ridiculous dimensions you can't see any of the borders or the title bar!!!! I had to use some work arounds to be able to adjust the size of the window to make it manageable.
You have some architecture problems. You have one loop enqueuing data and two loops dequeueing data. When you put in your piece of data designed to stop the loops, one consumer loop or the other will get it. It just depends which loop happens to grab it first. The other consumer loop will just sit there waiting for the next element in the queue which will never come. What happens is the producer loop ends and kills the queue. That causes the waiting consumer loop to stop waiting at the dequeue and throw the 1122 error. But in your posted VI, this doesn't stop the loop which continues to run and continually throw an error for an invalid queue reference.
The 1122 is not a bad error if you do use the presence of an error to stop the consumer loops. You could even look for that particular error and throw it out.
I'm not sure why you are using a 1:2 producer to consumer loop ratio. Do you just want to have two loops to share the workload of whatever the producer provides?
Using a local variable in a careful manner to stop the two consumer loops is not a bad thing. You could also have your producer loop enqueue the stop element twice so that the second loop is able to get it. I would not kill the queue until all the loops have stopped.
I myself would not use a data element where it is a 3-element boolean array where the 3rd boolean has a special meaning (stop loop) from the other two. I tend use us a cluster where one element is an enum that gives a specific command (initialize, stop loop, analyze data) and the other element is the data type I want, or a variant if I need to be able to pass a variety of datatypes through the queue.
04-01-2010 11:13 AM - edited 04-01-2010 11:15 AM
Hey Thanks for your reply. I am sorry for the inconvinence caused to you.
As far as the front panel goes, I face the same problem everytime. I make my VI in one computer and then open in the other one, all my front panel is messed up. Please indicate any documentation to have a VI same on all the machines irrespective of the screen resolution. I found one option in the VI properties about resizing the front panel if the screen resolution changes, but it did not work for me.
In response to your 2nd Para, most of the part makes sense to me. But I would like to clarify in the VI posted, I do not get the 1122 error, the other consumer loops keeps on going on and never stops. Please correct if I interpreted you wrong.
Yes, I thought of using the 1122 error for stopping the loop. But, I believe there would be some other elegant way of doing it.
The reason for using the 1:2 producer to consumer loop ratio is to keep the data acquisition independent of the elapsed time vi. Before working on this architecture, I had a serial architecture (please refer to my initial post in this thread for more details) where in a single while loop I was acquiring data, calculating peaks, using the peak times to calculate the rate and based on the rate values perform 3-4 conditions. For some of the conditions I had to monitor the stability of rates for 50ms-250ms (depending on condition), I used the elapsed wait vi. If the conditions did not change within those 50-250ms, I would shut down the VI. I wanted to VI to be very accurate (within 20-30 ms) and I asked people for feedback about it. The suggestion I got was to use the producer consumer loop for better timing. Since the 2 conditions have a elapsed time VI which should not interfere with the data acquisition, I kept them in different loops. Thats how I got this 1:2 ratio. Do you think using this way wont help me achieve better timing? Also, I wanted to use wait vi instead of elapsed time just because it is not an express vi.
For local variable approach, I just connected the local variables of the stop button in the producer loop to the stop conditions in the 2 consumer loops. I also changed the mechanical action of the stop button. But it did not work. I got the error 1122. I think I wil try your idea about using the stop element twice. If this does not work, I will stop the loops if I get the error 1122.
The reason I use the 3-element boolean array because it was very simple to implement it. Do you think it was logically incorrect or something that labview does not allow? I just changed slightly the way producer consumer loops are used. Do you think using my approach is less robust.
04-01-2010 12:34 PM
Go to File/VI properties. Go to Window size. There is a checkbox there for Maintain Window proportions. Yours is check. Uncheck it. I have yet to see a good reason to ever have that checked. That is what is causing your window to resize itself between different computers. Design your front panel to work with the lowest resolution screen you expect and it will look just fine on higher resolution screens with that unchecked. Resize your window to fit on the screen and save the VI.
You basically understood paragraph 2 correctly. In your current VI, the dequeue element is throwing an 1122 error, you just don't see it because the error wire going to the loop tunnel is handling it. If you deleted that wire, it would pop up an error message every iteration. If you put a probe or indicator on that wire now, you will see the error message there.
Producer/consumer is a good way to pass off processing and allow your producer loop to run faster. I just don't know if you are intending to use the two consumer loops the way you are now. If the producer loop queues up A, B, C, D, E, F, .... One consumer loop will handle elements A, C, E, ..., the other B, D, F. But actually that not guaranteed, they could be handled differently. Each loop will grab whatever is next in the queue when it gets to it. So if the first loop runs faster, it may get A, C, D, F while the other loop gets B, E.
If you want both loops to get element A, and both loops to get element B, and so on. You need to create two queues where the producer can enqueue elements in both queues, and each consumer dequeues from its own dedicated queue.
As for the data element itself, use whatever works for you. I myself don't like to bury data in a structure with somewhat unrelated data. While a user won't care as long as the program works, a future programmer might not pick up on the fact that boolean array element 2 means stop loops, while elements 0 and 1 mean something completely different.