Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Jeff

  1. I wanted to do the same thing; but I had a discussion with some TS developers who told me this is not possible. What we need is to have PropertyObject.SetValVariant work for a LabVIEW object, or perhaps have a method something like PropertyObject.SetValLabVIEWObject, The only way to pass a LabVIEW object between TestStand and LabVIEW is through the VI's connector pane. NI suggested posting on the TestStand feature request page. I have been meaning to do that, but I haven't gotten around to it. If you post a suggestion, I will vote for it!
  2. You're right, the Automation Open function is not needed when the existing Engine is passed in from TestStand. To run the VI standalone (i.e., not called by TestStand), you would need the Automation Open in order to get an Engine reference. Have you tried passing False to the "open new instance" input of Automation Open? I haven't tried it, but in that case I would expect you would get a reference to the existing Engine object that was created by the Sequence Editor (or UI). With a value of True, you are creating a new Engine instance for which no Application Manager exists.
  3. You can get a reference to the Application Manager from the Engine.GetInternalOption method. Then you can use the Application Manager reference to register for events. However, just looking at it, it seems that your code should work too.
  4. Hi, Norm, I can change springboard code myself, so it's not a big deal. But if this tool is intended to be used by the general LabVIEW community, the code should use the older "official" version of AMC to keep it compatible with the AMC library that people may already have installed. Or perhaps it (and the example) should use its own private AMC library, just like the generated code does. Then the code will work no matter which AMC version you have installed. I previously thought that it would be better to have the generated code refer to the user.lib copy of the AMC library than its own private copy, but I see how having its own private copy avoids any potential conflicts with the user.lib copy. By the way, do you know if and when the new AMC library will be "official"?
  5. This package seems to install v3.0.0.4 of the AMC library (and two dependencies), which is newer than (and is incompatible with) the version ( library (and its own dependencies) that generally seems to be available here and that I had already installed. It is confusing to me that new projects built with the tool use a copy of the AMC library (i.e., it resides in the directory of the newly created project), but the tool itself uses the AMC library from user.lib. Since the new AMC library is incompatible with the old library, it seems that the tool itself should also use its own copy of the library to avoid conflicting with an installation of an older version of the library. Furthermore, is the newer AMC library availble independently? The only reference I have been able to find for it is here, which explains that it is not available publicly yet but will be available "2011 Q4 or 2011 Q1".
  6. By default, the LabVIEW adapter is configured to reserve loaded VIs for execution. This setting can be changed in the adapter configuration (Configure>>Adapters) for LabVIEW. To unreserve all reserved VIs, select File>>Unload All Modules. Also, if you select a step that calls a code module, then select Edit VI, the VI will open in an unreserved state.
  7. Not sure if this is what you are looking for, but you can display the sequence file hierarchy for a sequence file in a TestStand project (or even outside of a project) to see (non-dynamic) callers of sequences at edit time. From a sequence file in a TestStand project, right-click>>Display File Hierarchy; or just from an open sequence file: View>>Sequence File>>Display File Hierarchy.
  8. I will be there too. Is there anyone carpooling from the hotel?
  9. Not thinking about the underlying mechanisms, here is how I (used to) think about how the Register For Events node and event cases in the Event Structure work: The Register For Events node adds to the list of event sources and their corresponding events that I can register for by adding to the list of Event Sources in the Edit Events dialog for the Event Structure (at edit time). In spite of its name, I didn't think that this node causes LabVIEW to start looking for (registering for?) those events--I thought the actual checking for events (registration?) only occurs at runtime if a case (configured from the appropriate item in the Edit Events dialog) in the Event Structure is defined to handle it. Why would the Event Structure look for a front panel control's Value Change event only if I created a case for it, but look for a calling VI's front panel control's Value Change (dynamically registered) event whether or not I created a case for it? The Register For Events node does allow you to change the source of the event at runtime, but does not allow you to change the type of event that can be acted upon (this can only be changed at edit time). Nor does it allow you to start or stop looking for (registering or unregistering for?) the event (even though the event source could potentially be changed to a null object). I guess that is another reason why I figured the node only defines events that can be "registered for" in the Event Structure, but does not actually "register" the events. So the actual behavior is that registration for a non-dynamic event (this is called "static registration") occurs only if an event case is created for that event; but registration for dynamic events occurs at the Register For Events node, whether or not an event case is created for it. After writing this sentence, I see that the behavior is actually consistent with the terminology and documentation. But if you rename the Register For Events node to something like "Define Dynamic Events", I think the terminology would be consistent with the behavior I (and I think a lot of other people) were expecting and, to me, seems more logical and self-consistent. Basically, the Register For Events node should add items to the Edit Events dialog, and creating a case to handle the event should register for the event. So, having thought about it more, it appears the behavior we see is actually correct given the terminology. But it would still make more sense to me to have all events registered the same way (i.e., defining an event case). Given that this behavior is not likely to change, I do agree with having a default event case or generating an error if an event isn't explicitly handled.
  10. I'm a little late to this conversation, but I would also be interested in helping where I can. It would be a good opportunity to bolster my knowledge of OOP. Jeff Siegel
  11. Another really nice feature of projects is that you can rename a VI, and all referencing VIs get updated to reflect the change. And in LV 8.5+, you can also move VI locations on disk (in the Files tab) and have referencing VIs automatically updated. (Just make sure you save the changes to the VIs when you close your project.) Jeff
  12. I am using a Linear Technology LTC1609 serial sampling A/D converter chip. Its 16-bit output data is serialized on one pin on the chip. There are several other ADC's that have a similar output (LTC1417, LTC2365, LTC2366, etc.). I would like to read the serial output using a digital input board. Has anyone done this before and have any advice/examples to share? Thanks! Jeff
  13. For my case, I think my answer would be "I would create a functional global that manages the <class data>" (and not, "I would create a reference to it"). But isn't that what GOOP effectively is? It's a functional global that manages data, with additional mechanisms to manage multiple data sets.
  14. Oops, I didn't mean to revive the by-ref/by-value debate. Sorry! Perhaps this should be the start of a separate thread, but let me explain what I am trying to do (at the risk of exposing myself to more wrath). I am creating a TestStand UUT dialog that runs in parallel to multiple UUT executions. The dialog acts on user interface events, updates the states of UUTs based on the events, and updates the display based on the states of the UUTs. In the meanwhile, the UUT executions are also getting and updating UUT states. So all the parallel threads require simultaneous access to the same objects. Perhaps I am old-school and too used to a class with a protected data repository that can be shared among parallel pieces of code, but this seems like an obvious solution to me. I'm completely in favor of avoiding references (and I have been trying to figure out a way to do so) if you can show me the error in my ways.
  15. Aristos Queue, thanks for that information. This will at least solve the problem about memory duplication when creating a new object. I haven't actually built anything yet. Without your example, I would have done something along the lines of what Daklu built, where a VI to create the new object has inputs for all the attributes from the parent object, and unbundles the old object's attributes and wires them into the new object's attributes using a bundle function. I'm still considering whether to do use a by-value or by-reference model. So I'd like to know if there is a way to replace a parent object with a child object and still keep the same reference. Mikael? Can I do that in GDS?
  16. Thank you all for your responses. Aristos Queue gives a very good explanation of why it is not legal to directly cast a parent class object to a child class object. The workaround is to essentially create a new object and copy the attributes of the old object (doing whatever manipulation of attributes is required in order make those attributes legal for the child class) one-by-one to the new object. That is essentially what Daklu's example does (thanks for that!). I think I was unsuccessful doing the same thing because I tried to copy the elements from the old to new class all inside the same VI, instead of getting the elements in one VI and passing them in as parameters to another VI. So creating an entirely new object seems like a reasonable way to solve my problem, but the act of transfering the parent attributes to the child attributes is unsatisfying, potentially memory-intensive, and error-prone. Each time I change a parent attribute, I have to modify the code that creates a new child from a parent. So what I really want to do is copy the parent attributes as a group to the new child object, despite the reasons that it is not strictly correct to so. I accept this can't be done, and I do not dispute the reasons, so my question now is: is creating a new object and copying the parent attributes to the child the best way to accomplish my goal? Or is there a better way? I would expect that others have to deal with the same issue I do--how do they deal with this? Perhaps I am thinking about this all wrong? If creating a new object is indeed the best approach, I have a second question: how would I do this using GOOP (GDS 3)? I see how to do it using LVOOP. With GOOP, I'm sure this could be easily done. I would presumably destroy the parent object and create a child object. On the one hand, I would want the refnum of the new class to be the same as that of the old class, so that any other code referencing the object would still be pointing to the same object after the "downcast". On the other hand, changing the class of an object has to change the data type of the reference, so this sounds impossible. Is there some trick to using the "cast to more specific" in the GOOP Kernel VI?
  17. Is it possible to dynamically recast a parent object to a child object? Here's what I am trying to do: I am testing two types of parts, call them Part A and Part B. I have a "Part A" class and "Part B" class, each of which inherit from a "Part" class. I create a "Part" object, and call its method to get the part's serial number (the procedure is the same for all part types). Once I know its serial number, I can determine which type of part it is. So at this point, I want to cast my "Part" object to a (say) "Part A" object. From all the examples I have seen, you have to create your object with the create method from whatever class you are trying to create, and it forever stays that class (even if sometimes it is represented by the wire type of a parent class--in this case you can use the "To More Specific Class" primitive to get the wire of the class that was created). I think this recasting could be theoretically done using LVOOP with a VI that creates a new child object, copies the data from the input parent object to the new child object, and sends the child object out via a parent object terminal; but the compiler doesn't allow this. I'm not really sure how I would go about this using GOOP (I'm using GOOP Developer Suite 3). I see that there is a function for "cast to more specific" in the GOOP Kernel VI, but I'm not sure how to use it (if it should be used). The fact that this is forbidden by the LV compiler (for LVOOP) leads me to believe that there is a good reason to not do what I am trying to do. Does anyone have any suggestions on how to do it, or some better implementation? Thanks.
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.