12-14-2010 02:00 PM - edited 12-14-2010 02:03 PM
If you would make use of the light bulb (Highlite execution), you would learn what is happening that makes your vi not work properly. After clicking on stop, the enqueue happens, then the dequeue happens and the next bottom loop iteration goes to the stop state. However, before the stop state can execute, it is waiting for input from the dequeue. This is where it hangs because you don't enqueue twice. To fix this, put the dequeue inside the read case. You don't need it anywhere else. Then your stop will execute because it isn't waiting for anything else. You will have to fix the Init state. Just make the next state read and delete the stop enum and selector. Then the vi will work perfectly.
Don't forget Darrin's suggestion. Add and error wire coming from the bottom loop and going to merge errors. Make the top loop error out go to merge errors. Wire the output of merge errors to the destroy queue function. This way, the queue won't get destroyed until both loops finish.
12-14-2010 02:44 PM
Hi,
Now the program works fine 😄
But I still have some doubts! What can I do if the stop don't be a part of the cluster in the front panel? And if I have more than one case to "read" the queue?
Thanks for all your help
Sílvia
12-14-2010 03:45 PM
You would need to redo your architecture. Instead of deciding which is the next state in the bottom loop, you should do this in the top loop. For instance, if the cluster changes, pass the read state via the queue to the bottom loop. Your cluster would contain a command (next state enum) and data. I think Ravens Fan had already suggested this. It is a great idea and it works fine. Easy to maintain and to add on.
If you take this approach, you can remove the stop boolean from the cluster. When stop is pressed, an event would put "Stop" as the next state on to the queue. In the bottom loop, you dequeue and extract the command element (next state enum) out and feed it into the case structure. The stop case would execute and everything would stop. If the numeric is changed, an event case would enqueue the read command with the new data. The bottom loop would then execute the read case. Do you get the idea?
12-15-2010 05:53 AM
Hi,
I think I understand, and I will try go through that way.
Just one more doubt, how can I do if I want to pass through two cases when a event occurred?
Sílvia
12-15-2010 08:14 AM
Hi,
I think I got it, is something like these?
Thanks for all your help,
Sílvia
12-15-2010 11:29 AM
Hi,
I have another problem with queues!
Inside the state machine I have two while loops running in parallel, and because of this, the dequeue that was before the case don't run when the program begin the inside loop.
I try to dequeue another time inside that loop, but as the queue is empty, the program don't run properly. What should I do to resolve this? Should I use two queues?
Thanks for all your help,
Sílvia
12-15-2010 12:49 PM
You've got two problems.
First you have while loops inside the Acquire case that have a False constant wired to the stop boolean. You've created infinite loops that will never stop unless you press LabVIEW's abort button.
The second problem is why did you put another dequeue element inside the while loop? If you only put one element in the queue, only the first main dequeue element gets it. The element inside the loop won't get it. Now the earlier message showed a good way of queueing up two elements, so on the surface one element could show up at the main dequeue element, and the 2nd element could show up at the inner dequeue element, but suppose the queue gets out of synch like if another element gets inject in between?
Whether you use another queue or not depends on what you are ultimately trying to do and how you want to architect this. It seems like you are starting to get an idea of how to use queues, but still are struggling at the edges because you haven't clearly defined on paper how you want this program to run.
Remember that when working with queued state machines, the state machine loop that contains the dequeue element can put messages back in the queue to itself. So if you have something that needs to run continuously such as a wait state that is just waiting for something to happen like a temperature to reach some set point, the wait state can enqueue another wait state so that it executes again. If the temperature is reached, then it can enqueue whatever the next state would be. This allows the consumer loop to function itself as a state machine, but also allow it to receive other messages from the producer loop as needed for things like "shutdown the program".
12-15-2010 02:18 PM
Hi,
Regarding the first problem, I know that I created infinite loops, I just put the program like that to test the queues. That will be another big problem! I'm thinking use another stop button, but I don't know how to stop the two whiles without using local variables.
Regarding the queue problem, I think the big problem is I have while loops inside the state machine, and because of this, when the program is acquiring the signals, it don't read the dequeue element.
Sorry but my English is not so good, and I don't understand what you meant with the last paragraph.
I attach the program, for you understand better what's happening.
Thanks,
Sílvia
12-15-2010 02:42 PM
Silvia,
Here is an example of what Ravens Fan was talking about. State machines almost always need only the outer loop. By repeating the Enqueue operation inside the Acquire state the next state will be Acquire (again)! If you wish to go to a different state on an error or after a specified number of acquisitions, you can easily modify the data enqueued.
Lynn
12-16-2010 08:01 AM - edited 12-16-2010 08:02 AM
Also see the JKI State Machine for a nice example of a queued state machine. It demonstrates how you can run macros with queued-up states, handle errors, etc
http://jkisoft.com/state-machine/download/