LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Handling a state machine using a single button

Solved!
Go to solution

Hi all,

 

I would like to implement a process which runs like a state machine with a certain functionality that I can't seem to make work just yet.

Basically, the user will first choose a number of processes (and the state machine will only run the process they select), and the following steps should occur after pressing start:

(Each process corresponds to a state in the state machine)

 

1) Process 1 is run for as long until user clicks an OK Boolean

2) After OK Boolean is clicked the state goes to Process 2 

3) Process 2 runs as long until user clicks the OK Boolean once again

4) And so on and so forth until all processes are done

 

The problem I'm having is with the OK Button. Accomplishing the above tasks is relatively simple if there are multiple OK Buttons for each process/state OR if the Boolean operation of a single OK Button is changed to Switch and is Reinitialized to Defalt after each process.

 

However I find both methods inelegant, especially when the number of possible processes is high hence the amount of local variables that need to be polled each time to see if it's been clicked and ensuring the button is reinitialized to false each time clutters the block diagram unnecessarily methinks).

 

I'm thinking of making just one single OK button and making it a latch, which runs into the problem of local variables not being possible to be inserted into each state. I feel an Event structure is needed *somewhere* so that the state (which is a loop that does a bunch of things) stays the same until OK is triggered (which effectively stops the loop in the current state, and then it springs to the next state and the same thing happens until OK is triggered again but my rudimentary attempts has only resulted in endless looping and hard aborts.

 

Bonus problem: when the user clicks the OK button, there should be an awareness they have done so and not press again because it might skip one/more states ahead than it should... (Dialog boxes are useless bc they just cause more unnecessary clicking; I've mulled over a kind of maybe showing a loading button but then the question comes up of how long enough should it stay up to make the user aware but short enough to not give the feeling that the program is lagging, etc....so other suggestions for this are welcome too.)

0 Kudos
Message 1 of 23
(2,993 Views)

I'd recommend separating your code into two loops, a UI loop and a "business stuff" loop. Use a queue or user event to connect the two master/slave loops. The Master loop will have an event structure to detect button presses and it will send that information to the slave loop. The slave loop will have a Dequeue function with a timeout set to 0 to wait on the information from the Master loop. With a timeout of 0, the Slave loop will check if there's an element in the queue and, if so, process the element (and thus detect the Stop), or if there's no elements in the queue, it keeps doing whatever it's doing and will not wait at all.

 

A second way to do this is with user events with a Timeout of 0, placing your "business logic" in the Timeout case of the Slave's event structure. Note that the Slave event structure doesn't detect the button press, just a user event that's sent from the Master loop when the button is pressed.

0 Kudos
Message 2 of 23
(2,990 Views)

Once you start talking about lots of local variables I suspect that the overall design is not very robust. Have you looked at the JKI State Machine? What you should do in your state machine is have a way to check the UI regularly and see what the state of the button is. In addition, I would use an event structure to catch when the button has been pressed.

 

Another approach is to run your processes as parallel tasks from the main state machine which will primarily be used to manage the UI and kick off the processes. You can then use a notifier or queue to send a message to the running process that it should stop running.

 

Also, it is far easier to provide help if you post your code. Or at least post an example which represents your code.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 3 of 23
(2,989 Views)

@Mark_Yedinak wrote:

Once you start talking about lots of local variables I suspect that the overall design is not very robust. Have you looked at the JKI State Machine? What you should do in your state machine is have a way to check the UI regularly and see what the state of the button is. In addition, I would use an event structure to catch when the button has been pressed.

 

Another approach is to run your processes as parallel tasks from the main state machine which will primarily be used to manage the UI and kick off the processes. You can then use a notifier or queue to send a message to the running process that it should stop running.

 

Also, it is far easier to provide help if you post your code. Or at least post an example which represents your code.


 

No, I'm saying that the amount of local variables needed would be high should that particular method be chosen (and hence why I've not gone with that route), not that they are. And...yes, I posted that an event structure in a separate loop might be a solution but I'm uncertain of where it might fit where the button can be read by the state machine loop, esp if the button is a latch.

 

