06-04-2010 01:23 PM - edited 06-04-2010 01:26 PM
You should read over the following Application Design Pattern articles:
Application Design Patterns: State Machines
Application Design Patterns: Master/Slave
Application Design Patterns: Producer/Consumer
Using Queues to Create a More Flexible State Machine
Also note that LabVIEW can generate these designs using templates. When you select File -> New expand VI -> From Template -> Frameworks -> Design Patterns. This way you'll have them available even if you don't have tbob's examples.
06-04-2010 01:32 PM
Wow, I truly appreciate your patience with me.
So if I get this right...
I would have a case structure with cases like this:
Initialize - set default values to controls and indicators and go directly to the listen case
Listen - containing an event structure, with events in the event structure for the different buttons, etc.
Start Keyboard - start my keyboard subvi, which will return a string and go directly to the search case
Search - see if string can be found in array go back to the listen case
End - stop while loop
...changing the subject...
I can't say I understand what you're trying to show me with the cluster you called Local Variable in the string state machine example...
I looked at the ni example of state machines and they use an enum to wire to the shift register, but you wire a string constant...I'm a bit confused about what I should use here
Thanks
06-04-2010 02:09 PM
KSU Flyer wrote:Wow, I truly appreciate your patience with me.
So if I get this right...
I would have a case structure with cases like this:
Initialize - set default values to controls and indicators and go directly to the listen case
Listen - containing an event structure, with events in the event structure for the different buttons, etc.
Start Keyboard - start my keyboard subvi, which will return a string and go directly to the search case
Search - see if string can be found in array go back to the listen case
End - stop while loop
That's a good start. Remember that those would be the states. You may want to use a producer-consumer architecture to separate the UI from the actual operation.
I can't say I understand what you're trying to show me with the cluster you called Local Variable in the string state machine example...
It's just there to carry around state data so all states have access to the data. Think of it as a variable that has program-level scope for text-based speakese.
I looked at the ni example of state machines and they use an enum to wire to the shift register, but you wire a string constant...I'm a bit confused about what I should use here
You can use either one. The enum-based one is typically done by making the enum a typedef so the state names are change in only one location. A string-based state machine has its avantages and disadvantages. One big disadvantage is that you can easily make mistakes as the text has to match between the string constants/output and the case names. One big advantage is that you can pass along any custom data for the state by employing a mechanism like <state name><delimeter><state data>. The state machine VIs I use work like this. Also, the JKI State Machine works this way too. Another disadvantage is that unless you set the case for case-insensitive match then the upper/lower case has to match as well. The enum has the big advantage that the case items get labeled automatically.
There is no "right" solution. My suggestion: use the enum for now.
06-04-2010 02:46 PM
I agree that enums are better than using strings. But I'm just too lazy to create a type def.
Actually, if I anticipate future changes and want scalability, I will use enums. Quick and dirty, I use strings. If I want to be able to stack a bunch of states at one time, I use a queue. KSU FLyer, don't worry too much about what to use yet. This will come in time with practice. For now concentrate on the actual state machine. For starters, use the enum.
06-04-2010 04:06 PM
With all of your help, I think I have a rough state machine in place already! I started with a string state machine, so we'll just keep working from here and go enum later maybe.
If you would, have a look at the attached...
Where I'm not so sure what best practice is in in the listen case, and in the event case searchResults. As you can see a value is assigned to selectedValue indicator. However, what is the best way to initialize this value to an empty string when the subvi is called? Do I have to run shift registers all over to avoid using property values? More generally, I have an initialize case, but not sure how to write default values to controls and indicators.
Thanks again! Mike
06-04-2010 04:41 PM
06-04-2010 04:57 PM
06-04-2010 05:07 PM
KSU Flyer wrote:With all of your help, I think I have a rough state machine in place already! I started with a string state machine, so we'll just keep working from here and go enum later maybe.
If you would, have a look at the attached...
That's a pretty decent start. A couple of FYIs:
Where I'm not so sure what best practice is in in the listen case, and in the event case searchResults. As you can see a value is assigned to selectedValue indicator. However, what is the best way to initialize this value to an empty string when the subvi is called? Do I have to run shift registers all over to avoid using property values? More generally, I have an initialize case, but not sure how to write default values to controls and indicators.
As noted by ricky, you can selectively reinitialize by creating the "Reinitialize to Default" Invoke node for a specific control/indicator.
06-04-2010 05:29 PM
One more problem. In the listen case, on the right border of the event structure, your terminals are set to "Use default if unwired". Not good. When searchResults button is double clicked, what is the next state? Since the default for a string is an empty string, that is what will be passed along as the next state. The case structure has no blank string case, so it will use its default case, which is "listen". This may be what you want. If this is so, wire a string constant with "listen" to the next state terminal.
Right click on the two terminals on the right side of the event structure and uncheck the Use default if unwired box. This will break the vi because you have unwired terminals. Wire them. I just told you to wire the terminal in the searchResults event case. Now wire something in the Cancel event case. It doesn't matter what string you use because the outer loop will stop. Just use "cancel" again.
For the next terminal, wire the left side terminal to the right side terminal in event cases that are unwired. Here also, if you use the Use Default if unwired option, the default is an empty array, and you lose whatever was there before.
You have the same problem with the terminals on the right side of the main case structure. You have nothing wired in the initialize case. Again, uncheck the Use Default option, and wire a empty string array to the terminal. The initialize state is where you initialize the shift registers and such, so always wire something here.
Besides all that, you did a good job for your first state machine.
06-04-2010 05:44 PM