Data Acquisition Reference Design for LabVIEW


The Data Acquisition Reference Design provides a framework upon which you can build and expand a custom application. The reference design’s core functionality involves configuring data acquisition, acquiring data, logging data to disk, and displaying data. It is built on top of other LabVIEW software components in order to maximize software reuse. This is not designed to be a fully featured application, but rather a starting place for customization rather than a blank block diagram. To meet your needs, some customization will be required. The goal of this document is to explain the overall software design of the system.


Software Architecture

The main software architecture consists of four primary processes as shown in Figure 1.

Figure 1 - Main Software Architecture

These processes perform the following tasks:

  • Handle all GUI events from the main user interface.
  • Process messages from user interaction or other external processes.  Additional display windows or ‘plug-ins’ can be launched from this process.
  • Acquire data continuously.  Data is sent via a queue to the data logging process and is also published via a notifier for any display windows.
  • Log data.

The messaging system between the different processes is based on the Asynchronous Message Communication (AMC) reference library.  

There are two types of data that are passed between processes: commands and data.  All of the commands are sent via AMC.  Time domain data is sent over a lossless mechanism (queue) and a lossy mechanism (notifier).  The design decision was made to guarantee delivery of data to the logging process while potentially sacrificing delivery to the display modules.  If the PC has enough resources, both the queues and notifiers will perform in a lossless way.  If the PC cannot handle what is being asked of it, the queue will buffer the data while the notifier will drop data.  This data flow is shown below in Figure 2. 

If you have another process which requires lossless data transfer, you can use another queue to transfer data to it.  This could be for signal processing or a data display for example.

Figure 2 - Data flow between processes

Source Code Organization

The source code is organized into multiple Project Library (.lvlib) files.  The top-level Project Library is named Data Acquisition Reference Design.lvlib (highlighted in yellow in Figure 3).  This library contains the main application, system configuration VIs, buttons, and each of the specific modules.  Each module is also a Project Library (highlighted in green in Figure 3).  The use of the Project Libraries provides a good mechanism for protecting the namespace of the VIs, defining the scope of the VIs (public, private, etc.), and organizing the VIs.  For more information on Project Libraries, refer to the Sharing Code With the LabVIEW Project Library guide.

The Project Library also provides a very convenient method for creating a new version of the code to modify by using the “Save As…” feature to the save a copy of the Project Library to a new working directory.

Figure 3 - Project view of Data Acquisition Reference Design

Code Modules

This reference design has four code modules for each of the major functional pieces of the application.  These modules are Configuration, Data Acquisition, Logging, and Display.


