LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Queues within an event structure...

I am in the middle of converting old, messy code into something more manageable and have come up with a few questions about a particular section.

  1. Do I need to put the queues and their error functions into shift registers as I have done at the moment?
  2. I am currently running the queues through every event structure instead of using the 'Default if unwired' setting. Is this unnecessary, despite me releasing the queues after the 'producer loop'?
  3. Do I need a blank 'Timeout' event in the event structure or is that also unnecessary?
  4. I have shown one of my consumer loops in the picture. It is used to write arrays of data to three graphs whenever the occurrence is set in any one of the events in the event structure. Is this the correct implementation of occurrences and/or is there a better way of doing this?
  5. If, for some reason (theoretically), the 'Test' button is pressed before the graphs have finished updating, does this cause any problems in the consumer loop as it reads the queues or is this not a problem?
  6. Bearing in mind that this is far from finished and that I've only included part of the code so far, is there anything immediately obvious where i may be going down the 'wrong' route?

 

Thank you for your time. These are mostly little questions that I just want to clear up.

James

P.S. I apologise if these questions appear trivial.
Message Edited by James Mamakos on 06-24-2009 06:26 PM


Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 1 of 30
(4,331 Views)

I would recommend NOT using the shift register on the error cluster.  Others may feel differently.  But you don't want an odd error being carried into the next iteration and preventing the next iteration from executing.

 

 

Why are you previewing the queue in the consumer loop?  Rather than flushing the queue and enqueuing new valuea in the producer loop, then setting an occurrence, to signal the consumer loop.  Just Dequeue in the consumer loop.  It will wait for the elements there.  No extra signalling needed with the occurrence functions.

 

Rather than create 3 separate queues of identical datatypes, enqueuing 3 times and dequeuing 3 times, I would make an array of that datatype.  Build the 3 pieces of data into a single array and enqueue into a single enqueue.  Use a single dequeue in the consumer loop and index the array as necessary.

 

How does your consumer loop stop?  With a false wired to the stop terminal, it will run forever.  Try wiring the error cluster to the stop terminal.  When the queue gets destroyed, the error will cause the consumer loop to stop.

0 Kudos
Message 2 of 30
(4,320 Views)

James,

 

1. You do not need shift registers for the queue references as they are not changed within any of the event cases.  You may want the errors on shift registers.   There was quite a discussion on errors and shift registers a while back.

2. It is necessary.  A default queue reference will not work. 

3. If the timeout event is empty, it is not needed.  Delete it.

4. Seems OK

5. Not sure.  Notifiers have changed in the newer versions and I rarely use them.

6. Generally looks good.  The array size is not needed in the event loop.  You could wire to the N terminal inside the for loop and get the same value. ALso, do not run the wire behind the sequence (or anything else).  I would get rid of the stacked sequence and use dataflow if at all possible. 

 

Lynn 

0 Kudos
Message 3 of 30
(4,318 Views)

1. No, queue looks like a control reference

2. You doesnt need wire every structure, refer 1

3. A timeout is unnecessary

4. You may use "elements in queue" with the function "get queue status"

 

5. Other events only execute after the current event finish.

 

6. How you do to stop the lower while loop. You must put a wait time inside lower while loop.

0 Kudos
Message 4 of 30
(4,314 Views)

I have updated my VI taking into account your suggestions...

 

The user can now still interact with the FP whilst the test is running (though some controls will have to be temporarily disabled to avoid conflicting commands).

 


Ravens Fan wrote: 

Why are you previewing the queue in the consumer loop?  Rather than flushing the queue and enqueuing new valuea in the producer loop, then setting an occurrence, to signal the consumer loop.  Just Dequeue in the consumer loop.  It will wait for the elements there.  No extra signalling needed with the occurrence functions.


I am previewing the queues in the consumer loop because the array of elements is in the same format as that needed to input the data into the three XY graphs. This is also because the graphs are not only updated once the 'Test Procedure' completes. The user is able to modify controls that change how the data in either of the graphs is displayed.

 


Ravens Fan wrote:

Rather than create 3 separate queues of identical datatypes, enqueuing 3 times and dequeuing 3 times, I would make an array of that datatype.  Build the 3 pieces of data into a single array and enqueue into a single enqueue.  Use a single dequeue in the consumer loop and index the array as necessary.


The idea behind having three separate queues is because in several other parts of the code, changes can and will be made to data or properties of the graphs individually. Also because I thought it simpler than having to index and build the resulting 2D array every time I wanted to change one small aspect. I also figured this way would take up less space and be easier for someone after me to see what was going on.

 

I am calling up the queues by name rather than having wires trailing all over my diagram. Is this particularly bad coding practice and/or is this method likely to lead to a noticeable speed reduction of the VI?

 

In the 'Shutdown Program' section,  I've wired a TRUE constant to the force destroy? terminal of the Release Queue. I did this because I read in the LabVIEW help that if I didn't and left it as FALSE (default), I'd need a separate Release Queue for every time I obtained the queue. Is this really the case? My intention is to destroy the queues when the program quits (so as not to be loosing memory) but when would i ever need to merely 'release' a queue as opposed to destroying it?

 

 

