LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Debugging producer/consumer design pattern with multiple consumers triggered by user events only.

Solved!
Go to solution

Hello all,

 

I am a very new LabVIEW user working on my first project. I have completed Cores 1 and 2 and about a third or core 3 and feel I've got a decent amount of tools under my belt to start tackling my own problem. I am currently having some troubles with using user events to trigger the consumer loops instead of queues. I have switched from queues to user events in order to avoid nested while loops which I can only seem to stop using local variables. More details are below but I would really appreciate any help on offer. It would also be great to hear any comments about how I could improve my code, for example would a different design pattern be more suitable. Apologies in advance if you thing my block diagram is not as neat as it should be, I've been trying to keep it as close to one screen in size as possible but this has come at the expense of things being packed rather tight!

 

I am trying to create a piece of software to control a mechanical test rig. I am using a producer/consumer design pattern with at least 3 consumer loops. The producer responds to button presses from the front panel, triggers the initialisation of each piece of hardware and their shutdown in case of an error detected in on of the consumer loops.

 

The first consumer loop controls a data logger (which wil be logging 4x thermocouples and 1x force sensor). The user must select which channels are to be used and then chose to begin logging. Once they have chosen to begin logging this loop reads data from the device every second. When using Queues I could only make this work with a nested while loop which I could only stop using a local variable. Further I think this design will make it more difficult to take data from the force sensor out pf this loop and write to file along with data from other loops (I would like to synchronise this but thats a problem for the future).

 

The second loop controls a heater via a PID loop. It takes it input signal via a local variable from the data logging loop. I don't mind losing data from the first loop as only the most recent temperature readings are relevant to this PID controller. When using queues I also had to use nested while loops to keep the PID control running without user input.

 

The first two loops seem to run fine with queues passing the data from the producer to the consumer and the event stucture to pass error information back to the producer. My next stage was to integrate control of two actuators. This is the third consumer loop. So far I have not been able to re-test the software with the hardware as the hardware is currently being modified by our electronics workshop, however I have been looking to check that the case where no equipment is connected works properly.

 

In the attached zip file is my project. "producer consumer QUEUE.vi" works as expected. The producer tells the consumers to start initialising the equipment and when no equipment is found, errors are fed back the the producer and the software shuts down. However when I have moved to using user events in "producer consumer USER event.vi"  the case for no equipment connected only works when highlight execution it turned on. I think that I maybe have a race condition somewhere but I cannot tell where! My reasoning for switching to user events is that I have now used the timeout cases to allow the datalogging and PID loops to continuously run until there is another user input. I also like how easy it would be in the future to add other loops almost like plug-ins.

 

I have also placed a couple of screen grabs from each version incase anyone can spot the problem without downloading the project folder. Sorry I can't show the entire block diagram, hopefully there is enough there!

 

Any help you can offer as to why my user event based vi doesnt work would be greatly appreciated, same with any other comments on how my system could be improved!

USER EVENT.png

 

QUEUED.png

0 Kudos
Message 1 of 9
(5,297 Views)

dmmistry,

 

Using several user event cases for one front panel isn't a good thing to do. What’s the point? Minimize the number of event display on the event selector case? 

I understand what you wanted to do but it's not the goal of a user consumer with event handler.

The producer should only handle event and send data to producer loop in order to proceed data from event.

In your case, if you want to have an event handling by panel, use sub panels.

 

Good luck

Regards.

Sabri JATLAOUI - Certified LabVIEW Architect - Certified LabVIEW Developer
0 Kudos
Message 2 of 9
(5,288 Views)

Hi Sabri,

 

Thanks for your swift response. Are you saying I could (and it would be better to) simplify the whole program down to a single loop with a single event structure? I had though that this might be bad practice as it would make it harder to add new functionality to the program. Additionally how could I tell if a process it intensive enough to warrant moving to a producer/ consumer design pattern?

 

Thanks,

Devesh

0 Kudos
Message 3 of 9
(5,277 Views)

I didn't look closely at your code, but one thing that's obviously wrong is that you're using a single registration node for more than one event structure. This is something which can definitely lead to weird behaviors (including, possibly, to what you're seeing. I don't know if this is the cause, but you should certainly change it). The way to fix this is fairly simple - the output of every register for events node should not go to more than one event structure. If you have multiple structures, you should have multiple nodes.