The reason for not posting sample code has also been stated....that it became an endless loop that I only managed to stop by timing luck.

 

Also I've been avoiding producer/consumer queues because this is a Subvi that i I'm dealing with so I'm trying to stick with a state machine and the Main vi already has a producer/consumer queue and because the sychronization steps in this subvi are important whereas it's not guaranteed in a producer/consumer loop. And if the user were to press the OK multiple times it would just keep enqueuing the same thing.

0 Kudos
Message 4 of 23
(2,977 Views)

If your processes are already in subVIs, that with some minor modifications you can can have your main state main run them as a parallel task. Use a message from the main state machine to the subVI processes to trigger the stop condition. DO NOT place a long running process in your main state machine and try to make your processes handle or look for UI events. This is a bad design. As Bert stated above, the goal is to separate your business logic from your UI processing. Your subVIs could be their own state machines/queued message handlers with one of the states being to check for new massages.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 5 of 23
(2,970 Views)

You can solve the "button detected more than once" problem with queues by setting the max queue size to 1 or with user events by flushing the event queue in the "button pressed notification" user event handling case.

 

flush.png

0 Kudos
Message 6 of 23
(2,961 Views)

@Mark_Yedinak wrote:

If your processes are already in subVIs, that with some minor modifications you can can have your main state main run them as a parallel task. Use a message from the main state machine to the subVI processes to trigger the stop condition. DO NOT place a long running process in your main state machine and try to make your processes handle or look for UI events. This is a bad design. As Bert stated above, the goal is to separate your business logic from your UI processing. Your subVIs could be their own state machines/queued message handlers with one of the states being to check for new massages.


Once again, that is not what is being the done here. The mainVi is its own producer/consumer queue and is as basic as it comes, the user is directly interacting with the Subvi's front panel through a subpanel and the SubVi is its own state machine (which is what I'm trying to work with here).

0 Kudos
Message 7 of 23
(2,956 Views)

 


@BertMcMahan wrote:

You can solve the "button detected more than once" problem with queues by setting the max queue size to 1 or with user events by flushing the event queue in the "button pressed notification" user event handling case.

 

flush.png


Huh, I didn't think of using dynamic events (which I haven't used before). I'll try this and see if it works.

0 Kudos
Message 8 of 23
(2,952 Views)

Yes, User Events have to be registered dynamically. Basically your Master loop will use normal events to "see" the button press and will Generate a User Event when it does. Your Slave loop will be Listening for this User Event, not the Value Change event on the button itself. This way, the UI doesn't need to know what the Slave loop is doing, it can just send updates to its hearts content, and the Slave loop can ignore them however it wants. It decouples responsibilities nicely.

0 Kudos
Message 9 of 23
(2,934 Views)

@nikvl wrote:

@Mark_Yedinak wrote:

If your processes are already in subVIs, that with some minor modifications you can can have your main state main run them as a parallel task. Use a message from the main state machine to the subVI processes to trigger the stop condition. DO NOT place a long running process in your main state machine and try to make your processes handle or look for UI events. This is a bad design. As Bert stated above, the goal is to separate your business logic from your UI processing. Your subVIs could be their own state machines/queued message handlers with one of the states being to check for new massages.


Once again, that is not what is being the done here. The mainVi is its own producer/consumer queue and is as basic as it comes, the user is directly interacting with the Subvi's front panel through a subpanel and the SubVi is its own state machine (which is what I'm trying to work with here).


Perhaps we could provide better information if you include ALL of the details in your posts. This is the first time you mentioned using sub panels. Where is your stop button located? In the subVI inside the subpanel or in the main VI. Regardless, you need to provide some type of messaging between your main state machine and your subVIs. Whether that be via queues, user events  or notifiers.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 10 of 23
(2,933 Views)