Basics of Building a LabVIEW Architecture
07 Jun 2016By Crystal Li, Biomedical Engineer & LabVIEW Developer
Hello! My name is Crystal and I am a certified LabVIEW Developer. LabVIEW is a great platform for quickly building awesome-looking user interfaces (UI). It is great for someone who doesn’t have a programming background to develop complex programs with a user interface, hardware communication, data acquisition, data analysis, file IO, and error handling. With all these components, it can be easy to get overwhelmed when building an application and end up with something like this:
While the above code may still be functional or even readable to the original programmer, it definitely will not be fun to modify or expand upon. There are ways to build the foundation of the code so that it becomes extensible and modular. Not only will your future self appreciate it, but so will anyone else diving into that same project. With the right architecture, you could turn that hectic block diagram into something much simpler:
There are plenty of LabVIEW design patterns to choose from when building your code; I’m going to cover one that we use frequently at Aztera called the “Multi-threaded Queue Message Handler”. At its core, this architecture is made up of multiple queued message handlers running in parallel and communicating with each other through the application program interface or API. Instead of placing all these components on one block diagram, they are all separated by libraries, each with their own block diagram, VIs, and controls (Figure 3). When adding a new UI or hardware, it becomes a matter of copy-and-pasting the libraries (Figure 4). The Main VI will look something like Figure 2 with all the Module Top Level VIs there, making it more straightforward for an outsider to know where to go to debug the program.
Inside each Module Top Level VI is a queued message handler with an event and message handling loop (Figure 5). This is where the magic happens. Whenever an action is written to this module, the bottom loop will dequeue that action along with the data sent with it and write it to the case structure. Then the action will be performed according to the code written for that case. The top loop can be used to handle user interface actions, data acquisition, and timeout events.
To write something to a module, the action and data can get bundled up into a cluster (Figure 6) and enqueued to the queue reference acquired using a functional global variable (Figure 7).
This is the basis for how we construct LabVIEW projects that require numerous communication protocols and UIs. Building an architecture may require some planning and time, but this investment will save you more in the long-run. Like a skyscraper, creating a strong foundation will help it stand the test of time.