Posts

Midlands LabVIEW User Group: Malleables, Pragmatic Test Rigs and Code Reviews

On Monday, I was at the latest meeting of the Midlands LabVIEW User Group at the MTC in Coventry (across the road from the AMRC for the IIoT event a few months ago).

Lovely day to learn LabVIEW!

I was presenting on Malleable VIs but also up on the projector alongside me was Ian Billingsley from CCS presenting on their pragmatic approach to test rig design using LabVIEW/TestStand and Peter Horn from NI with ‘Code Reviews for Teams that don’t have time for Code Reviews’.

Ian Billingsley – CCS

First up was Ian – his presentation was very interesting as it is always good to see how others are customising TestStand. It looks like they have found a robust and adaptable architecture that allows continuous monitoring of the test rig along with controlling it from TestStand. There were also some interesting discussions about when/why you should use TestStand and the benefits of building a simulation interface into your software. If you didn’t make it to the MLUG meeting, he will be giving a revised version of the presentation at GDevCon in September.

Peter Horn – National Instruments

Second up was Peter talking about how Code Reviews are a Good Idea™ and that if you don’t currently do code reviews, you probably should. You don’t have to implement some huge process where you sit down for 3 hours and get grilled on every wire bend. I believe in the benefits of having someone else look at your code – both to improve software quality and as a learning exercise for the reviewee/reviewer. The key message of the presentation was that you have to find a process that works for you/your team (whether that’s formal/informal/tool-driven code reviews) and to nurture the appropriate culture for them within the team (it’s not to pick faults).

Me!

Finally, I gave my presentation on Malleable VIs – an introduction to Malleables and some practical examples of how I have used them in my code. I demonstrated some examples from my previous blog posts but also some fresh examples with the Type Specialisation Structure introduced in LabVIEW 2018. Whilst preparing the presentation, I discovered an obvious workaround to the property node limitation of Malleable VIs – just wrap the property node calls into a SubVI!

Here’s a sneak peak from the presentation of a Malleable VI that can set the enable/disable state of a scalar/array of controls – using a scalar/array of ‘Enabled/Disabled/Disabled and Greyed Out’ enums or booleans:

Set Enabled State.vim – Various supported use cases of the Malleable VI for enabling/disabling controls.

You find find the full slides from my presentation as a PDF here: Malleables in the Wild – MLUG 2018

In Summary

LabVIEW User Group meetings are a great way to network with and learn from fellow LabVIEW developers. Thanks to Argenta for organising another successful MLUG.

Just don’t ask us to take the CLAD exam any time soon! (We had some CLAD practice questions to work through as the coding challenge this time around – I’m blaming our poor performance on the lighting / projector!)

Custom Property Loader Plugins in TestStand

Update 30/10/2018

This was going to be part of a series but unfortunately, as mentioned below, there was a lack of available documentation and I ended up implementing a workaround – it was a much simpler solution that could be easily tested. I created an action step which pulled the limits/parameters from the database and wrote them to a temporary CSV file which is then loaded by a Property Loader step. I’d probably only suggest implementing custom plugins at this stage if you were releasing/selling an addon/customisation for TestStand where it would make the time investment worthwhile. Of course, hopefully in TS2017 the documentation will be available to make the process much easier.

Introduction

In this series of blog posts, I’m going to be talking about how to create a Custom Property Loader Plugin for TestStand using LabVIEW.

I have a custom database schema that doesn’t follow the NI database format that the built-in property loader plugin supports. We have separate tables for limits/test configuration parameters and options for product/test specific limits/parameters. In the last few years, NI has changed aspects of the TestStand Engine to allow more customisation of the various aspects by the use of plugins (e.g. process model plugins, report generation, property loader plugins). The advantage of using a custom property loader plugin is that it allows us to use our custom limits/parameters database but also use the other built-in options as an alternative (e.g. for off-site use at a contract manufacturer without access to the database).

Unfortunately, I couldn’t find much documentation on the subject (NI says that the documentation is coming for TestStand 2017) so figured I’d suffer through the hard work and post it so you know what to expect if you intend on creating custom property loader plugins for TestStand.

