GregFreeman Posted June 27, 2013 Report Share Posted June 27, 2013 (edited) I'm just curious if any of you have successfully wrapped DAQmx into LVOOP classes (on an application specific level, not wrapping all of DAQmx functionality), and what you have found to be most effective. One thing that troubles me about DAQmx is the lack of safety between the type of acquisition and the DAQmx reads, which manifests itself in run time errors. For example, you may have set up buffered acquisition when you create your virtual channel, but that doesn't stop you from wiring a single point DAQmx read up to your task, resulting in errors at run time. This is just one example. I am not looking for an exact solution, but I am just curious what other people have done in their code with regards to providing themselves with an application specific DAQmx classes. Possible inheritance hierarchies, what pertains to the base class and what pertains to the child classes, if you even care about any of the issues I've stated above in the first place, etc. Edited June 27, 2013 by for(imstuck) Quote Link to comment
todd Posted June 27, 2013 Report Share Posted June 27, 2013 This isn't what you're looking for, but it's the beginning of a method I'm trying to refine. It's AF, and it's woefully simple, but it was a starting point for me. In a similar actor that uses visa, when the visa resource name is empty, a child actor is called that allows for simulated/scripted data. StreamDaq.zip Quote Link to comment
GregFreeman Posted June 27, 2013 Author Report Share Posted June 27, 2013 (edited) It isn't exactly what I'm looking for but it brings up another point. This is showing an actor that is strictly tied to one type of acquisition: analog acquisition with buffered inputs. One of the things I have issues with when abstracting DAQmx is how to organize the different layers. Should all analog tasks (temperature, pressure, strain) inherit from a base class "analog task?" Maybe, maybe not. Are there enough similarities? Sure, they are all voltage, but what if temperature is only going to be single point, software timed acquisition while the others are buffered? At this point, does it still make sense to inherit? You can no longer have a dynamic dispatch "read" VI because some tasks will return an array, others a single value. So, you can make a polymorphic VI, but then you are back at square one if the wrong instance is selected: run time errors. You could break them off into their own processes for each different type, but now there is no reason to have inheritance at all, because they will all be in parallel. In this case each process manages one, and only one, type of acquisition. Edited June 27, 2013 by for(imstuck) Quote Link to comment
ShaunR Posted June 27, 2013 Report Share Posted June 27, 2013 (edited) You can no longer have a dynamic dispatch "read" VI because some tasks will return an array, others a single value. So, you can make a polymorphic VI, but then you are back at square one if the wrong instance is selected: run time errors. You can always just return an array with one element for single values (if a task returns a single value, just use the build array to convert it). Then all your companes are the same. If you really want to, you can wrap that that into a single value polymorphic VI to return just element 0. That way you won't get a run-time error. Edited June 27, 2013 by ShaunR Quote Link to comment
GregFreeman Posted June 27, 2013 Author Report Share Posted June 27, 2013 You can always just return an array with one element for single values (if a task returns a single value, just use the build array to convert it). Then all your companes are the same. If you really want to, you can wrap that that into a single value polymorphic VI to return just element 0. That way you won't get a run-time error. I thought about this, but I didn't know if this was a code smell for something that's not correct, causing me to manipulate connector panes purely to force something to work. Quote Link to comment
todd Posted June 29, 2013 Report Share Posted June 29, 2013 Scalar measurement and array measurement sound like different methods, if not different classes. I go back and forth between creating a few classes that cover lots of functionality, and many classes that cover simple tasks. The ones that get reused the most tend to be the simplest (because they're well-understood and they fit easily into any app), and the most complex (because they are the hardest to change - ha!). Quote Link to comment
Jarrod S Posted July 1, 2013 Report Share Posted July 1, 2013 You don't have to choose between classes and polymorphic VIs. You can get the inheritance you want, automatic function selection, and you can make it an edit-time error you choose the wrong read and task creation combination. Check out this example of dummy classes. Open example.vi attached here (saved in LV 2012) to get an idea of what I mean. We have done this in our classes before with great success. In fact this can work better than doing Dynamic Dispatch for your reads, because there is no run-time overhead for LabVIEW to determine what Read VI to call. But you still have the flexibility to define your OOP hierarchy. daq classes.zip 1 Quote Link to comment
Aristos Queue Posted July 3, 2013 Report Share Posted July 3, 2013 The questions being asked here are exactly the same questions asked at NI when DAQmx was designed. There were many debates over the trade offs of which way to slice functionality for max polymorphism (which has user advantage insofar as lots of measurements have a similar API) and what to make runtime vs compile-time errors. You see the result. If you're trying to write a *general* OO wrapper, I bet your wrapper will just trade one set of issues for another. But if you design an app-specific API to wrap DAQmx, I know you can put a much easier to use API into place... I know because I've seen users do it. 1 Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.