The Configuration module’s purpose is to provide a way for the user to configure the system interactively.  This could be through a front panel, loading saved configurations from file, or a configuration currently in memory.  The decision of the specific implementation is up to the user and developer.  Configuration is a very important piece of any application since there is typically lots of user interaction and it must strike a fine balance between features and usability. 

 There can be a wide range of implementations for configuration from very simple to very complex.  A good place to start is with the Queued Message Handler Template from AMC (


Data Acquisition

The Data Acquisition module acquires data from the configured data source.  This would typically be a hardware data acquisition device, but could also be data from a file or even simulated data.  This module must be able to acquire data in a lossless fashion and send it to other processes for logging to disk, signal processing, or display. 

Depending on the application requirements, signal processing can also be added to the Data Acquisition module or could be an entirely new module\process of its own.

The data acquisition process in the main application is a queue driven state machine (see Figure 4).  A VI is used to receive messages generated by the user (such as pushing the Start button) and to progress the state machine appropriately.  The state machine has four main states: Idle, Start, Acquire, and Stop.

Figure 4 - Data acquisition process in main application


Data Logging

The Data Logging module saves time domain data to disk.  The data is received from the data acquisition process via a queue.  The queue is a buffered mechanism which guarantees that the data path is lossless, but if the data logging process cannot write data to disk fast enough, the buffer in the queue will continue to grow and use memory.  Thought should be given on how to handle this situation such as some combination of limiting the queue size, monitoring the queue backlog, automatically stopping the acquisition and notifying the user.

The data logging process is also a queue driven state machine (see Figure 5).  A VI is to receive messages generated by the user and dictate the next state for the state machine.  The state machine consists of four states: Idle, Open File, Write to File and Close File.

Figure 5 - Data logging process in main application

Display Windows

The display windows provide a way to get immediate feedback from the data as it is being acquired.  The display windows are launched through VI Server in the Main Message Processor as reentrant VIs so that multiple windows of the same type kind can be viewed at the same time.  The display VIs must be placed in a specific directory relative to the main application.  The directory is <main>\Modules\Display. 

The display windows are built from a VI template (see Figure 6).  The Display Template.vit is based on the Queued State Machine template in AMC.  Every time new data is received from the notifier, the Process Data state is executed.  This is where any display code should be place such as channel selection or signal processing (FFT, RMS, etc).  If it is important to the display, the data can be checked for continuity so the user is informed if the display is not continuous.  This is particularly important to know in cases where signal processing like averaging or filtering is used across multiple data blocks.

Figure 6 - Display window template block diagram

Follow these recommended steps to add a new display window.

  1. Create a new display window VI.
    1. Right-click on Display Template.vit in the project and select “New from Template”.
    2. Modify the VI and save it to the <main>\Modules\Display directory.
    3. Add the VI to the Display Windows.lvlib.
  2. Create a button for the main application to launch the window.
  3. Add a “Value Change” event to the event structure for this new button.
  4. In this new event case, use AMC to send the “Launch Window” command with the new VI name as the data to the main message processor (see Figure 7).

Figure 7 - AMC command to launch FFT


User Interface Techniques

Creating an application which is functionally powerful and intuitive at the same time can be very challenging.  A lot of this challenge is in the design and implementation of the user interface (UI).  Below is a list of different techniques for implementing the user interface in LabVIEW used in this application.

  • Use a custom menu instead of the default LabVIEW menu.  An example of this is in the NVH Channel  This provides the user with only the options that apply to their specific application.
  • Implement a simple toolbar.  The main application has a simple toolbar (shown in Figure 3) implemented with customized system style buttons.  Using glyphs with the buttons generally makes the user interface more intuitive and cleaner.  Also, add tool tips to each button so the user can see a description of the button when it is hovered over.

Figure 8 - Toolbar of the main application

  • Use splitter bars on front panel that can be resized.  Splitter bars are a very useful tool when there is a portion of the front panel that needs be resized and another portion that doesn’t.  An example of this common situation is in the FFT  In this situation, the user is resizing the pane in order to get a better view of the graph so we don’t want to also resize the channel selector control as well.  The front panel (see Figure 4) uses a splitter bar to divide it into two panes.  The top pane consists of a ring control for channel selection that does not change size with the pane while the bottom pane has a graph which does scale to the pane size.  To set a control to scale to the pane, right-click on it and select the “Scale Object with Pane” option.

Figure 9 - Splitter bar for front panel resizing

  • Use tab controls and hide the tabs to give a more custom appearance.  By hiding the tabs, another mechanism on the front panel can be used to switch between the different tabs.  One example would be a toolbar on the left side of the front panel with different selections.  In Channel, a tree control is used to provide a more dynamic menu.  When a different item is selected in the tree, the associated tab page is displayed.  Programmatically changing the visible tab is very easy especially compared to doing something similar with subpanels.  Another option is to make the tab itself transparent which makes the page names appear as text on the front panel.  When the user clicks on the page name, that page appears.

Figure 10 - Hidden tabs

  • Use XControls where appropriate.  An XControl is a great way to encompass a custom user interface control that will be reused.  The XControl provides addition customization options that aren’t available with standard controls and they help to keep the main VIs code cleaner by containing all of its code with the XControl.  The main application uses the Channel Monitor XControl for quickly monitoring the status of the acquisition channels.  Figure 6 shows the Channel Monitor XControl and some of the custom “right-click” options it has.

Figure 11 - Channel Monitor XControl

For more examples of UI techniques in LabVIEW, join the UI Interest Group on’s Community area:

LabVIEW Code

For a more advanced architecture for running multiple sections of code running in parallel and sending data between them, please review this guide on Using a Queued Message Handler in LabVIEW.

Was this information helpful?