___________________
Try to take over the world!
Message 4 of 9
(5,256 Views)
Solution
Accepted by topic author dmmistry

I'm assuming that “producer consumer USER event.vi” is the main file.

“Loading TC-08 channels in a loop.vi” is missing.

Neatness matters a lot in LabVIEW. If wires or wire ends can't be seen, you can't tell where they go. You have to double-click each wire to check. This wastes tons of time and hides errors. The tools to move things around are good. Start now  effort will pay off quickly.

In the producer loop – you connect the stop event reference to the Dynamic Event terminal. I'm surprised this is possible.

Each loop that registers for events should have its own Register for Events node (I see tst mentioned this). Only bring in the events used in the particular loop – others will “touch” the loop even though they aren't registered. You can make a cluster of events and feed that into the Register for Events node when needed (like the cluster you made for the Producer loop).

In your consumer loops, you seem to be firing the error event all the time. Use a case structure to only fire on error.

I would make the consumer loops into subvis.

That's a start ...

steve

 

--------------------------------------------------------------------------------------------------------------------------
Help the forum when you get help. Click the "Solution?" icon on the reply that answers your
question. Give "Kudos" to replies that help.
--------------------------------------------------------------------------------------------------------------------------
Message 5 of 9
(5,239 Views)

I think you are confusing two different Design Patterns, the Simple State Machine (where there is nothing explicitly time-critical) and Producer/Consumer (where the Producer has a time-critical element).  [Purists can quibble with some of this, but this is how I explain this to myself and to my students].

 

One really nice aspect about User Events is that it allows you to have a State Machine (defined by the User Events as the States) that incorporates Front Panel processing.  For example, when the Start button is pushed, the Value Changed Event for Start Button simply raises the User Event "Start", and when the Gain Dial is changed, the Value Changed Event puts the new Gain on a Shift Register where it is shared by the Event Loop (which is also the State Machine loop).

 

Producer/Consumer, on the other hand, is an instance of two parallel loops, the Producer (which runs on a clock of some sort, such as the output of a DAQmx Read) that generates information that must be "exported" so that the next loop can run at the proper time, and a Consumer that knows what to do with these data (save it to disk, display it on a Chart, show an image, do an FFT, etc.).  The notion is that the Producer spends 99% of its time "waiting" for data to appear, but when it does, it runs (in parallel with the Consumer, if need be), while the Consumer has, at a minimum, the "free time" that the Producer is waiting to process the data.  If a few such processes take a little more than one Producer cycle to complete (such as opening a file or doing a major display update), it doesn't matter as the data are saved in the Queue, ready for processing.  As long as the Consumer, on average, is faster than the Producer (or you have enough memory for the Queue), no data will be lost.

 

So decide what you are trying to do.  There's nothing wrong in mixing the two models.  I like using the User Event State Machine for overall Program Control (Initialize, Configure, Start, Stop) and use Producer/Consumer for the time-critical "Run" part of the program.  When I do this, I usually use "spawned" Producer and Consumer loops (I write them as "looping" sub-VIs, then start them with Start Asynchronous Call, starting the Consumer first, and having both Producer and Consumer construct a named Queue so that the Queue Wires stay within each sub-VI and don't need to be exported.  Stopping these loops can be done by a variety of techniques, including (a) destroying the Queue, (b) using a VIG/Global/Shared Variable to carry an Exit signal, or (c) a Notifier input to the loops.

 

Bob Schor

 

P.S. -- congratulations on your progress in learning LabVIEW.

Message 6 of 9
(5,233 Views)

Thanks stevem181 and tst. I'll work through your suggestions and see where I get with that! I have attached the missing file, not sure how I left it out.

 

Cheers,

Devesh

0 Kudos
Message 7 of 9
(5,227 Views)

Thanks Bob, looks like there quite some way to go for me!

0 Kudos
Message 8 of 9
(5,224 Views)

@dmmistry wrote:

Thanks Bob, looks like there quite some way to go for me!


The more you know, the further away the horizon gets.

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 9 of 9
(5,214 Views)