LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Need help designing class hierarchy for analog input/ouput program

I'm designing a program that outputs a sine wave voltage and measures the resulting voltage and current of a device. This prorgam need to work with several different types of hardware. For this reason I want to use classes to organize the code, but I'm having some difficulty in designing the hierarchy.

 

One configuration could be a function generator to output the voltage signal and an oscilloscope to measure the response. I would then need 2 classes: "input" and "ouput" class. However, another configuration uses only a source meter which has the capability to generate as well as measure, so the "input" and "output" class needs to be 1. Or I need to duplicate code.

 

Another options is to simply make 1 class called "Measure", make a child for each configuration. Then the function generator + oscilloscope child would itself have 2 classes called "function generator" and "oscilloscope". 

 

But here is another problem. Let's say I want another configuration, say "function generator" and "multifunction". I would create a new child of "Measure" for this configuration, but function generator would need a different configuration than the previous when it was paired with the oscilloscope. How would I go about this?

 

I hope my explanation is clear, I get a bit confused with hardware abstraction layers.

0 Kudos
Message 1 of 6
(1,729 Views)

@Basjong53 wrote:

One configuration could be a function generator to output the voltage signal and an oscilloscope to measure the response. I would then need 2 classes: "input" and "ouput" class. However, another configuration uses only a source meter which has the capability to generate as well as measure, so the "input" and "output" class needs to be 1. Or I need to duplicate code.


Look into interfaces. LV 20 and higher.

 

Make a input interface and a output interface. Then the same device can implement both the input and the output.

 

I'm not sure if it helps with preventing duplicate code. Interfaces can't have state, so it's hard to actually make them actually do things. They can, but they require each child to implement accessors.

Message 2 of 6
(1,719 Views)

wiebe@CARYA  ha scritto:


Look into interfaces. LV 20 and higher.

 

Make a input interface and a output interface. Then the same device can implement both the input and the output.

 

I'm not sure if it helps with preventing duplicate code. Interfaces can't have state, so it's hard to actually make them actually do things. They can, but they require each child to implement accessors.


Interfaces seem to be really powerful for this kind of application. I found some examples online that I didn't fully understand, but something like this seems the most logical to me:

Basjong53_0-1615369937615.png

The top row are the two interfaces. The middle row is the hardware abstraction layer of the various types of devices. I have the source meter layer as a child of both the input and output interfaces. The bottom layer will then be the actual implementation of the specific hardware.

 

One question regarding where to create vi's and where to put the data. As I understood, interfaces cannot have private data, but can have abstract vi's that have to be overwritten. So I must create all vi's as dynamic dispatch in the interface and override them in the bottom layer. Simply treat the interface like parent classes?

0 Kudos
Message 3 of 6
(1,660 Views)

@Basjong53 wrote:

wiebe@CARYA  ha scritto:


Look into interfaces. LV 20 and higher.

 

Make a input interface and a output interface. Then the same device can implement both the input and the output.

 

I'm not sure if it helps with preventing duplicate code. Interfaces can't have state, so it's hard to actually make them actually do things. They can, but they require each child to implement accessors.


Interfaces seem to be really powerful for this kind of application. I found some examples online that I didn't fully understand, but something like this seems the most logical to me:

Basjong53_0-1615369937615.png

The top row are the two interfaces. The middle row is the hardware abstraction layer of the various types of devices. I have the source meter layer as a child of both the input and output interfaces. The bottom layer will then be the actual implementation of the specific hardware.


Sounds like a plan...

 


@Basjong53 wrote:

One question regarding where to create vi's and where to put the data. As I understood, interfaces cannot have private data, but can have abstract vi's that have to be overwritten. So I must create all vi's as dynamic dispatch in the interface and override them in the bottom layer. Simply treat the interface like parent classes?


An interface can also have VIs that don't need to be overwritten.

 

You can put logic in those interface VIs, but required data needs to be handled through accessor VIs.

 

I guess you can make an Iinput and an Ioutput interface, then make an input, output and input output child. Put shared logic and data in those classes. You'd still have duplicate code, but not every device would need a duplicate.

 

Interfaces are quite new to LabVIEW. So there is not that much precedence. 

0 Kudos
Message 4 of 6
(1,651 Views)

This all sounds weird to me Input Output parent class... Virtual Class OK.

 

when I model the test hardware I prefer to use live settings. An Instruments Class is the parent, it contains VISA addr and Instr Name. Childs are the physical hardware types, i.e. function generator, Oscope, DMM. 

 

Keithley, Tektronics, Keysight could be child of Function Generator, Oscope, DMM and all could inherent from each other.

 

When you break your code into smaller component virtual parts, you maybe creating code that's of little use.  No harm done maybe confusing to the reviewer.

 

There is not wrong way of doing this but don't make it harder to code and debug.

0 Kudos
Message 5 of 6
(1,623 Views)

@richjoh wrote:

When you break your code into smaller component virtual parts, you maybe creating code that's of little use.  No harm done maybe confusing to the reviewer.

 

There is not wrong way of doing this but don't make it harder to code and debug.


There's always been a search for the perfect HAL.

 

I agree, dedicated drivers for specific devices is a lot simpler.

 

However, if you want dynamic configuration (e.g. configurable by the user or from a file) of interchangeable devices, some sort of HAL needs to be made.

 

I also agree that two interfaces, 3 base classes, and then a device driver layer is more complex than desirable. But without interfaces with state, it seems the way to reduce duplicate code.

 

There are other options.

 

Giving a parent input and output methods that don't do anything, and then implementing them, as appropriate, in each child also works. It's less 'pure', but maybe more practical.

 

The traditional way to get multiple inheritance is to use containment. Make an hardware class, with an input and an output child. Then put an array of supported hardware interfaces in  each device driver. You can query the device driver for supported hardware interfaces. But this will get you run time errors, not compile time errors.

 

And of course you can go old school, and simply start methods with VI Server (Call By Reference or Run method). That a poor man's OO, really. But it worked for decades, and it still does. And again, run time errors, not compile time errors.

 

Come to think of it, interfaces only give you run time errors as well. At some point you'll have to cast to the interface, and that will give errors if the objects don't support the interface. But you will get better 'error prevention' support while editing.

0 Kudos
Message 6 of 6
(1,607 Views)