09-12-2019 02:58 AM
The simple solution in this case is to add a Reconnect case which'll run if there's an error in Connect. The others are simple enough, just use a Select to choose which state should be next.
/Y
09-12-2019 08:27 AM
I understand. So its best to get down to the fundamental imperative style and just explicitly program what I want rather than depending on State and Actions. Did I get you right?
09-12-2019 09:48 AM
@asukumari wrote:
I understand. So its best to get down to the fundamental imperative style and just explicitly program what I want rather than depending on State and Actions. Did I get you right?
I would argue that a true state machine implementation would be a more flexible solution and allow for more enhancement in the future.
09-12-2019 11:14 AM
@asukumari wrote:
I understand. So its best to get down to the fundamental imperative style and just explicitly program what I want rather than depending on State and Actions. Did I get you right?
I'm not sure if that was directed at me or not, but if so, I'll try to answer. Depending on state and actions is good, it's just the wrong tool for this particular question. Queuing up actions is a poor way to program- queuing up messages is a great way to program. If you're queuing actions, you'd be better off 99% of the time to just use subVI's, as you can change and direct flow as needed.
This program is a good example. Say you have an Actions queue, and you send a Connect action then a Send Data action to send a "Set Voltage" action then a "Set Current Limit" action. If your Connect succeeds, but your first Set Voltage action fails, now you still have a Set Current Limit action stuck in the queue, and you have to push a Disconnect-Reconnect-Set Voltage into the front of the queue to try again. You end up having to handle the whole queue manually, which is a pain, and it's quite tricky to handle individual "dumb" actions like that.
Contrast this with a queued *message* handler wrapped around a state machine. Now, the main loop sends a Connect *message*. This message can look at the internal state variable (I use enums) and say hey, I'm already connected- don't do anything. Contrast this to a connect *action* which will just call the Connect process no matter what the previous state was. The *message* can then decide if it needs to run Connect.vi or not, and if so, can set the internal state variable to Connected.
Next you have your Set Voltage *message* which can look at the internal state variable. If it's Connected, great, call Set Voltage.vi. On the error line from that, and in the same message handling structure, decide if there's no error, great, don't change the state. If there is an error, you can decide (based on the needs of your program) to either Disconnect-Reconnect-Retry, or to run Disconnect.vi, set the internal state to Disconnected, and display an error to the user (e.g., "Send message failed, please ensure the device is plugged in and try to Connect again")
Basically, keep the State of the State machine in a shift register local to the message handling loop. This loop will try to dequeue *messages*, not *states*, and each message can decide what to do by looking at the current State in the shift register for that independent loop.