For the first part of the series, I’ll start by giving an overview of what a property loader is (and what it does), why you should use it, how to create a custom plugin from the template and give an overview/reference of the VIs / ActiveX objects that make up a custom property loader plugin. In subsequent parts, I’ll be building up my plugin by modifying the VIs to talk to my custom database schema (and the challenges that may come along with it).

Our custom property loader plugin will be talking to a database – but the process should be similar for files – just replace any instance where I’m referencing a database with your custom file IO.

For reference, I’m running TestStand 2016 SP1 and LabVIEW 2017.

Loading Properties in TestStand

Before going into the details of creating a custom property loader plugin (CPLP?! CPP?!) I wanted to just give a quick overview of the various components/mechanisms of loading properties in TestStand.

The main use case for a property loader is to load your test limits and/or test parameters from a file or database at run-time. This gives you the following benefits:

  • You can modify/update limits without modifying the sequence files (of course, you need an appropriate change management system)
  • All of the limits/parameters are in a single location (e.g. a file/database table rather than having to check individual sequences/steps) – this makes checking/validating/updating the limits/parameters easier
  • You can load different sets of limits depending on certain conditions – by specifying the file by expression, you can use different sets of limits/parameters depending on the UUT being tested (e.g. similar products in the same family but with different characteristics)
  • Using a centralised database or network-shared file for the properties means that all test stations use the same limits for testing

Natively, TestStand supports comma-separated (.csv), Excel and tab-delimited text (.txt) files and loading properties from an NI TestStand database schema. There’s plenty of information online and in the TestStand training materials about using the built-in plugins (e.g. here, here and here).

The property loader can import any property to just about any TestStand component (that has properties) – the most useful ones are step properties (e.g. to set limits) and sequence variables (e.g. sequence/sub-sequence Locals, StationGlobals etc.). You can also use aliases so that your parameters/limits have sensible names and then these are automatically mapped to the appropriate steps/properties in your sequence.

There are two ways to use property loaders – a property loader step in a test sequence and using the import/export properties dialog in the TestStand tools menu.

It is important to mention this because our custom property loader plugin will not only load and apply properties from the database, but it should also work with the import/export properties dialog as well.

Property Loader Step

The Property Loader Step in TestStand allows you to load properties at sequence/execution run-time by dropping a Property Loader step into your sequence and configuring it on the Step Settings and Source Settings panes of the Step Settings.

Import/Export Properties Dialog

You can also use the import/export properties dialog to manually import/export properties to/from a property loader source. This is useful for generating the initial source data in the correct format (e.g. set the properties in the TestStand environment, export and then load the data in the property loader step) and for verifying the source data. You also use the Export function of the dialog to generate an aliases file (.pla).

As with the Property Loader Step type, you can select the Source for the properties and configure whether to load all of the properties, or just select properties (using the Property Selector pane).

Creating A Custom Property Loader Plugin

The only documentation I could find on creating custom property loader plugins was this small snippet of information which says to copy one of the existing template plugins as the starting point and go from there. So I guess we’ll just dive in then…

Duplicating the Template Plugin

Shipping with TestStand 2016 SP1 is a selection of sample plugins for various programming languages/environments (CVI, .NET, VisualStudio and LabVIEW). You can find these in <TestStand Install Directory>\Components\PropertyLoader\Templates (i.e. C:\Program Files (x86)\National Instruments\TestStand 2016\Components\PropertyLoader\Templates).

The documentation says to copy the template plugin to <TestStand Public>\Components\PropertyLoader\<YourPluginName> directory – initially I couldn’t get the plugin to load following these steps and after a support request with NI it seems that you have to copy and rename the template .llb file to <TestStand Public>\Components\PropertyLoader\ (i.e. C:\Users\Public\Documents\National Instruments\TestStand 2016 (32-bit)\Components\PropertyLoader\MyPlugin.llb) rather than having it reside in a sub-folder. The PropertyLoader folder in <TestStand Public>\Components probably won’t exist if this is your first attempt at a custom plugin – so you’ll need to create it.

You’ll end up with something like this:

The next step is to configure our new plugin by modifying the PluginInformation.vi inside our fresh plugin .llb file:

Modifying the plugin information for the custom property loader plugin

The VIs themselves are reasonably well documented (most of them are empty stubs though) – here we need to set up the basic information (some fields only apply when loading files e.g. ‘extension’) for TestStand to identify it. You need to change the ID (by default it’s a GUID but I think you can use anything as long as it’s going to be unique to your plugin).

