LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Problem using local variable in event loop

I have a state machine from which I want to monitor various controls, including "Start" and "Stop" buttons.  Not every state needs to monitor the controls.  At present, most states run timed loops.  In the first state that reads the front panel, I have an Event structure (inside a While loop) that monitors the various controls' Change Value events.  For numeric controls, I update variables (in shift registers) as needed.  The "Start" button is used to end the While loop controlling the Event structure, allowing the State to exit to the next state.

My problem comes in subsequent states that employ this same idea.  Here, I put a Local Variable bound to the Start button and use the same code, but it frequently happens that when I enter this particular state, I cannot "turn on" the control -- I push the button, but it stays off.  Curiously, if it was On when I enter, I can turn it off, but then I'm stuck not being able to turn it on.

I mocked up a very simply routine that illustrates this.  There are two sequences (corresponding to the two states).  Both use an Event loop with a local variable bound to my Stop button (really this is an LED control with custom colors).  I've deliberately moved the "initialization" (the declaration of the control in the block diagram) out of the Event loops -- putting it inside the first loop modifies the behavior in another strange way.

Here's my thinking on how I would expect this to work:  The code outside Event Loop 1 should have little effect.  Assume the Stop button is initially Off.  You will "sit" in Event Loop 1 until you push the Stop button, changing its value to True; this value will be passed out of the Event case and cause the first While loop to exit.  You now enter the second sequence.  As I understand the Exit tunnel, it defaults to "False", so I'd expect to stay in the second Event loop until I turn the Stop button from On to Off, which will pass out a False, and keep me in the While for one more button push.  However, this doesn't happen -- I immediately exit, as though the "True" value of the Stop local variable is being seen and recognized by the Event loop (even though it hasn't changed, at least not in the context of this second loop).

An even more curious thing occurs if I start this routine with the Stop button turned on.  Now I start in my Event loop waiting for a change, but this time the change will be from On to Off, which won't cause an exit from the frame.  This will be reflected by having the While loop count increment.  We should now be in the state of the example above, i.e. in an Event loop waiting for the control to be pushed again, and turned On.  However, clicking the control has no effect -- I cannot get it to "turn on".

