LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamic Mapping of Varying Instrumentation

Hi all,


The Problem:

I want to run the same software on machines with different hardware without any changes to the VI's.  Rather, I'd like to use a config file to map universal commands to the appropriate relays at run time. 

(Unfortunately I am not able to pull screenshots or anything off of my platforms, and my development computer doesn't have any PXI cards it's tough to get a screenshot but I'll explain this as best as I can.)

PXI1 cfg: (16 channel relay in slot 2) 
======================================
Relay1 : 2-1 ... Relay 16: 2-16 PXI2 cfg: (8 channel relay in slots 2 and 3)
======================================
Relay1: 2-1 .... Relay8: 2-8 Relay9: 3-1 .... Relay16: 3-16

So when a script says "Close Relay 9" the user doesn't care the physical location of that relay.  In PXI1 the 9th relay in Slot 2 will close and in PXI2 the 1st relay in Slot 3 will close.  At that point it's just simple mapping.

Where I hit a snag when my system has 2 power supplies controlled by GPIB, 2 power supplies that are controlled over RS232, 3 PXI relay cards, 16 relays controlled by Digital Outputs, 16 channels of analog inputs, and god knows what else. 

If anyone knows an elegant solution that'll allow tasks to be created and mapped at run time, that'd be wonderful.

Things I've Tried:
-Using MAX to name each relay, input, output, PSU, etc.
If there was a way to programmatically do this, I'd maybe go for it but given the sheer amount of tasks I'd need to create it'd be a nightmare.

-Opening DAQmx/TCP/Serial Task, performing action, Closing task every time action occurs.
While my program doesn't require Real-Time, the amount of overhead is not ideal.  Especially for tasks like AI or RFSA that takes a significant time to create/start/stop/close. 

-After Opening each of the tasks, converting each of the instrument handles"to Variant", clustering them with a string denoting the data type I'd like to convert it back into upon use, and building an array of these clusters.
I'd rather not have to pass this massive array into every subVI I call.  Ideally, since race conditions are a non-issue (since I will only be reading from that array) I could use a Global Variable.... but I try to avoid those if I can.

 


If anyone has any ideas I may be completely overlooking I'd greatly appreciate it.  Would using Classes help?  I'm familiar with C# and other object oriented languages that use classes but I haven't used Classes in LabVIEW.  As usual I'm trying to minimize wiring and clutter where possible.  ANY help would be amazing. Thanks.

~Andrew Wojtkowski

0 Kudos
Message 1 of 4
(3,298 Views)

What you are asking for is a HAL or Hardwre Abstraction Layer.

Start Here 

An example HAL project in LabVIEW can be found here 

A nice community presentation is here

 

And be careful.  a HAL can come back and bite you rather harshly when it gets expanded to "Do Everything" they are quite handy IF you know up front the limits you need to impose on the class.  When you find you need "Just 1 more" device you can find yourself "Shoehorning" in that oddball device and things can get ugly.


"Should be" isn't "Is" -Jay
0 Kudos
Message 2 of 4
(3,283 Views)

We have a similar problem with different types of test fixtures. They use similar devices, but different communication types, for example the mass flow meters can be analog, DeviceNet, some RS485 protocol, etc...

 

Usually all channels of the DAQ cards are placed in a single task. For example for a 24 DI/DO card there are just two tasks: one task for all DIs and one task for all DOs. I realize that this makes it impossible to measure or set a value of a single channel, but for this application it is fine. The tasks are defined as multiple channels, one sample on demand.

 

The mapping files were initially plain text files. Now I switched to NI ini-file type:

  • The section name includes always the DAQmx task name for DAQ cards, or the DeviceNet network for DeviceNet communication, or COM-port for serial, etc... (tf_ai, dnet0, etc...)
  • 'key' names starting with underscore are reserved for properties like communication type, channel number, etc...
  • all other 'keys'  indicate channel numbers, or MAC ID for DeviceNet, or port/line combination for DO, etc... depending on what type of signals are included in the io-maps
  • the 'key values'  indicate the device type, i.e. valve, pressure transducer, mass flow meter, etc... and the caption of the related control on the user interface (see mapping file below)

To make it simple: the mapping file is the link between the IO channel, no matter what is the type, and the caption of a control or indicator on the user interface.

 

Each test fixture type has a dedicated user interface which gets launched asynchronously  from a controller VI. The user interface VI has just a little bit of code in order to send the references of all control and indicators to the controller VI. Then the controller launches all devices, i.e. valves, flow meters, etc... as actors (Actor Framework). The actors take care of the events generated by user interface changes, i.e. controls, or indicators updates based of IO signals. Probably you can keep it more simple.

 

Below is an example of 2 different mapping files. In Example #1 the flow meters signal is analog (0-5V), in Example #2 the same devices are digital (DeviceNet). This is really just an example, the actual files are much bigger and include additional information about scales, etc....

 

io_mapping.png

 

 

0 Kudos
Message 3 of 4
(3,223 Views)
Are you using NI-Switch where you can name a route?
0 Kudos
Message 4 of 4
(3,192 Views)