The ‘Type’ field has the following options which are fairly self-explanatory:

  • SourceType_Database: When you choose this, the Step Settings for the property loader step allows you to specify/configure a database connection
  • SourceType_File: As above, but it prompts you for a file path to the file containing your properties
  • SourceType_Custom: I tried to set the enum to SourceType_Custom to see what happened but it just produced an error in TestStand (see below) so I’m not sure if there’s something else that needs to be configured/set first to get this one to work. I guess you’d use this for anything that isn’t a file or a database? Ideas on a postcard please!

That’s OK – I didn’t want to create a SourceType_Custom plugin anyway…

After populating the fields and launching TestStand, you can then drop a Property Loader step into your sequence and you should see your newly created plugin in the Source Type drop-down:

‘Hacking TestStand by Code Injection’ – Available at all good bookstores soon!

Of course, at this point it doesn’t do anything but we’ve at least managed to get it to load and register the plugin. Time for a beer (or other beverage of your choosing)! Next we’ll take a deeper look at what’s inside the template plugin.

Exploring the Template Plugin

Opening up the .llb of the plugin we’ve just created, we find the following VIs:

Contents of a LabVIEW Property Loader Plugin

I’ve already discussed the PluginInformation.vi which sets the metadata/information about the plugin that TestStand uses to populate the plugin in the source type drop down box.

Let’s take a look at the VIs in the template plugin and their functionality…

Custom Property Loader Plugin VIs

Name Description
BrowsePropertyLoaderSource.vi If ‘SupportsBrowseSource’ is set in OverrideOptions (see below), this VI is called when the user clicks the ‘Browse Source’ button – for files this could launch a file dialog or for a database it could be to select a specific set of tables.
ConfigurePluginSpecificOptions.vi

Called when you select the ‘Configure’ button on ‘Plugin Options’ (see below). You could use this VI to launch a dialog where the user can set/configure any plugin specific options for import/export. This is similar to creating a LabVIEW dialog for configuring a custom step type.

DisplayPluginSpecificOptionsHelp.vi Called when the user hits the ‘Help’ button in ‘Plugin Options’ (see ConfigurePluginSpecificOptions.vi description).
Export.vi Used when a property loader ‘Export’ is called from the import/export dialog – this is the main VI that exports the current property values back to the property loader source (e.g. file/database). If ‘OverrideImportExportSummary’ is set, then you can also return a custom summary text to display the status of the export operation.
ExportAlias.vi The reverse of ImportAlias.vi (see below) – if you have the ‘OverrideAlias’ set then this can be used to perform an export of the aliases to a custom aliases format. By default, you configure aliases from the Import/Export Properties dialog and these are then automatically exported (as an XML .pla file) when you perform the export.
GetImportPropertyItems.vi Called before Import.vi to read the source and retrieve only the property loader groups information and the properties within that group. This data is used when importing all of the source data (so the plugin knows which properties to load i.e. all of them), determining if a property exists in the source, populating the property selector (for the import/export dialog) and for specifying the properties for the Import operation.
Import.vi Used when a property loader ‘Import’ is called (either through property loader step or the import/export dialog) – this is the main VI that retrieves the properties from the file/database to apply them to the steps/sequence properties. If ‘OverrideImportExportSummary’ is set, then you can also return a custom summary text to display the status of the import operation.
ImportAlias.vi If ‘OverrideAlias’ is set in OverrideOptions (see below), this VI allows you to write custom behaviour for loading the alias names. Aliases allow you to match up variable/parameter names in your property loader source with their matching counterpart in the test sequence (e.g. variable/property name) – there’s documentation and an example of using aliases here. Overriding the default functionality allows you to load/configure aliases as part of your custom plugin (e.g. generate them dynamically or from your property source), rather than specifying them in an aliases file (.pla).
OverrideOptions.vi Used to set override flags/options which control certain options for the plugin (e.g. to allow the user to view the source data and browse for the source). The list of options/overrides are detailed in the ActiveX reference below.
PluginInformation.vi Defines the basic metadata about the plugin when it’s loaded into TestStand (e.g. name, description, type, plugin ID).
PluginSpecificOptions.vi Creates/initialises the available plugin specific options.
PluginSpecificOptionsSummary.vi Generates a summary text of the plugin specific options as shown in ‘Plugin Options’ (see ConfigurePluginSpecificOptions.vi description).
PropertyLoaderSourceFormatCount.vi Specifies the number of different source types that the plugin supports. I’m not quite sure what this means and the template plugin returns 1 (i.e. the plugin supports one source type). I’m not sure if this means that a single plugin can support multiple types (but it’s not obvious how to specify them) – maybe this is reserved for future use?
ValidateImport.vi Called by the Sequence Analyser to allow the creation of a custom VI to check the status of the source during sequence analysis. This could be to check for a correctly configured database connection, check properties are available etc. and return an error if the analysis fails.
ViewPropertyLoaderSource.vi Used to launch a dialog to ‘browse’ the source data (e.g. view the source file, browse database tables).

