Academic Company Events NI Developer Zone Support Solutions Products & Services Contact NI MyNI

Document Type: Tutorial
NI Supported: Yes
Publish Date: Sep 6, 2006

Developing a LabVIEW Real-Time Application for FieldPoint

7 ratings | 2.57 out of 5
Print

Overview

This document introduces and explains concepts and programming techniques used in developing LabVIEW Real-Time applications for FieldPoint.

Introduction

Before you start developing your application, decide whether you need a true real-time application. If not, you can develop a FieldPoint distributed I/O application in LabVIEW Real-Time just as you would with regular LabVIEW. Just keep in mind that some LabVIEW features are not supported in LabVIEW RT and that the FieldPoint controller has limited memory. If you need to create a true real-time application, the concepts and programming techniques in this document will be of great help to you.

Defining Determinism


Real-time does not necessarily mean faster. A real-time system is one in which processes are executed within a specific time period. In other words, real-time actually means on time.

Real-time applications are also called deterministic. The amount of determinism in a system describes how reliably the system responds to events or performs operations within a given time limit. All systems have some jitter, or variation in execution time, but the variation in a real-time system is much smaller than the variation in a non–real-time system.

The FieldPoint RT controller has a real-time operating system (RTOS). By contrast, a PC operating system such as Windows is not real-time. The RTOS is necessary, but not sufficient, to achieve determinism in a FieldPoint real-time application. In addition, the LabVIEW application must be developed in such a way that the deterministic, time critical VI always executes within the time limit with minimum jitter.

The most important concepts to understand when developing a LabVIEW Real-Time application are multithreading, priority, and shared resources.

Multithreading and Time Critical Priority


LabVIEW can break an application into multiple threads of varying priorities. This is called multithreading. Threads are independent subprograms that run within a program. A subVI, for example, is a thread of a VI. LabVIEW can assign different priorities to threads, and the highest priority a thread can have is time critical priority.
In a FieldPoint real-time application, only one thread, or subVI, should be set to time critical. The time critical thread is usually the one that monitors and controls the FieldPoint I/O modules. The time critical thread can have only one while loop in it.

Setting a VI as Time Critical
1) Right-click the VI icon and select VI Properties.
2) In the VI Properties dialog box, select Execution.
3) On the Priority dropdown menu, select time critical priority (highest).

Figure 1. Setting a VI to time critical priority

Having a thread set to time critical can cause starvation. Starvation happens when a higher-priority thread consumes all system resources and does not allow lower-priority threads to execute. For instance, a time critical VI could keep you from communicating with the controller because communication tasks are assigned a lower priority. To avoid starvation, use the sleep functions (Wait until Next ms Multiple.vi or Wait.vi) to put the time critical thread to sleep long enough for other, lower-priority threads to execute.


Figure 2. This while loop in a time critical VI has a sleep
function to avoid starving lower-priority threads.


Having a subVI or thread set to time critical may not be enough to make a LabVIEW application deterministic. Other techniques can help to ensure that the time critical thread executes without significant jitter.

Avoiding Nondeterministic Operations in a Time Critical Thread


Including nondeterministic operations in a time critical thread can add significant jitter to the thread. Avoid including any of the following types of operations in a time critical thread:
  • Network communication (to host PC, other FieldPoint banks, etc.)
  • Serial port communication
  • File I/O (data logging)
  • Semaphores
  • Property nodes

    Transferring Data between Threads

Some applications consist solely of one time critical VI that monitors and controls the FieldPoint I/O modules. Other applications have two or more threads: one time critical subVI for I/O control and monitoring, and others with lower priority to perform nondeterministic operations.

If data must be transferred between the time critical thread and any of the other, lower-priority threads, use functional global variables or RT FIFOs to avoid jitter in the time critical thread.

A functional global variable is a subVI set at subroutine priority that contains a while loop with a nested case structure for read or write access. Select the Skip Subroutine Call If Busy option for the functional global variable. This option prevents threads from waiting for the variable to be available before taking it. Failing to select this option causes jitter in the time critical VI.

