LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Producer consumer continous data retrieval

Hello All,

 

I am using a producer/ consumer pattern to continuously get data. in consumer loop, i am using a state machine in which i try to use this data. But the problem is that when i start state machine, the incoming data is stopped. I need this data while state machine is running. I am new to Labview, does not know much. A help will be highly appreciated.

 

Regards, 

0 Kudos
Message 1 of 14
(3,860 Views)

Ok, so firstly, good job with commenting up some of your code, and attaching the whole project rather than broken bits and pieces.

 

With regards to your problem, you have the dequeue element outside all of your cases. This means that will dequeue one element of the queue per iteration of the outer loop.

 

When you press Standard Test, you enter a new loop, which waits for M1's local variable read to be between 59.9 and 60.1. This condition will never be satisfied since a) M1 is generated between 0 and 10, and b) only one value of M1 (the current value) is considered - the dequeue won't be used again until the end of the inner loop's event, which never happens, because the loop in the middle never stops.

 

You need to dequeue inside the inner loop if you want new values, and you need the condition to at some point be true to ever get out of the inner loop.

 

You also have a compound arithmetic OR on a single value. This does nothing! 🙂


GCentral
0 Kudos
Message 2 of 14
(3,847 Views)

Dear cbutcher,

 

Thank you so much for your kind and quick reply. I understand the values are mistakenly wrong, it should be between 0-10. But the main problem is to get values continuously. I put dequeue elements inside case selector, but still the problem persists. Or i could not understand your point- sorry for that. I have attached snapshot of changes. Kindly have a look.

 

Plz ignore any stupid questioning from my side.

 

Thanks

0 Kudos
Message 3 of 14
(3,838 Views)

What I meant was more that the Event Structure's case for Standard Test: Value Change starts a loop which checks the same value read from the M1 and M2 local variables to be between some limits.

 

The values which are checked never change - they are read before the loop starts (you see they are wired into the left side of the while loop in the image).

 

If they don't satisfy the check on the first iteration, the loop will never end, because the values never change. It looks like what you want is to repeatedly check the values generated in a producer loop, and wait for them to satisfy some condition in the consumer loop.

 

Hopefully you can see that the main problems is due to your flow of data - although you move the dequeue element inside the test selection case, this is probably worse! What you really want to be doing is removing the inner loop because this is blocking the outer loop from iterating. In a text language, this would be something like (terrible pseudo-code follows!):

 

while ! stopCondition do {

get MValues

if StandardTest clicked, do {

while M1 not between valueA and valueB {

continueForever

// See the problem here?

}

}

}

 

Hopefully my dubious text-based pseudo-code, complete with whole sets of mixed-language syntax, has highlighted the problem. You dequeue is outside of the loop that checks, and then you forever check the same values against some condition. This either passes on the first attempt, or locks forever!

 


GCentral
0 Kudos
Message 4 of 14
(3,824 Views)

Dear Cbutcher,

You got my point, this is exactly i need "It looks like what you want is to repeatedly check the values generated in a producer loop, and wait for them to satisfy some condition in the consumer loop."

But now, the problem is that i could not exactly understand how to do it.

What i tried is to remove the case selector, which i did, but still it does not help. Actually, this is just a dummy program. what i want  to design is similar to this, that is why i put this design.

Still confused due to my lack of knowledge. Can you edit this program for better clarification of your point?

Thank you so much for your effort.

0 Kudos
Message 5 of 14
(3,811 Views)

Take a step back.  Think about the Order of Execution.  Maybe what you want to do is to first "Decide on a Course of Action" (perhaps by pushing a button, but think about what would happen if you pushed two buttons), then "Do the Selected Action".

 

When you have multiple Controls on the Front Panel and want to "do something" when they change, the Event Structure is a handy way to wait and "do something" only when a Control changes.  This is often used as a Producer in a Producer/Consumer Design, as you can see by looking at the Producer/Consumer Design Pattern (Events) built into LabVIEW (open LabVIEW, go to the File menu, choose "New ..." (the dots are important), and under From Template, find Producer/Consumer Design Pattern (Events)).

 

What does the Front Panel contain that might be passed to a Consumer?  One thing is "What routine shall I do?", i.e. an Enum consisting of "Just Dusting", "Standard Test", "Cycle Test", etc.  Something else that might be passed to the Consumer is "Stop", a boolean -- however, this is slightly different, as we'll see in just a second.

 

So what does the Consumer do?  Well, this can (and should) be a really tiny (in screen-space) piece of your Block Diagram -- a While Loop that has, inside it, a Dequeue function (that dequeues the Enum value placed on it by the Event Loop) that "feeds" a Case Statement that takes on the values "Just Dusting", etc. of the Enum.  The Just Dusting Case should consist of a single VI that executes the "Just Dusting" code all by itself.  Note that, at present, this code, once running, has no interaction with the calling program except for the Stop command.  If you need to see Indicators on this sub-VI, one way would be to configure it so that it runs with its Front Panel "open", allowing you to interact with it.  Indeed, one way to handle stopping this sub-VI, if its Front Panel is visible, is to put a Stop button on its Front Panel to stop it.  When it stops and returns to its caller, the Case Statement will be satisfied, and you can exit the While Loop (if you want).  Lots of flexibility -- you could also select another Case ...

 