Custom Property Loader Plugin ActiveX Components

The VIs all interact using ActiveX methods/properties (as with any other custom LabVIEW components for TestStand), here is a brief overview of the main ones that are used in the VIs.

Name Description Properties Methods
PropertyLoader.PropertyLoaderContext A reference to the instance of the property loader containing generic configuration parameters for the instance and references to the TS Engine and Sequence (i.e. the location of the PropertyLoader). AliasLocation
Engine
IsUsingTool
Operation
SequenceContext
SourceLocation
TargetSequenceFile
N/A
PluginSpecificOptions (PropertyObject) PropertyObject containing the plugin specific options. (See TS.PropertyObject) (See TS.PropertyObject)
PropertyLoader.SequenceFileLoader Contains the list of properties to import which are then updated with the property objects once loaded. AliasNames
PropertyLoaderGroups
SequenceFile
UserObject
GetLoaderObjects
PropertyLoader.ImportOptions Contains the user-configured options for the import operation. ImportAllDataFromSource
ImportToRelatedExecutions
PropertyNotPresentInDestinationAction
PropertyNotPresentInSourceAction
StepUniqueIdLookup
TargetSequence
N/A
PropertyLoader.ImportPropertyItems Container for the list of properties in the property source. Count Clear
Create
GetEnumerator
Insert
Item
Remove
PropertyLoader.PropertySourceGroups Container for the list of groups in the property source. Count Clear
Create
GetEnumerator
Insert
Item
Remove
PropertyLoader.AliasNames Contains the aliases used for the import/export operation – used when overriding the default plugin alias functionality (using OverrideAlias). Count Clear
ExistsAlias
ExistsLookup
GetEnumerator
GetExpandedPropertyLookup
GetItemByAlias
GetItemByLookup
Insert
Item
Remove
PropertyLoader.OverrideOptions Contains the options for overriding/enabling certain functionality for the custom plugin. OverrideAlias
OverrideImportExportSummary
OverridePropertyNotPresentInDestination
OverridePropertyNotPresentInSource
PropertyNotPresentInDestinationAction
PropertyNotPresentInSourceAction
RequiresPropertySelector
SourceLocation
StepUniqueId
SupportedProperties
SupportsAliases
SupportsBrowseSource
SupportsExport
SupportsGroups
SupportsImportAllData
SupportsViewSource
TargetSequenceName
N/A
PropertyLoader.PropertyLoaderPluginInfo Contains the basic metadata about the plugin. Description
Extension
FormatDescription
IconName
ID
Type
N/A
PropertyLoader.ExportOptions Contains options for exporting properties to the source. StepIdUniqueLookup N/A

Summary

That’s enough for Part One. I’ve covered an overview of how Property Loaders work, why you would want to create a custom plugin and how to create your very own custom property plugin and load it into TestStand. I’ve also provided some reference material about the VIs and ActiveX objects that make up a custom plugin. In Part 2, I’ll begin customising the VIs to work with a custom database schema.

MediaMongrels Ltd Custom TestStand Solutions

If you’re looking for a bespoke test system and are considering using TestStand, why not get in touch and see if MediaMongrels Ltd can help. We are an NI Alliance Partner with Certified TestStand Developers and we have experience of architecting test systems from the ground up (including custom process models, Operator UIs, custom database recording) to provide flexible and configurable test frameworks for your component and system tests.