Thank you for all your help so far.

 

James

Message Edited by James Mamakos on 06-25-2009 11:18 AM


Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 5 of 30
(4,281 Views)

Just noticed something else...

 

In the 'Update Graphs' loop, the Wait on Occurrence means that the loop executes once before waiting for another occurrence to be set. This means that the empty queues are written into the graphs, effectively clearing the graphs when you first run the program. This is the desired effect. However, in the 'Test Procedure' loop, I don't want it to execute when the program is first run - I want it to only execute after the first occurrence is received. How could this be achieved? The method I can think of is enclosing the For Loop in a case statement so that it doesn't execute on the first iteration of the while loop - is this the best way?

 

James

Message Edited by James Mamakos on 06-25-2009 11:26 AM


Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 6 of 30
(4,277 Views)

James,

 

i think it is useful to step back and see what is going on at all when using shift register vs. tunnel. This is explained very well in this thread.

Transferring this to your questions leave the following hints:

1.) That is up to you regarding the queues. Error cluster is different since you have to answer the following questions:

- Do I need error information about errors in previous iterations?

- If a previous iteration has created an error: Does it need to prevent queue functions to work?

If you answers to both questions is NO, use a tunnel.

 

2.) If you use a tunnel for your queue reference, you will not need to wire an outputtunnel at all. This is only true if you release the queue from/after your consumer. If you release the queue after your producer (just like now), you need to wire the queue reference in any case of the event structure (as you already did). The second part is true for shift registers as well; if you use shift registers to store (any) references, you have to make sure to write the correct reference again after each iteration of the loop.

 

I am wondering why you are not using a "traditional Producer/Consumer Framework Eventbased" in order to implement the code. This would remove the need for the occurrence. If you need the consumer to execute an iteration from another part of the software than your producer, please use user defined events to make the producer to enqueue an element.

Aonther thing I am not sure about: Why do you use three queues if they are executed in the same manner all the time (same datatype, same interaction regarding enqueue/dequeue). Just include some kind of ID to your datatype and use this to determine which indicator should be used to display the actual data.....

 

hope this helps,

Norbert 

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
Message 7 of 30
(4,259 Views)

In using an event structure with separate while loops, I've come across a problem to do with Local Variables. As you can see in the attached picture, I have an event which needs to read controls held in another while loop. I cannot use wires to transfer the data, so I've opted for Locals. Bearing in mind all the times I've been told not to use Locals where possible, is there a better alternative for transferring data from the controls (seen in the sequence structure in the lower left while loop) to and from events in the even structure?

 

Also, do i need to flush a queue before releasing it or is that not really necessary?

 

Thank you for your time. 🙂

 

Message Edited by James Mamakos on 06-30-2009 05:16 PM


Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 8 of 30
(4,210 Views)

James,

 

Your VI looks a lot like a Producer/Consumer pattern.  Usually the  Consumer is a state machine.

 

If you used a state machine in the Consumer (where your Test Procedure loop is), you could eliminate the need for most or all of the local variables, the Startup and Shutdown seqeunces, and the Update Graphs loop.  Each of those sections would become one or more states in the state machine.

 

I do not see the CAL control which triggers the event case shown.  If it is a button, just put it in the case.  The CAL code should also be in a state of the state machine.  That way all the controls and indicators with the data are in that loop and no locals will be required.  You will need some shift registers, though.

 

i would probably use queues to transfer commands (such as CAL) from the User Interface to the state machine.  The presence of a new command in the queue would have the same effect as your notifiers.  The state machine could just remain in an Idle state while waiting for a command.  Most event cases would only contain the command enqueue function.

 

Flushing the queue is probably not necessary.

 

Lynn 

Message 9 of 30
(4,201 Views)

I hadn't actually considered using a state machine, though I may give it a try. This VI is still far from being finished, and so there are still a few controls lying off-screen that are yet to be connected up.

 

I have about 6-7 separate 'processes' of which the Test Procedure and Update Graphs are the only two to be executed slightly differently from the rest. The Test Procedure is by far the longest and I want it to run when called, but once it's started for it to run on its own. The Update Graphs does exactly as the name suggests and has just been detached from the rest so I didn't have to right out the code more than once or carry references to the graphs around. The remaining 'processes' require user intervention which is why I've placed them in the event structure (locks front panel until process is finished) and also because whilst they're running, I don't want anything else to be. When the Test Procedure is running, I don't want any of the other 'processes' to be able to run (I'll probably just disable their button controls) but I do want to be able to do several other things (some of which require the graphs to be updated).

 

That's just a very basic, brief and probably-not-very-understandable description of my VI, but I hope it makes some sense.

 

It may be that I'm just not very experienced in using them, but do state machines not loop endlessly (albeit with a default blank state)? This was the kind of operation I was trying to avoid when I started converting this VI to an event structure based producer/consumer architecture. I assume that were I to implement a state machine, it would go where I now have a normal case statement in the Test Procedure while loop?

 

James



Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 10 of 30
(4,191 Views)