Jump to content

drjdpowell

Members
  • Posts

    1,964
  • Joined

  • Last visited

  • Days Won

    171

Everything posted by drjdpowell

  1. Regarding the initial post: John, you don't have to worry about the robustness of using an uninitiallized shift register. Even if this use of a USR was not originally foreseen, it has been a common method of LabVIEW programing for many years, as are other design patterns using shift registers. However, you should carefully consider what Norm said about the possibility of eventually needing more than one copy of the thing you program as a functional global. -- James
  2. Can you get your hands on one example unit now? Learn the tuning procedure manually and then you might be able to code a simple step-by-step procedure (tune V1 until X is true, tune V2 until Y is minimized, etc.).
  3. What is your question? If it is the line drawn back from (10 8) back to (0 7) that you don't want, then adding an extra point with a Y value of "NaN" (Not a Number) between them will eliminate the line.
  4. By coincidence I'm working on a similar thing right now: Message objects via TCP. Like you, I've mostly done two VIs on the same machine (except for one brief proof-of-principle test between England and California which worked fine). The one issue I can add is the rather large size of flattened objects, especially objects that contain other objects (which might contain even more objects). Sending a simple "Hello World" as one of my Message objects flattens to an embarrassing 75 bytes, while the "SendTimeString" message in my linked post (which has a complex 7-object reply address) flattens to 547 bytes! I've just started using the ZLIB string compression (OpenG ZIP Tools) and that seems to be a help with the larger objects (compresses the 547 bytes down to 199). I've also made a custom flattening of the more common objects to get the size down ("Hello World" becomes 17 bytes). -- James
  5. Well, I can't say that was fun, but I've managed get my code in such a way that only required parts of it will load. I found that I had a few VIs here and there that existed to help use diverse classes together. I had placed these helper VIs inside one of the classes involved; because of this they served as linkers that caused all the classes to load when the first one did, even if that VI and those other classes were never used. Just dropping an instance of my parent class loaded 75% the entire toolkit! Tracking these Vis down and getting them out of the classes broke the cross links. I found a use for a few LVLib libraries to hold collections of these VIs and others that didn't need to be in their related classes (and didn't always need to be loaded with the class).
  6. Kudoed. I was going to make the same suggestion if you hadn't already. Don't see why it wouldn't work with objects, though. My array is relatively static (rare additions, no deletions), but perhaps I'll live with the copies for now, until I get to the point that I can do comparative testing.
  7. Thanks, I was worried that copies are made. I was considering storing an index to an array and Tim suggests, but I might wait till I upgrade (still on 8.6) and go with the DVR as the code would be simpler.
  8. Hello, I've been using the feature of Variant Attributes to store and lookup values in an efficient way. In particular, I've been storing complex objects such as the (simplified) example below where I post messages to "Observers" of those messages. My question is: is this the most efficient way to do this? In particular, I select one attribute, modify it, and then return it to the variant: does this involve copying the entire cluster of objects, or does the LabVIEW compiler identify this as an operation that can be done "in place"? -- James
  9. Thanks everyone, I think I'm slowly getting a better feel for how to structure things. Mostly by keeping classes out of LVLibraries, but identifying small groups that need to be closely tied together. I actually have a small section of my messaging code that uses Command-Pattern messages; if I don't put them in a Library I could accidentally build an exe that wouldn't contain its own commands! I might retain a library for the core classes that will always be needed; though the boundary of such a core isn't very distinct, so perhaps not. I also like Paul's idea of a set of classes as one template. I don't (yet) have any such groupings, but I'm toying with the idea of a Command-Pattern-style Actor Template (ripping off inspired by the Actor Framework) and that would involve a template of multiple classes. Part of what motivated my question is that I am currently in the middle of trying to adapt my messaging system, up to this point working only within a single Application instance, to work via TCP between different App instances or over the network. Thus, I've had to consider the issue of different instances having limited subsets of the messaging package (particularly if one instance is on a memory-limited Real Time system). A whole new dimension to worry over... Thanks again, -- James
  10. I have a largish set of reuse code for inter-process messaging that I've been using in all my new projects. But I realize that I haven't really thought about how to organize things in Libraries. Given the difficulty in reorganizing libraries once they are referenced by many different projects, I'd like to get a good organization decided now. Currently, I have one large library with many classes in it, but that leads to any project using any part of the library loading every single class in it (and lots of VIs), even if individual projects only use a small subset of the classes. Classes that aren't in the library only load if needed, which seem a better feature. This makes me wonder if I shouldn't keep Classes in Libraries at all, unless they are very closely connected such that they will always be used together. What do other people do in organizing with Classes and Libraries? -- James
  11. I've been meaning for the longest time to add a Network-messaging capability to this library, and finally made the time to do it this week. I thought I would update my example here with TCP communication. Converting the example took only a few minutes, which shows the advantage of the "plug-and-play" nature of using a LVOOP class structure for message communication methods. Here's good old "Process A", now standing alone in its own App instance (Application 2), with the new "TCPMessenger" plugged in in place of the original QueueMessenger: And here is the rest of the example on Application 1 (haven't had a chance to test on a separate computer yet). It uses "RemoteTCPMessenger" to connect to the server created internally by Process A's "TCPMessenger". Otherwise it is identical to before. Note how the reply from Process A is routed back through the Process A's TCP connection. This is because the "reply address" on the "SendTimeString" message, "CommandMessenger B", is a QueueMessenger, and its internal queue is local, and not valid on the remote Application 2 that contains Process A. The two TCP connection "Actors", running in the background, inspect and alter the reply addresses of sent messages to perform this routing of replies through the sending TCP connection. As the "Observer Registration" messages, shown in Parallel Process, utilize the same "reply address", that system of publishing information also works via a TCP connection, even if the observer has a local-only messenger. Here is a Message custom probe showing summary information about the message received by Process A. The "X"s after the QueueMessenger (queue refnum 4076863496), which is Process B's, and the Message Logger indicates they are invalid in Application 2 (but they are still valid in Application 1). QueueMessenger (refnum 4091543557) leads to the TCP Connection Actor. The TCP communication is all run by "actors" based on the Parallel Process design. Creating "TCPMessenger" launches a "TCP Listener Actor" in the background. "RemoteTCPMessenger" launches a "TCP Client Actor" which initiates the connection; the TCP Listener then launches a "TCP Connection Actor" to handle its side of the connection. Multiple RemoteTCPMessengers can connect to the same TCPMessenger server (a new TCP Connection Actor is launched to serve each new connection). -- James
  12. Wait, wait, wait.. I thought the dialog was a simple while loop with two buttons; where'd this event structure come from? If you have an event structure in a dialog you have to be careful to clear any leftover events, otherwise those extra key presses or clicks will be queued up and ready to go the next time the dialog runs. I think the only way to go is to dynamically register for any events you want, and unregister as you exit the dialog. Re-registering on the next call to the dialog will ensure there are no leftover events from last time. Never use statically-registered events in a dialog, as they can't be cleared.
  13. I found this conversation which illustrates that event registrations seem to behave strangely and not like other refnum objects as I understand them. Something is going on under the LabVIEW hood that might be affected be a subVI, and perhaps I would be better to restrict event registrations to the same block diagram as their corresponding event structure
  14. I learned that through painful experience. But I don't understand the relation to subVI's. I understand that if the subVI returns a previously created and saved reference, then it will be the same each time. But if the subVI creates a new event registration, then it should be different each time. And both these are independent of the subVI being "inlined". Here is an example. Since I did this two days ago, and it is the first time I've put an event reg in a subVI, it is an important case for me! Is there something I should be worried about with this code? It's my understanding that this subVI should always create a new event registration for each call. -- James
  15. Just a small suggestion, but you could place your code in the TRUE case of case structure connected to the "NewVal" output of the event case. That would drop any double clicks by the user (as the second would be false). Can't help with the dialogs; though the primitive 2-button can be OKed with the Enter key, your second one has no key bindings and thus should require a very deliberate User action to dismiss. How do you know the event happened, BTW? Are you sure the action contained isn't being triggered by some other method than the event case? -- James
  16. Hi Norm, I'm not sure I follow. Can you (or AQ) explain more about possible issues with putting an event registration in a subVI?
  17. I think GregR means that you provide a function that produces an event registration for just the encapsulated User Event, and that registration is clustered with another registration for any other events before being passed to the event structure. Thus you only need one member VI. However, this doesn't keep the User Event encapsulated, because it can be accessed in the event structure frame itself. See below: -- James BTW, I learned only recently that one can use a cluster of multiple event registrations for handling by the same event structure; does anyone know if there are any performance differences with using multiple registrations instead of a single one?
  18. Is it this library you are using? If so, did you correct the bug pointed out in the comments: a flaw in MB CRC-16.vi in NI Modbus.llb A failure mode turn up in testing at 1200 baud. It turned out to be a flaw in MB CRC-16.vi in NI Modbus.llb. The failure mode is that the MB Serial Recieve.vi that waits for a Modbus reply to a command may falsely detemines that the message is complete before the last byte is recieved. This is becuase because MB CRC-16.vi coerces the U16 CRC to a U8, and the U8 becomes zero for a message with all but the last byte transmitted. The correction is to change the data type of the Exception Code indicator from U8 to U16. - Jim Figucia, Code G Automation. labview_work@msn.com - Sep 15, 2009 I haven't used it but when I downloaded the library a few months ago the bug was still there. Don't know if it could cause your problem.
  19. I've just become an official CLA.......... ......D I wasn't that worried about failing.
  20. If all your doing is showing the User information, you have a third option to Daklu's two. Just have the subVI open its front panel and display the information, then immediately finish (but leaving the front panel open). To modify the example from the conversation you linked to, just delete the loop and the "Stop" button. I think you need to select "Show front panel when called" and NOT select "Close afterwards if originally closed". And make sure it isn't "Modal", as ShaunR suggests. The User can close the window when they don't the info anymore. -- James
  21. I think you badly need the opportunity to use LVOOP for a couple of small projects, in a simple way. First just try using an object or two in place of type-def-clusters. Then a try a parent and two children (your USB or TCP/IP communication might be a good choice). With experience in the basics, you'll be able to get more out of all that reading. There is quite a few examples of people on LAVA trying to develop tools to handle the complex tasks with multiple processes running in parallel, but it would be quite hard to just jump right in without some experience.
  22. BTW, here's an extension I am working on, that uses the "Self-Addressed Envelope" aspect of the framework: a class of Asynchronous Dialog boxes. This allows a process loop to display a dialog box for User input, without waiting. It can then continue to perform other actions. When the User dismisses the dialog, his/her input is sent back to the loop's Messenger via a "reply". So far, I have only created a Dialog that is a modification of the standard LabVIEW "Three Button Dialog"; an example is shown below: Here, the example process increments a count every 200 ms (in the Timeout case). If the User presses the "Clear Count" button, a dialog is configured and displayed. Had the standard LabVIEW dialog been used, this would block the incrementing of Count until the dialog completes. But here the dialog is dynamically launched and asynchronous, and thus the loop keeps counting. Part of the dialog configuration is to give it a message Label (also used as the dialog title) and attach the loop's own Messenger (Event-type, in this case) as a "return address". When the User pushes a button and dismisses the dialog, the name of that button is sent back the the return address with the supplied label. Thus, the loop can perform the required action, such as resetting the Count to zero if the User responded "Yes, please!". The asynchronous dialog box has an optional timeout function (it replies "window closed") and will automatically close if it's calling VI goes idle (it uses a Notifier internally to achieve these functions). -- James
  23. Thanks for replying, If I understand your question correctly, your asking if a message logger could automatically be attached inside the "Create" methods, thus making logging of all messages automatic while hiding this fact in the top-level diagram. Correct? One could easily create a "Create and auto-log" VI that does exactly this, encapsulating the currently existing functions, and setting up a logger that records all messages to the created Messengers. Personally, I wouldn't use this, as I don't actually want all messages logged except when I'm debugging, and when I am logging I want this fact to be very clear from the top-level VI. What is logged and where isn't something that should be hidden, IMO.
  24. Ah, but at least the resources would be spent on "interesting new functionality", rather than boring old "rehashing existing functionality".
×
×
  • Create New...

Important Information

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