LabVIEW OOP to Create a Class for the Measurement Tool Chest
Each inherited class has to provide “overrides” for certain base class methods that the architecture needs
The Measurement Tool Chest introduced is an architecture that relies on a set of inherited classes to perform measurements specified by each inherited class.
Each inherited class has to provide “overrides” for certain base class methods that the architecture needs. Specifically, as mentioned in the last issue, the methods that each inherited class needs to provide are for initializing, configuring, and a way to save results. This issue will show how to create such an inherited class.
Base Class Overview
In this example, each inherited class needs to override certain base class methods. The project window below shows the design of the base class.
Figure 1 – Plugin base class project tree
As an example of one of the methods that needs to be overridden in the inherited classes, look at the front panel of the ‘Initialize.vi’ base class method. Note that the upper left and upper right connector terminals have a dashed line around each of the terminals. This visual attribute indicates that the method can also accept inherited classes.
Figure 2 – Front panel of base class Initialize method
The other public method in the base class that needs to be overridden is the ‘Set Run Data.vi’. The ‘Abort VI.vi’ does not typically need to be overridden, since all this method usually does is abort the VI referenced in the subpanel (although it might also close a handle to a device before aborting). There is also a pair of private methods in the base class for set/get of the ‘Run Mode’. These methods are used in this application Tool Chest app, but we can rely on the base class to provide this support since the inherited classes don’t need to modify its behavior.
Creating a New Inherited Class
Create the Class
A “Pulse Frequency” measurement class would be a good addition to the Tool Chest.
Right button on the ‘Plugins’ folder and select ‘New>>Class’, as shown below.
Figure 4 – Project tree after adding a new class showing class private data
This control defaults as an empty cluster. For object initialization and configuration, this cluster could hold many details, such as info about the instrument being used to make measurements (e.g., the DAQ device name). The ‘Initialize.vi’ method that needs to be overridden gives an opportunity to set these details, as will soon be shown. For this article, the class data will hold an integer for setting a number of readings to average.
Define the Inheritance
Now that the class is defined, the plug-in design of this application needs this new class to inherit from the base class. Right click on the Pulse Frequency.lvclass and choose the Properties menu item. On the left side of the dialog that appears, select the Inheritance item. Press the ‘Change Inheritance’ button and choose ‘Plugin Base.lvclass’, as shown below.
A dialog appears asking for the name of the new class. As you can see in the following project tree, the new class was named ‘Pulse Frequency’ and LabVIEW automatically created a private typedef class control for the class data.
Figure 5 – Choose the base class
Press the ‘Inherit from Selected’ button, and the Pulse Frequency class now inherits from the Plugin Base class.
Adding a Dynamic Dispatch Method for Initialize
Whenever a new measurement tool is selected in the user interface, the main application calls the base class methods as shown in the snippet below (from Figure 2 in the previous issue).
Figure 6 – Snippet from “change plugin” event block diagram of application
The base class provides the functionality for the ‘Abort’ and ‘Set Run Mode’ methods. But, as discussed above, the ‘Initialize’ method needs to be overridden for each inherited class so that when the base Initialize VI (right most VI in the snippet above) is called, LabVIEW looks at the actual class type on the wire and at run-time determines which class’s Initialize method should actually be called. Thus, the inherited Inherit method class “overrides” the base class Inherit method.
Here’s how to create an override method. Right button on the ‘Pulse Frequency.lvclass’ and create a new override VI using the menu as shown.
Figure 7 – Create a new override VI
This menu opens a dialog that shows all the methods available for overriding. You want to choose the Initialize method to have LabVIEW automatically create the Initialize method for the inherited class. Here’s how the block diagram of the new VI appears.
Figure 8 – Block diagram of automatically created inherited Initialize method
Note that the Plugin Base class Initialize method is called. Since the “new override VI” step was taken, this VI expects that you may want to call the parent (e.g., Plugin Base) class method in case that method does something useful for the inherited class (so you don’t have to rewrite more code than needed). In fact, in the case of this Initialize method, there is functionality that the base class provides. Specifically, it saves the subpanel reference for later use when the subpanel VI needs to be invoked.
Now all you need to do is add the rest of the code to complete the initialization of the Pulse Frequency object. Here’s a completed block diagram for your review.
Figure 9 – Block diagram of Initialize method for Pulse Frequency
Another Way to Dynamic Dispatch
While selecting the “VI for override” menu item above you may have noticed that other options exist. For example, you could have chosen the “VI from Dynamic Dispatch” as shown below.
Figure 10 – Menu for adding a new dynamic dispatch method
This approach creates an “unnamed” VI method with the appropriate terminals for a dynamic dispatch of this Pulse Frequency class. Importantly, the properties for the terminals that connect to the object control and indicator are set automatically to “Dynamic Dispatch Input (Required)” and “Dynamic Dispatch Output (Required)”, as needed for designating this VI as a dynamic dispatch VI.
This VI is still unnamed, and needs to be saves as ‘Initialize.vi’, since that’s the method to be overridden. Take care to name it exactly the same as the base method.
One trick with this approach requires the use of ‘Call Parent Method’ to assure that the call to the base Initialize method actually calls the base class method.
Comments on Block Diagram for Initialize
Here are a couple of points about the code in the Pulse Frequency block diagram.
References
To run the Measurement Tool in a subpanel, a reference to the subpanel and a reference to the VI that will run in the subpanel are needed in this Initialize method. Refer back to the snippet above from the “change plugin” event and note how the subpanel reference is passed into the Initialize method. Any inherited class will use that same reference, so no special coding is required for any inherited class. However, the VI displayed in the subpanel is unique to each inherited class, so it first appears in the Initialize method overridden in the inherited class. A hardcoded VI reference is used here for simplicity. Note that this reference makes its way to the Set VI Reference method of the base class so the base class can launch the appropriate VI when the subpanel becomes live.
VI and Object Data
Suppose you had multiple instances of this Pulse Frequency class. Each Pulse Frequency object needs to hold its own data (e.g., device name, channel number, measurement period, reference clock rate, and so on), and that data needs to make its way to the VI doing the measurement. This data transfer happens by copying the Pulse Frequency object data into the front panel control of the subpanel VI. The VI method ‘Ctrl Val.Set’ is used here.
Also, the subpanel VI needs to know the mode it will run. That mode is passed from the base class via the Read Run Mode method to the subpanel VI control, again using ‘Ctrl Val.Set’
Complete the Initialization
Finally, the base class Initialize method is called, in case any additional initialization is required by the parent object. This technique of pushing a method call down the inheritance tree is typical, but not necessary, and in some cases is just wrong. For example, the base initialization might overwrite configuration parameter values that had just been set by the inherited class.
What else?
What else is needed to complete the inherited class? Here’s a list.
The ‘Set Run Data’ method also needs to be overridden using the same steps as above, but with different block diagram code, obviously.
Also, the Pulse Frequency class data cluster needs to be completed to hold the appropriate data required for configuring the frequency measurement and any data processing needed for the measurement.
Also, the subpanel VI needs to be created and implemented.
Many of these tasks are mostly duplicates of what’s been done already or are standard LabVIEW programming and won’t be covered in this issue.
Next Steps
A new class was created for the Measurement Tool Chest. Steps to define the inheritance tree and ways to define dynamic dispatch methods for overriding the base class functionality were shown. I expect that this example shows enough of the intricacies of creating a class that some of the mystery is removed.
If you’re looking for help with your LabVIEW-based system, check out our LabVIEW experience and reach out if you want to chat.
If you work for a US-based manufacturer and have a quick LabVIEW-based question, you can reach out to our LabVIEW experts to see if we’ve got a quick answer.
If you’re deep into learning mode, here’s some other useful resources:
- LabVIEW Test Automation – Custom Automated Test System Buyers Guide
- Which NI Platform is Right for Your Automated Test Needs? cRIO, PXI, cDAQ, sbRIO?
- 5 Keys to Upgrading Obsolete Manufacturing Test Systems
- 5 Considerations Before Selecting a LabVIEW Consultant
- LabVIEW OOP Example – Measurement Tool Chest