Figure 3. Right-click the functional global variable
and select Skip Subroutine Call If Busy.


Figure 4. VIs in your application can set the mode to Read
and read from the A Out and B Out terminals.


Figure 5. VIs in your application can set the mode to Write and
write to the A In and B In terminals.


Figure 6. Another VI accesses the global variable.

One disadvantage of using functional global variables is that old data is overwritten even if it has not been read. If you are concerned about losing data while transferring it to a different thread, use RT FIFOs.

RT FIFOs are like regular LabVIEW queues, except that they allocate enough memory to store up to n elements of a user-defined numeric representation. Do not use LabVIEW queues as they introduce jitter.

One disadvantage of using RT FIFOs is that data cannot be accessed arbitrarily or in blocks. RT FIFO elements must be read from the queue one element at a time.

The following example uses RT FIFOs to transfer data between a subVI (icon in red) and the while loop of a time critical VI.

Figure 7. Use RTFIFOCreate.vi to create two FIFOs: One reads
from the subVI and the other writes to the subVI.



Figure 8. Example subVI


Use RTFIFODelete.vi to remove the FIFOs from memory at the end of the time critical VI.

IMPORTANT: The RT FIFO VIs were not included in LabVIEW 6.x, but you can get them from the
NI Developer Zone (see the links below).

LabVIEW Shared Resources


A shared resource in LabVIEW Real-Time is anything that can be used by only one process at a time. Shared resources include global variables, the memory manager, non-reentrant subVIs, single-threaded DLLs, networking functions, and file I/O.

If a lower-priority thread is using a shared resource, the time critical thread has to wait until the lower-priority thread releases it. This waiting time is reflected as jitter in the time critical thread.

Follow these guidelines when using shared resources in a LabVIEW Real-Time application:
1) Do not use regular global variables, networking functions (TCP, UDP, Logos, DataSocket, VI Server), handshaking protocols (serial), file I/O functions, or single-threaded DLLs in the time critical thread.
2) Configure subVIs used by both the Time Critical thread and a lower-priority thread for reentrancy. (Right-click the subVI icon, select VI Properties, then select Reentrant Execution.)

Figure 9. Making a subVI reentrant

3) Use the memory manager properly:
a. Remove all memory allocations from the time critical thread.
b. Allocate memory statically to avoid conflicts caused by multiple threads trying to access the memory manager at the same time.
c. Allocate arrays outside the time critical thread to avoid shared resource conflicts. Always allocate enough space for the largest array size that the VI will encounter.
d. Select appropriate data types for all data items.
e. Use inplaceness (the ability of a function to reuse memory buffers) when possible.

Figure 10. The Initialize Array function allocates the memory required by an array writing to an
analog output channel. The Replace Array Subset function writes values to channels.

Other Recommendations:


1) Avoid using property nodes in your application. In general, LabVIEW Real-Time does not support property nodes for deployed applications. Also, property nodes reduce the determinism of a thread. Use property nodes only for updating indicators and controls on remote panels.
2) Be aware of the memory limitations of the FieldPoint controller. Avoid wasting memory. For example, avoid using the Build Array function in a loop because it allocates new memory every time the loop iterates, and only the last space of memory allocated will be used.
3) Use the FieldPoint controller LEDs to indicate the status of your application. For example, you can have your application make the LED blink to indicate that the application is running.
4) Avoid using too many front panel controls and indicators.
5) Use Logos instead of DataSocket when communicating with another FieldPoint module or PC over Ethernet.
Related Links:
Real-Time FIFO for Deterministic Data Transfer Between VIs.
Real-Time FIFO Example
LabVIEW Real-Time Memory Management
Preallocating Arrays for Deterministic Loops
7 ratings | 2.57 out of 5
Print

Reader Comments | Submit a comment »

 

Legal
This tutorial (this "tutorial") was developed by National Instruments ("NI"). Although technical support of this tutorial may be made available by National Instruments, the content in this tutorial may not be completely tested and verified, and NI does not guarantee its quality in any way or that NI will continue to support this content with each new revision of related products and drivers. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).