So how would one of these sub-VIs work?  Another Producer/Consumer pattern.  You want to start collecting/generating data (your Producer), then your Consumer wants to do various things with these data.  Have you ever heard of a State Machine?  Have you ever heard that you should never use a Stacked Sequence (we've been lobbying NI for years to get rid of it, and in the most recent versions of LabVIEW, it doesn't appear on the Structure Palette), and should almost never use a Flat Sequence (one exception is to "bind" a Wait function to, say, the Error Line, for sequencing).

 

As I understand it, what you want to do is to look at incoming data (in your Consumer).  In your initial state, you are looking for certain conditions to be met (the data must be between X and Y, or you need to see "three in a row", or the User needs to Push a Button).  When the condition is satisfied, you move to a new State where you Save the Data, Plot the Data, Do Something Else with the Data, and you stay in this State until something else occurs, at which point you move to yet another state.

 

Well, LabVIEW has you covered here, as well.  Open LabVIEW, click Create Projects, look under the Desktop Templates for Simple State Machine, and study the example.  Look at your Stacked Sequence -- can you see that it is, essentially, a State Machine, but with horrible, inflexible, archaic architecture?  [A State Machine is a Case Statement inside a While Loop, with State Variables being carried in Shift Registers so that they are available for every State, but can be changed from State to State, no local variables anywhere because they're in Shift Registers, so no Race Conditions, etc.]

 

This may be a little bit too much to take in all at once.  And sometimes, particularly if you are trying to modify existing code, it can see hopeless.  Here's a suggestion -- take notes on paper, plan what you want to do, then start over.  Build a State Machine that does one of the Producer/Consumer tasks (like Standard Test).  Test it to confirm that it works.  Try to build another one.  Now try to build the Front Panel Producer Consumer (the one with the Buttons that calls these simpler State Machines).  Don't try to do everything at one sitting -- do Standard Test, test it, get it working, then use it to build Custom Test or one of those, get it working, then build the "Master" Front Panel program.  You'll learn a lot, develop some skills, learn Producer/Consumer, learn State Machines, learn LabVIEW.

 

Bob Schor

Message 6 of 14
(3,800 Views)

Bob's rather excellent post has you covered with a lot of good points, but to try and give you a hint as to where to start, you should look to the middle of what he wrote. (Note - you should read all of his post, and carefully - it has a lot of key points for architectural design that will help you a lot in the future!)

 

@Bob_Schor wrote:

As I understand it, what you want to do is to look at incoming data (in your Consumer).  In your initial state, you are looking for certain conditions to be met (the data must be between X and Y, or you need to see "three in a row", or the User needs to Push a Button).  When the condition is satisfied, you move to a new State where you Save the Data, Plot the Data, Do Something Else with the Data, and you stay in this State until something else occurs, at which point you move to yet another state.

 

Well, LabVIEW has you covered here, as well.  Open LabVIEW, click Create Projects, look under the Desktop Templates for Simple State Machine, and study the example.

The key point here (as I see it) is that your data consumer shouldn't be locking itself out of getting new data! As you can see from his detailed explanation, the idea of a state machine here is that rather than having a case which starts a loop checking the inputs for some condition (between 59.9 and 60.1, for example) you can have a case which says - is this condition satisfied? If yes, go to the next state. If no - go to the same state. Here, you can have it so that each iteration of your consumer, if the condition is not satisfied, you remain in the same "Check condition" state, and never start what is step 2 (case 1) of your Stacked Sequence Structure. Once your condition is satisfied, you can wire 'Step 2' to your state output from that case. See the example State Machine for more details!

 

Edit: The state machine example is called "State Machine Fundamentals", at least in LV2016, and as far as I can see there's no template under "New...", just the example. Contrast this with the Producer/Consumer, which you've already found the template for.


GCentral
0 Kudos
Message 7 of 14
(3,792 Views)

@cbutcher wrote:

Edit: The state machine example is called "State Machine Fundamentals", at least in LV2016, and as far as I can see there's no template under "New...", just the example. Contrast this with the Producer/Consumer, which you've already found the template for.


Right.  As I said, this is found by doing Create Project, and (from the drop down) choosing Templates, then on the right hand pane choosing Simple State Machines.  I agree that "Templates" means one thing in File/New ..., and something slightly different in Create Project in the LabVIEW Opening Screen, slightly confusing ...

 

BS

0 Kudos
Message 8 of 14
(3,788 Views)

Dear Bob_Schor and Cbutcher,
Thank you for comprehensive reply.
As from Bob_Schor suggestion, i have implemented a state machine for whole program. Now it seems to have better control. Attached hereby.
however, i could not understand the concept of using state machine for comparison of values. Here the problem is that, i could not even get the values inside my flat or stacked sequence.
I understand of using cases, but where? inside flat sequence?
I hope you'll understand my point.

Waiting for your kind reply.

Regards,

Khan

0 Kudos
Message 9 of 14
(3,783 Views)

Well, I guess I didn't get my point across.  So here's how you can understand what I'm trying to say --

Open test_program.  Look inside the "Standard Test" Case.  See the Stacked Frame?  Delete it, and everything else (especially those Local Variables) inside the Case.  Now, put a While Loop inside there, and a Case Statement inside that.  Think about what specific (sequential) things you want to do, we call those "States".  As a hint, the first State can possibly be described as "Have we gotten the M1 and M2 variables where we want them?"  If so, we go to the next state, if not, we stay here.  M1 and M2, of course, "live" as Shift Register variables in the While Statement.

 

Bob Schor

0 Kudos
Message 10 of 14
(3,742 Views)