Create a responsive user interface based on two loops operating in parallel: the "producer" loop event structure responds immediately to user interactions such as button clicks and mouse movements that send commands through a queue to the "consumer" loop which performs the required tasks. Separating the state machine into two loops allows the user interface to remain responsive should a consumer task require an unusual amount of time or must wait for a shared resource to become available.
Use cases
PC-based user interface (UI) (also called human-machine interface or HMI) for a continually-running RT system controller application
Connect to and disconnect from the remote RT application as part of its normal operation
Dual-loop design with each loop referencing a common queue
Producer loop:
Event structure handles button clicks
Each button enqueues a particular consumer-loop state as a string of the form “state:params” in which the optional “:params” provides state-specific parameters
The front-panel stop button enqueues the “Shutdown” state
Guard clause (Boolean case structure) traps errors generated within the Producer Loop and shuts down both loops
Consumer Loop:
Queued state machine based on the common queue
Guard clause inspects error cluster on each loop iteration:
No error – dequeue the state inserted by the Producer Loop
Error – go directly to the “Shutdown” state
Separate the dequeued string into the state string and parameters string, if included
Case structure decodes the dequeued string from the Producer Loop:
“Initialize” – use “Invoke Node” to release the “connect” button and “Property Nodes” to disable the buttons that should only be used once the RT connection has been established
“Connect” – create the network stream writer endpoint, disable the “connect” button, and enable the system controller buttons; generate an error if the connection cannot be established within 5 seconds
“Send” – write the parameter to the network stream as the command message for the RT controller
“Disconnect” – send the “Disconnect” command message, flush the network stream to ensure that the message is received by the RT controller, destroy the network stream endpoint, and then return the buttons to their default states
“Shutdown” – signals the Producer Loop to stop by virtually clicking the front-panel “Stop” button via a “Property Node” and then stops itself by feeding a “true” constant to the loop conditional terminal
Default case – traps unrecognized state strings and inserts an error into the error cluster
NOTE: This controller has specific behavior for the “Home Security System”, but the overall structure itself is a standard and well-accepted architecture that can be easily modified for your own controllers.
See the complete Home Security System project to get an idea of how this producer-consumer state machine interacts with the RT system.
Keep in mind
Stopping both loops is a rather involved yet still understandable process that has three possible causes:
“Stop” button is clicked:
Producer Loop event structure performs two actions: (a) enqueues the “Shutdown” state at the front of the queue to ensure that this is the next state processed by the Consumer Loop, then (b) stops itself by feeding a “true” constant to its own loop conditional terminal
Consumer Loop dequeues the “Shutdown” state which performs two actions: (a) signals the Producer Loop to stop by virtually clicking the front-panel “Stop” button (in this case a redundant action because the “Stop” button was already pressed), then (b) stops itself by feeding a “true” constant to its own loop conditional terminal
Error generated within Producer Loop:
Producer Loop guard clause detects error and enqueues the “Shutdown” state at the front of the queue to ensure that this is the next state processed by the Consumer Loop
Consumer Loop dequeues the “Shutdown” state which performs two actions: (a) signals the Producer Loop to stop by virtually clicking the front-panel “Stop” button, then (b) stops itself by feeding a “true” constant to its own loop conditional terminal
Producer Loop event structure performs two actions: (a) enqueues the “Shutdown” state (in this case a redundant action because the Consumer Loop has already stopped), then (b) stops itself by feeding a “true” constant to its own loop conditional terminal
Error generated in Consumer Loop:
Consumer Loop guard clause detects error and selects the “Shutdown” state
Subsequent actions are the same as Steps 2 and 3 from the Producer Loop-generated error
LabVIEW block diagram elements
Locate these elements with "Quick Drop" (press Ctrl+Space and start typing the name); click on an icon to see more sample code that uses that element:
Example code
Connect your Academic RIO Device to your PC using USBLAN, Ethernet, or Wi-Fi. NOTE: Not all Academic RIO Devices have Ethernet and Wi-Fi connectivity options.
If using the NI myRIO 1950 or NI RIO Control Module start with the NI myRIO 1900 Archive.
Different IP address: Right-click on the "NI myRIO 1900" Device, choose "Properties", and then enter the new IP address
Different device:
Right-click on the top of the project hierarchy, select "New Targets and Devices", keep the "Existing target or device" option, and then find and select your particular device
Select all of the components under the "NI myRIO 1900" device: click the first one and then shift+click the last one
Drag the selected components to the new device
Right-click the "NI myRIO 1900" device and select "Remove from project"
Observe the indicators at the top of the “Remote Monitor” panel: the green flags designate these indicators as bound to network-published shared variables (NPSVs) hosted on the RT target. When properly connected these indicators will track the indicators on the RT system controller.
Click “Connect” to establish the network stream connection to the system controller; note the “PC host connected” indicator on the “RT Main” front panel
Click each of the now-active buttons to send a message to the controller:
“Valid Code” emulates a proper keypad sequence entry
“Reset” initializes the controller regardless of its current state
“PANIC” sends the controller directly to the “alarm” state
Click “Disconnect” to close the network stream connection
“RT Main” should continue to run regardless of the run state of “PC Main”: observe the “PC host connected” indicator on “RT Main” as you stop “PC Main” while connected to the RT target and then restart and reconnect
Event structure blocks (waits) until a front-panel button is pressed
Each event case subdiagram enqueues the associated command for the Consumer Loop
Guard clause enqueues “Shutdown” state when error is detected
Review overall structure: Consumer Loop
Guard clause enqueues “Shutdown” state when error is detected, otherwise blocks until a queued command is available from Producer Loop
“State & Args” subVI separates command and optional arguments (parameters) into two strings
Case structure subdiagram implements functionality for each command
Review overall structure: indicators and queue setup
Front-panel indicators bound to network-published shared variables hosted on RT target
No special programming required, simply place them somewhere on the block diagram
Create the command queue and enqueue the “Initialize” state
Release the queue only when both loops have stopped
Normal operation sequence: Producer Loop
Both loops block until a button is pressed – much more CPU efficient than polling, and ensures responsive user interface
Press a button to cause event structure to enqueue the appropriate Producer Loop command as a string
connect -> “Connect” command (connect to RT target)
disconnect -> “Disconnect” command (disconnect from RT target)
reset -> “Send” command with the RT controller message command “SysMgr/Initialize” as the optional argument
valid code -> “Send” command with the RT controller message “SysMgr/alert:valid”
panic -> “Send” command with the RT controller message “SysMgr/alarm”
[ESC] (Stop button) -> enqueue “Shutdown” state at the top (front) of the queue to ensure that it is executed as the next command, and select the “true” value to stop the Producer Loop
Guard clause takes no action
Producer Loop completes iteration and waits for next button press
Normal operation sequence: Consumer Loop
Guard clause dequeues command from Producer Loop
“State & Args” subVI separates command and optional arguments (parameters) joined by colon “:” into two strings
Case structure implements the appropriate action for each command
Initialize -> Unstick and enable the “connect” button and disable the buttons which are only to be used when connected; use Invoke Node and Property Nodes
Connect -> Create the network stream writer endpoint (wait up to 5 seconds before timing out), and enable the three buttons
Disconnect -> Send the “Disconnect” message to the RT target, flush the stream to ensure that it is received successfully, destroy the network stream endpoint, and disable the three buttons
Send -> Send the arguments as the message to the RT target
Shutdown -> Virtually press the front-panel stop button with a Property Node, and select the “true” value to stop the Consumer Loop
Default -> Throw an error for unrecognized command from Producer Loop
Consumer Loop completes iteration and waits for next command in the queue
Normal shutdown sequence: “Stop” button
Producer Loop enqueues the “Shutdown” state at the front of the queue to ensure that this is the next state processed by the Consumer Loop and then stops itself
Consumer Loop dequeues the “Shutdown” state and stops itself
Queue is released because both loops have stopped
Error-induced shutdown sequence: Producer Loop
Guard clause detects error and enqueues the “Shutdown” state
Remaining sequence is the same as normal shutdown sequence
“Simple Error Handler” function reports the detected error
Error-induced shutdown sequence: Consumer Loop
Guard clause detects error and selects the “Shutdown” state
Remaining sequence is the same as normal shutdown sequence
“Simple Error Handler” function reports the detected error
Tips to modify the controller
Create a new button
Create associated event structure subdiagram
Create associated case structure subdiagram
Locate the Invoke Node and Property Node
Create a custom error message with Error Ring
For more information
Effective LabVIEW Programming (http://www.ntspress.com/publications/effective-labview-programming/)
An excellent textbook by Dr. Thomas J. Bress covering all aspects of system design; Chapter 27 describes the "Event-driven Producer-Consumer State Machine" in detail. Download all of the code examples from this textbook: follow the link above, select "User Resources", and then "All VIs".