Where am I going astray in my thinking?  What is it about this method of doing things that violates the Labview paradigm?  As far as I can tell, what I'm doing is "legal", and I don't see the flaw in my reasoning, above (of course not -- otherwise I'd have fixed it myself!).  Note that because I'm using local variables inside Event loops (and I'm doing this because there are two places in my code where I want to do such testing), the Stop control is not latching (as required).  Is there something that gets triggered/set when one reads a latched control?  Do I need to do this "manually" using my local variable?

I'll try to attach the simple VI that illustrates this behavior.

Bob Schor

0 Kudos
Message 1 of 8
(4,147 Views)
The good news is that your example is so simple, there's not much wrong with it.  Smiley Wink
The bad news is that it shows something you should never do with an event structure.  NEVER have multiple event structures that share the same events.  Just because the other event structure hasn't been executed yet, or in the other case the first event structure may have already passed, it doesn't mean that the event structures aren't sitting there waiting for their event.  Either one could pull the event off the event queue and block the operation of the other.
 
(By the way, writing a control to the local variable of itself is a meaningless operation.)
 
As for latched controls, only when the latched control gets read (meaning the code actually acts on the terminal within the code) does the control get latched back to its false condition.  If you use local variables of a latched control, Labview wouldn't know whether it should unlatch it when the control is read or whether the local variable is read.  The program would behave inconsistently and unpredictably, thus Labview does not allow local variables with Latched controls.  You can make your own latched controls by manually resetting the value back to False with a local variable or property node.  But it is up to you to determine how and when the occurs in your program.  For instance, if you are using a local variable of a stop button to stop multiple parallel loops, you would probably want to make sure all loops have stopped before you would manually reset the stop button back to False.
 
I don't completely understand myself the inner workings behind the event structure, but I do know never have multiple event structures share the same events.

Message Edited by Ravens Fan on 10-28-2007 04:33 PM

0 Kudos
Message 2 of 8
(4,143 Views)


@Ravens Fan wrote:
NEVER have multiple event structures that share the same events. 

Actually, that's OK. 🙂 NOT OK is having multiple event structures in the same sequence structure.

See also: http://forums.ni.com/ni/board/message?board.id=170&message.id=278981#M278981

 

First for the definition of a state machine. You don't have a state machine by any conventional definition of it, but a state worm. 😉

A state machine has a single main state loop and can transition from any state to any other state depending on the needs. You can switch states, or repeat states as often as needed. Your "states" must execute in a forced linear order and then all's over. Not a state machine!!!

I think you should take about two steps back and rethink your code architecture. What UI events need to be handled? What needs to occur in parallel?

Remember: An event structure is always ready and does not depend on dataflow. If an event is set to lock the front panel until it complete (the default setting) and dataflow prevents it from executing, your entire program will deadlock.

0 Kudos
Message 3 of 8
(4,137 Views)


@altenbach wrote:


@Ravens Fan wrote:
NEVER have multiple event structures that share the same events. 

Actually, that's OK. 🙂 NOT OK is having multiple event structures in the same sequence structure.

See also: http://forums.ni.com/ni/board/message?board.id=170&message.id=278981#M278981


That's interesting.  I had always thought I read more messages discouraging such a thing rather than saying it was okay.  Your link lead me to another thread with this message. http://forums.ni.com/ni/board/message?board.id=170&message.id=245793#M245793.  Now that thread was mainly concentrating on registered user events which would be a different, but related animal. 

So if you have 2 event structures they each have their own event queue?  So if you have a common event, one structure pulls it off its event queue and it does not affect the other structure's event queue?  I guess the inherent problem with this particular VI was that the second event structure locked the front panel.  Since the code never got to that 2nd event structure because the  first loop never stopped because the change was from true to false.  After reading your post and the others, I did some experimentation and turned off the Lock front panel on the 2nd structure, and that prevented the lockup of the program.

Overall, the example VI still shows problems with the architecture and I think your answer should put the original poster on the right track.  I think as a rule I would probably never put the same event in multiple structures, I feel there are better ways to communicate the same event between different parts of a program,  but I learned something by reading your reply and about how the event structures work in the background.  Thanks.

0 Kudos
Message 4 of 8
(4,118 Views)
Sigh.  I know this simple example is not a state machine, I don't typically use sequences in my code, but was trying to illustrate a problem and misunderstanding I have.  Let me try again.

I have a State machine, built, for example, using NI's State Machine template.  Assume there are three states: "Wait for User", "Do Stimulus", and "Gracefully Abort".  The "normal" sequence is to "Wait for User" (meaning the user pushes a front panel button and starts things going), during which time the front panel controls can be read and variables reset, followed by "Do Stimulus", where the system executes a particular sequence (say, generates 20 cycles of a sinusoid) before returning to the Wait for User state.  For both states, I want to catch/trap the push of an "Abort" button and gracefully turn things off (ramping down the stimulus, rather than jerking to a stop).  I had an Event structure in Wait for User that had the actual front panel controls in it, and it worked fine, as one would expect.  In particular, if one pushed the "Start" button (which was an "event"), it was recognized and the state was exited.  This same event loop also trapped the "Abort" button, and also worked.  However, in the Do Stimulus state, the event structure meant to catch the abort button exhibited the same behavior that my very simple (and, I admit, "simple-minded") example showed, namely that under some conditions, the control appeared to "lock up" and not be push-able.  I needed to use a local variable in the second loop, which is why I fixated on local variables in my example code.  I included two sequence frames, and had the "silly" example of a control passing its value to its local variable (that was just a ruse to get the control out of the sequence) -- this was meant to be code that illustrated a "behavior" problem, namely having a control that couldn't be turned on from the front panel.

One responder said "I did some experimentation and turned off the Lock front panel on the 2nd structure, and that prevented the lockup of the program."  Hmm -- what is "lock front panel"?  Once I learn this, I'll see if this fixes my "real" (as opposed to my "example") problem.

Bob Schor
0 Kudos
Message 5 of 8
(4,113 Views)
Right click on the event structure and Edit Events for this Case.  You will see a check box near the bottom that is usually checked by default to "Lock Front Panel until the event case for this event completes."
 
You may want to look into producer/consumer loop design patterns.  Let one loop be the user interface loop with that handles the front panel interface.  Let the other loop be the state machine.  You can pass the commands into the state machine by way of queues or notifiers.  (Queues are more commonly used.) 
Message 6 of 8
(4,110 Views)
Smiley Very HappyEpiphany!  I get it!  I'm new enough to Labview (despite having done real-time programming, on a PDP-11, no less, more than 30 years ago) that I haven't learned to think in terms of parallelism.  Simply move the Event loop out into its own loop -- if you need to handle events differently in different states, just put in the appropriate State case statement in the appropriate Event case.  The "new and improved" conundrum routine, which works EXACTLY as I would have thought it should, and does not involve worrying about "locking the front panel", is attached.  Much simpler!

Thanks to all for their help -- by saying "What a Bonehead Program!" (even though I'd intended it as the "simplest demonstration of a more complex problem"), you pointed out that the fatal flaw was in the basic structure.  The "Aha!" moment came to me as I was pondering your comments.

Bob Schor
0 Kudos
Message 7 of 8
(4,087 Views)
You may want to do something more like this.  What you posted still isn't really parallel loops.  The lower loop with the event structure won't execute until the upper loops are done and the boolean is passed out of the sequence and into the event structure loop.  What you have may work for you in a simple example, but as you start adding events, you would find that your other events aren't really executing until the upper loops are done.

Message Edited by Ravens Fan on 10-29-2007 11:24 AM

0 Kudos
Message 8 of 8
(4,070 Views)