Malleables VIs: Practical Example Part 2 – Malleable Class Adaptation & Practical Application

This is the second of a two part post about the use of Malleable VIs in a practical project – rewriting a test system to use TestStand. In Part One, I introduced the project and the decision to use LabVIEW OO and Hardware Abstraction Layers to allow an easy switch between Simulated and Physical hardware in the test sequence.

In this part, I will discuss the implementation in more detail and how I am using the Class Adaptation feature of Malleable VIs. Class Adaptation allows me to create a malleable VI that can act on unrelated classes (i.e. no inheritance between them). I believe in Computer Science terms, this qualifies as some sort of Mixin.

Read more

Introduction to Malleable VIs in LabVIEW

In my first LabVIEW-related blog post, I wanted to talk about a new feature introduced in LabVIEW 2017 – Malleable VIs. I will give an introduction to Malleable VIs, discuss some of their benefits/limitations and show some examples of how Malleable VIs can improve code reuse. I’ll expand on this post with more examples in subsequent posts.

The Problem

Malleable VIs are designed to implement ‘generics’ in G, a feature which can be found in other languages (e.g. C#), allowing you to create functions where the data type is not defined in the function and is determined either at compile or run-time. The use of generics allows you to improve code reuse since you can write a function once for many data types. If you find yourself writing (or copying+pasting) very similar VIs where only the data type on the connector pane is different, you probably want to have a look at Malleable VIs.

Before Malleable VIs, this was done in one of two ways:

Method 1 – Polymorphic VIs

The first method of supporting multiple data types is to use a Polymorphic VI, but I consider it to be cheating – essentially creating a separate VI for each data type you need to support. This leads to large numbers of VIs that have to be maintained, most of which are essentially the same but with different data types on the terminals to avoid coercion.

As an example, here is the OpenG Sort Array function. This is a polymorphic VI that sorts a 1D or 2D array of most LabVIEW datatypes (e.g. numeric types, strings, paths). This leads to 33 different VIs – the polymorphic VI itself and the ~32 VIs that support the different data types.

OpenG Sort Array Function

Of course, if you wanted to sort an array of a datatype not supported by the OpenG Sort Array function, such as clusters, enums etc. then you would need to create an additional Sort Array VI for your data type to do so.

Method 2 – Variant Polymorphism

If you look at the functions of the OpenG/MGI toolkits, there are many VIs which take in and pass out a variant. Since a variant is a generic data type (it can hold any type of data at run-time), LabVIEW will automatically coerce any data type to a variant at the connector pane terminal boundary. This allows you to wire anything into a variant terminal, perform some operation on the data and then return the variant out. Inside the VI, however, you must handle the different data types (e.g. by type-casting) and it also requires the user of your VI to type-cast the variant back to the initial data type.

Below is an example of how this method is currently employed in the OpenG Read INI Section VI. The VI has a variant in (to define the expected data type/default values) and returns a variant which then has to be converted back to the original type.

OpenG Read INI Section VI – Variant Polymorphism

The Solution – Malleable VIs (.vim)

Introduced in LabVIEW 2017 was the new VI extension ‘.vim’ for Malleable VIs. With VIMs, the data types on the connector pane can adapt to any valid input (i.e. any data type where the VI can still compile / no broken run arrows).

In the following sections, I’ll show a basic and an intermediate example of Malleable VIs which should help to explain the concept.

Basics – Stall Data Flow.vim

I think most LabVIEW developers have at some point found themselves creating a VI like ‘Delay with Error Wires’ or ‘Tick Count with Error Wires’ for adding delays or benchmarking their code. Even if you haven’t, you’ve probably found yourself putting a sequence structure frame with a Delay primitive inside it and a wire going through. One of the Malleable VIs included in LabVIEW 2017 is Stall Data Flow.vim which replaces the ‘Delay with Error Wires’ with a VIM that can delay data flow on any wire type – making my VI ‘delay with error wires’ VI redundant (good!).

Stall Data Flow.vim – Examples

The content of the VIM is very simple – exactly the same as what’s in my ‘delay with error wires’ VI shown above but if you look at the examples at the bottom, any data type passed in is passed out without coercion dots – so you can use it with any data type. That’s the basic principle of the Malleable VI.

Intermediate – The Type Selector – Increment Array Element(s).vim

The next aspect of VIMs I want to introduce is the Type Selector. The type selector is a new structure specifically for VIMs that isn’t currently available on the palettes (as of LV2017 SP1 – probably coming in LV2018). It allows you to handle cases for specific input data types. The simplest example of which is to allow for a terminal to be a scalar as well as an array – as is the case in Increment Array Element.vim.

Increment Array Element VIM – Type Selector Structure

LabVIEW checks each case of the type selector until it reaches the first one that is valid (i.e. compiles), and it uses that as the implementation for the case. If a scalar is passed in, the VIM increments just the specified index and if an array of indexes is passed in, each element is incremented in a for loop.

To take it slightly further, there is also a ‘match type’ node which breaks the type selector case if the data types do not match, giving you another tool for handling specific cases in your VIM, but I won’t go into those here.

Advanced – Coming Soon!

There are also more advanced uses for VIMs (to do with using Malleable VIs as OOP interfaces, and some examples with sorting of arrays using custom sort functions) but I won’t go into those in detail as this is just an introduction. Stephen Loftus-Mercer from NI (AristosQueue) gave an excellent presentation at the CLA Summit in Madrid in which he showed many examples of Malleable VIs. There are some examples included in LV2017 SP1 and some more that should be shipping with LabVIEW 2018.

  • examples\Malleable VIs\Basics\Malleable VIs Basics.lvproj
  • examples\Malleable VIs\Class Adaptation\Malleable VIs – Class Adaptation.lvproj

If you have access to the CLA Community, he has posted a further example here.

My Example – INI Configuration API

One of the immediate use cases for Malleable VIs that jumped out at me was for creating a re-use library for handling INI configuration files. In many of my projects I use INI configuration files when I need a simple human-readable configuration file format. I use the OpenG configuration file functions, but I wrap them into a ‘Load Configuration’ and ‘Save Configuration’ VI with a type definition that contains the contents of the file. Here is what it usually looks like:

Load INI Configuration – Type Definition

This VI loads the INI file and if it (or some keys) can’t be found, uses the default values specified. It then writes the settings back to the file (which is useful to create the file on initialisation of the software). I create a ‘project-specific’ version of this VI (i.e. with a different cluster type definition) since I want to keep my top level block diagram (where I load the settings) simple.

Now, with Malleable VIs I have created the following:

Load Settings – Reusable VIM

I now have a reusable API for loading/saving INI configuration files (with the initialisation code), I can easily see the path/default values on the calling VI but I don’t have to convert the variant back to my settings type on the calling VI (and no coercion dots!).

Limitations

Malleable VIs currently have one major limitation – they must be set to ‘inline’ in the execution properties. While this might not seem like a big deal at first (e.g. you have to disable debugging, no automatic error handling and must be shared/preallocated reentrant), this is actually more of a limitation than you might think – some LabVIEW nodes cannot be used in inlined VIs. According to the LabVIEW documentation, inline VIs cannot contain ‘certain’ block diagram nodes – the help mentions Property Nodes and Invoke Nodes (but there are others – I couldn’t find a list!). There is a flat restriction that inlined VIs cannot contain property nodes or invoke nodes (this includes class property nodes, even though the accessor VIs can be inlined). This unfortunately rules out many potential use cases for them – for example for UI manipulation.

Below is an example of something I thought would be a great candidate for a Malleable VI – something which sets VI properties on a bunch of control references. This Malleable VI would allow me to wire in either a scalar or array of control/indicator references and set some property (e.g. visible, disabled etc.) on all of them at once.

Set Disabled Malleable VI – Not possible due to inlining restriction

There is a LabVIEW Ideas exchange post about the issue, but with the inlining restriction of Malleable VIs I think it is more relevant now than ever so please go ahead and +1 it.

Summary

I think Malleable VIs are a really neat feature included in LabVIEW 2017 and I hope that this post goes some way in helping you to understand them and unlock their potential in your LabVIEW programming. It was a bit of a shame to discover I can’t use them to replace some of my UI utility functions, but I see that there are still plenty of other uses for them.

I’m very interested to hear/see how others are using Malleable VIs in their code – so if you have any examples/ideas then it would be great to hear them – please leave a comment below!