09-14-2016 05:30 PM - edited 09-14-2016 05:34 PM
Hi,
I am trying to create a state machine in order to control a conveyor, mixer, pump, and linear actuator. Each component runs in a sequential order all the time, so I figured that using a state machine would probably be the best program architecture.
The problem I am experiencing is that there are some states that require extra time before the next state begins. For instance, I need to be able to run the pump or the mixer for a different period of time. I understand that simply using the wait VI is not a good idea since it removes the ability to stop the program in the chance that something goes wrong (at least until the wait function completes execution). I tried using clock timing in order to force the program to wait for a specified time between states, but I ended up with nested while loops for each state that require separate stop buttons which ends up making the program convoluted (this is what is seen in the attached VI).
I looked on other threads that mentioned using notifiers or event structures, but since I am using a state machine, I am not sure how to use them with mutliple states.
If there is any way to force timing between states while maintaining stop button control and possibly the ability to run other code during the wait, please let me know. I have attached the VI I am working on, and the main focus is on the "Wait for hatch to open" state.
Thanks.
Solved! Go to Solution.
09-14-2016 05:48 PM
Make a common state called wait that you can use.
In this state put an event case with a timeout for your wait period. Add a case for a stop button. If the cases timeouts then go to the next case. If the user hits stop then go to your safe shutdown state sequence.
mcduff
09-14-2016 05:49 PM - edited 09-14-2016 05:50 PM
What you need to do is have the wait state call itself if the wait condition has not completed. Here is a very quick example to show the idea. But what this does is allow for checking of stop conditions or other things you have to be constantly aware of.
09-14-2016 05:51 PM
Can wiring the wait time to the timeout case in an event structure that the stop button operates with work? That way it will wait the time specified unless the stop button is pressed, and if the stop is pressed the event will immediately change to the stop event.
09-14-2016 05:55 PM
State machines can be quite limiting actually, but since youre already started with one a simple solution to your problem could be to put a secone loop with an event structure outside the state machine and write to a local variable if the state of the stop button changes. Youll have to reinitialize the stop button though.
Attached is a simple example.
09-14-2016 06:07 PM
@matt198717 wrote:State machines can be quite limiting actually, but since youre already started with one a simple solution to your problem could be to put a secone loop with an event structure outside the state machine and write to a local variable if the state of the stop button changes. Youll have to reinitialize the stop button though.
Attached is a simple example.
A hammer is quite a limiting tool also, but if the problem is a nail, then it's the right solution...
09-15-2016 10:18 AM
Hi crossrulz,
Thanks for the reply.
This seems like a solution that would work, but how would I be able to tell the program which state to proceed to next if the wait state is shared between the other states? I assumed that the strings are supposed to represent the states, so now I am confused about a solution to change the "Complete" state to correspond to the next state (which changes depending on the previous state). Also, I would need to be able to change the Time Target depending on the previous state as well, but I don't want to have to use shift registers that carry values that don't change.
Thanks.
09-15-2016 10:24 AM
I would suggest that you look into the JKI State Machine and refactor your code. You can download it via VIPM. It has a built in event case.
There are lots a things that you can do to make your code better, for example, have a State called current status, that way you wire directly to the indicator not write to a local variable.
Cheers,
mcduff
09-15-2016 10:28 AM
victorzhao wrote: but I don't want to have to use shift registers that carry values that don't change.
What I do is use strings for my state and then add parameters to the string. So I might have a state string of "Wait:1.5:Complete". I would use Match Pattern to get the state to actually go into (for the case selector) and then parse the rest of the string to know to wait 1.5 seconds and go to the "Complete" state when the time has elapsed. The JKI State Machine does something very similar.
09-15-2016 11:05 AM
Let your state machine shift register be a cluster. First item is an enum to tell the next state to go to. Second item is a numeric that would define how long to wait if the next state is a wait. Third item is another enum like first to tell which state to go to after the wait ends.
Beginning of your state machine loop, unbundle the first item to know what state to go to. In your wait state, when you've determined the wait is done, unbundle the 3rd item. Set the state machine cluster's first item to be that same enum so it goes onto the next state. Basically let the state machine's shift wire carry along with it other state state, not just the next state, but also what the following state would be when the next state is complete (in the event there are multiple choices.)