I’ve had an interesting problem to solve at work this week involving creating, buffering, and then transmitting GPS signals using an NI RFSG but being able to alter those signals on the fly.
For the project as a whole we committed to using the Actor Framework early on as it is quite a complex asynchronous process application with significant inter-process communication with a strong requirement to be able to chop and change modules as well as adding new ones in at run time.
This admittedly could also be done using daemons, but the benefits of Actor such as the robust inter-communication, ease and speed of putting an infrastructure in place and the ability to very easily make an Actor Framework remote controllable and run headless via TCP/IP (which is a very common request from clients) made it a perfect fit for this job.
However, this particular problem also had state machine written all over it, and having tried to use Actor before to do state machines where you have a different VI for each state I have found that they very quickly become very difficult to debug and follow so I thought I’d have a crack at putting together something that would provide all the benefits of Actor and a single VI with a state machine and this is a demo I came up with to prove the design.
It is certainly not the most inspired demo you will ever see, it is simply an overridden Actor Core GUI with a FSM running behind it that simply cycles through states to set 4 colour boxes on the GUI and allow you to start/stop the cycling, and change the interval between each box being set.
On the GUI We have a State indicator which is set from the state machine itself and a Play, Stop, Reset Button, and FSM Interval(ms) control that trigger events in the Actor Core override and enqueue message handlers to be executed on the core.
The FSM itself is a single VI that holds its state information in the Actor private data and simply iterates from an idle state to 4 states which set the colour of each color box with a one iteration delay between each.
Now the cool bit, and one of the reasons I really like Actor. To run this as a state machine you use the Time-Delayed Send Message.vi to instruct the Actor Core to enqueue the state machine at certain intervals.
There are actually two ways you can do this, you can use the Time-Delayed Send Message.vi with the iterations option set to to 0 – this will enqueue the state machine at a set frequency ad-infinitum which is great, but I personally prefer the option to use Time-Delayed Send Message.vi with the iterations option set to 1 which means it will do a single enqueue of the specified message with a time delay which I do once in the overriden Actor Core to get the process started, and then at the end of every iteration of the FSM.
My main reason for this preference are primarly debug; If you use the infinite enqueue option (0) and you run the vi that is being enqueued with execution highlighting switched on, messages do not stop getting en-queued in the background so as soon as you turn off highlighting all those messages that have been en-queued will get executed one after another without any delay.
Another reason for my preference is that by en-queuing on each iteration it also means that you can alter you interval rate, so for instance when the state machine is in IDLE I enqueue an element with a delay of 1 second, then when the play button is pressed the interval is set from the from panel FSM Interval control – it is a neat little feature that I can think of many uses for i.e. the classic CLD car wash exam where you have to time each state using an elapsed time vi – well here you could simply use constants for going between states. I have also used Time-Delayed Send Message.vi quite extensively for data logging use cases where i have found it’s time to be remarkably accurate.
In terms of the event handlers, well they simply set the next state of the FSM (but could obviously do a lot more) – another really nice feature of Actor in this context is that because all messages are executed in-line with the FSM it makes it very easy to debug and integrate user events with the state machine – although one thing to watch out for here is that if you are putting very small or possibly no delays between your FSM being en-queued for execution, it is worth giving you Event Handler messages high priority to ensure they always get executed as soon as an iteration of the FSM has finished or before if it is in a delayed state.
Link below for project – possibly obvious, but run Main.vi to get started – LabVIEW 2013.
Hopefully it’s been of use to someone somewhere, and thanks for reading.