LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Control producer loop from consumer loop

Hi,
I have the following problem: I created a data acquisition application that runs the data acquisition in a producer loop and passes the data to the consumer loop, main VI that offers all the controls to the user. Data is passed via a Queue. However, I would like to be able to control the producer loop via the consumer. Specifically, the user should be able to stop the producer from the front panel of the main VI. Therefore, he should be able to change the number of data readouts or abort the acquisition. For this, I used a channel wire that allows to update the abort condition of the producer loop from the consumer loop dynamically. However, I have now the problem that I can't run the producer VI anymore independently. Do you have any idea how to make it possible that the producer loop VI can be run as top-level VI? For the data pass queue, I found a solution by using the "Not A Number/Path/Refnum? Function" VI. But how can I deal with the channel wire?

If this is not possible, are there other structures which offer me the functionality I need (and described above) that allow to run the VI independently?

 

Thanks a lot for any hints!

 

Peter

 

Download All
0 Kudos
Message 1 of 7
(3,149 Views)

Hi,

 

Although not a great solution, the simple answer is to have the controlling VI exit its own loop then force close the queue reference. This will cause an error in the other VI's loop when it next tries to use the queue function, which you can connect to the stop condition in the loop.

 

This is not great because generally it's not an amazing idea to cause errors for normal operations (i.e. stopping). A more robust/safe method might involve using multiple queues and a state machine. You could use one queue to pass the data from producer to consumer, and another queue to pass instructions (perhaps using a typedef'd enum) from your master to the slave (whichever way round you wanted to do this).

 

You can also then implement (consider using the Not a Queue function you already used) some alternative method of control for the Producer, if you really want this to act as the slave.

A possible example is attached - obviously you could extend this to use more than just a STOP message (and rearrange it to avoid the Case Structure) - I chose to use the CS and String rather than Enum to avoid subVIs or typedefs for the forums.

 

snippet.pngTrue case in Producer - allows running independentlyTrue case in Producer - allows running independently

 


GCentral
Download All
Message 2 of 7
(3,139 Views)

And consider using dynamic events, using as a datatype a cluster of a typedefed enum and a string or variant as dynamic data. You have to register this event in your producer loop, doing all default stuff in the timeout case, with timeout set to zero. From the consumer loop you can send the event with the enum value set to 'stop' or set to 'Set_Aq_Speed' with the actual speed value passed in the dynamic part of the cluster.

I use this a lot and it works very well, LabVIEW handles these events very fast.

Greets, Dave
0 Kudos
Message 3 of 7
(3,066 Views)

I think you don't understand the idea of the Producer/Consumer Design Pattern.  There may be exceptions to what I'm about to "generalize", but these can (probably) be dealt with easily:

  • The Producer is "in charge".  The Producer/Consumer pattern begins when the Producer starts "Producing", and ends when the Producer gets notified that things are at an end.
  • The Consumer is a "tool of" (or "slave to") the Producer.  As long as the Producer is alive and Producing, the Consumer must be alive and Consuming.
  • If you have Channel Wires, the easiest way to configure a Producer/Consumer Design is to use a Stream Channel Wire from Producer to Consumer.  Every time data is placed on the Producer's Writer, it will appear on the Consumer's Reader.
  • When the Producer decides to stop the process (and end its Loop), it should wire a "True" to "Last Element?" (to tell the Consumer that this is the last time it needs to read from the Producer).  In some instances, you may also want to set "Element Valid?" to False.

Here's a Snippet of a Producer/Consumer governed by a Stop Button (in an Event Loop, itself a kind of "Producer").  The Producer is simulating a DAQ Device reading a sinusoid, 100 samples at 1 kHz, and sending its output to a Consumer for plotting in a Waveform Chart.  Note that the Stop Button is used to stop the Event Loop and (via a Tag Channel) stop the Producer (and signal the Producer to stop the Consumer).

Producer-Consumer DemoProducer-Consumer Demo

The attached VI is in LabVIEW 2016, so any version supporting Channel Wires should be able to run it.

 

Bob Schor

Message 4 of 7
(3,064 Views)

@pegli wrote:

However, I would like to be able to control the producer loop via the consumer. 


You really don't want to do this.  If you're starting down that path, stop.  Step back.  Breathe.

 

You're looking for ways to control the producer loop.  Add that logic to the producer loop.  It looks like you're ultimately running into issues where you're acquiring large amounts of data at once and wanting the user to be able to stop that.  If that's your actual issue, this isn't something you'll solve cleanly by trying to use the consumer loop to perform this action. 

 

In order to provide meaningful advice, it'd help to understand what your goal is with respect to acquisition.  What are expected durations of acquiring?  I didn't poke the VI here too much as I'd expect it to be butchered a bit to try to make the circular control thing take place.

0 Kudos
Message 5 of 7
(3,055 Views)

To followup on @natasftw's notion of guarding against a gross mis-match between Producer and Consumer speed, it is easy to modify the Demo I presented to cause everything to shut down if the Consumer gets too "backed up".  I'm going to leave this (in part) as an "Exercise for the Reader", but here are some of the steps you could take:

  • How can you tell if the Consumer is lagging behind the Producer?  The Stream Reader has an output, "Count", that says how many unprocessed elements are left in the Channel after the current element is removed (it should, ideally, be 0).  You could test for, say, >10, and if so, put a "True" on a Tag Channel, take it out the right side of the Consumer, bend it up and over the top of the Loop and join it to the existing Tag Channel that stops the Producer (which stops the Consumer after letting it empty the Channel).
  • What's missing from this solution?  "Two out of three isn't too bad ...".  In LabVIEW 2016, there isn't an elegant way to stop the Event Loop -- Event Messenger Channels were added in LabVIEW 2017.  So find an "inelegant" way (say, a 100-msec TimeOut Event processing some input ...).

Bob Schor

0 Kudos
Message 6 of 7
(3,029 Views)

I differ with several responders in that I *don't* particularly think you're on the wrong track.

 

Much as cbutcher already covered in msg #2, I think the Queued Message Handler (QMH) is a well-accepted architecture that I often use in ways much like you describe.

 

I tend to have one top-level "main brain" loop and several simpler, single-purpose loops for things like instrument communication, data acq, file logging, etc.   Each loop has its own queue to receive messages or commands.  

 

The top level loop is both a "master" (in the sense of coordinating all the other loops) and a "consumer" (in the sense that it receives all the instrument and DAQ data).

 

I've often set up data acq loops that are both "producers" and "slaves".    As a slave, it receives and acts on messages/commands such as "Init", "Exit", "Start Data Acq", "Stop Data Acq".  When data acq is active, it primarly acts as a producer, regularly sending data back to the main loop.

 

So in this way, I see no conflict about the idea of a consumer loop (my main brain loop) that controls a producer loop (my data acq loop) by telling it when to start, stop, and exit.

 

 

-Kevin P

 

P.S.  There's a shipping example of a QMH project template available to study or use.  You can open it from the menu "File-->Create Project..."

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
0 Kudos
Message 7 of 7
(2,989 Views)