Jump to content

drjdpowell

Members
  • Posts

    1,969
  • Joined

  • Last visited

  • Days Won

    172

Posts posted by drjdpowell

  1. It's nice to be able to dump an array of doubles in one end and get the same array out the other end, without having to search for data boundaries and reinterpret bytes.

     

    For anyone listening, here is how to send messages (or any other data type) via a TCP connection.  Basically, one just puts a message length at front and reads that first.   TCP handles making sure you never miss a byte, so there is no need to identify data boundaries.

    post-18176-0-48858100-1447878814.png

    • Like 2
  2. 1. No Polling. Seems like there will always be a need to poll the connection.  If nothing else then to be able to respond to internal shutdown messages.

    2. Robust connections.  How do you re-establish the connection from the server side due to your flaky network dropping it if the client does not have a unique machine name and port to connect to?

     

    It seems like I would run into the same issues and would have to design a very complex solution from the ground up.  

    You can cross (1) off at least, as there is no need to poll a TCP connection.   Just have one loop sit waiting for incoming messages, with a second loop to do sending in parallel.  TCP is bi-directional and the two directions don’t interfere with each other, just like a pair of Network Streams.  But being bi-directional, you don’t need to establish a second connection from server back to client, and thus don’t need to know the client name.  If the client can reach the server you are done.  And the TCP Listener is exactly what you asked for as far as a server handling incoming connections.   To me, TCP seems much simpler than what you described.

     

    Re (2), I don’t have experience in unreliable networks.  But I have always been confused by Network Streams, as TCP is already a robust network protocol that resends lost packets; what is Network Streams able to do that TCP can’t?   

     

    — James

  3. Are you trying to measure volume?   With a bright light wall behind, the meniscus should be visible.  

     

    In this image the level (of a petroleum product) is very clear because of a layer of bubbles (white bubbles, but they appear black against the light wall), but even without bubbles one can pick out the level.

     

    post-18176-0-65575700-1447682478.png

  4. @drjdpowell,

     

    Edit: The Open Vi Reference followed by "Auto Dispose" TRUE only seems to work if I wire in a strict VI Reference constant with the correct connector pane.  If I do a generic "VI Open" without the VI Type being specified, the VI will still auto-abort when leaving the sub panel even if "Autodispose" is set to TRUE.

     

    That’s surprising to me, but then I haven’t used the Run VI method in years.   I only use ACBR, which always required a strict reference.

  5. This can be a bit surprising when you come accross it the first time (and I still think it's not ideal behaviour to be honest).  You have to babysit that original reference until the VI has left the subpanel, had its FP set to not closed and then and only then can you close that VI reference.  

    For async VIs** I use ACBR with option 0x80, which, like Run VI with Auto Dispose Ref = TRUE, means the VI never aborts like this.  

     

    **We don’t seem to be talking about synchronous subVI calls here, but for those I just use a static reference (which cannot be closed).  

  6. If I run it with the panel hidden and then close the panel to insert it into the subpanel, that's going to reset all the values to default values, isn't it?

    (that's what it seems to be doing for me... maybe I've still got something wrong.)

    Does it?  Closing isn’t the same as unloading.  Is your VI reserved-for-execution?  If it is, I don’t think closing the FP unloads it or resets anything.

  7. Or does a VI have to already be running before it goes into a subpanel? 

    If you executed it, then it must be reserved for running, so the “nasty transition†Neil mentions doesn’t apply.  

     

    Do I have to close the panel before I put it into the subpanel? 

     

    Yes.   I put Close Front Panel before Insert VI (I ignore any error from the Close, thrown when it was already closed).

     

    PS: After I put the panel into the subpanel, can I close the reference or do I have to keep it open so that the VI stays in the subpanel? If I don't close it and then put a different panel into the subpanel, will the subpanel close the reference for me?

     

    You can close the reference.  The subpanel doesn’t (I don’t think) ever close the reference itself.

  8. For example: Log button becoming true sends "Start Logging" command, Log button becoming false send "Stop Logging" command.

     

    The thing I like about this is that I can handle fiddly "stateful" control logic inside XControls. The Xcontrol has an enum value and I can register a particular enum value to a command specific command message.

     

    For example, a "tape deck " type control with play, pause, resume and stop / abort buttons. Three button, four messages "Play" "Pause" "Resume" and "Stop". The X control logic wraps the "button logic" up nicely without having to smear it over 4 cases of you main UI's event structure.  

     

    I solve this issue a different way, by making my messages all "control-likeâ€: a label and a value.   So I would have messages:

     

    “Set Loggingâ€, a boolean that is True or False

    “Set Play Stateâ€, a string (or possibly enum) with values "Play" "Pause" "Resume" or "Stop"

  9. I tried having call-backs that called methods on a LVOOP object inside a DVR.  It worked, except that occasionally two events happening at about the same time caused the UI to freeze, possibly due to some kind of lock-up involving the DVR and the UI thread in which the callbacks run.  This was near impossible to debug, and I abandoned callbacks in favor of an asynchronous VI that handled events with an Event Structure (calling the same LVOOP object held in a shift register).

  10. Are we actually disagreeing?  Your pointing out a way for calling code, that explicitly knows what a "dog" is, to call subVIs that only deal in "animals".   If the calling code has reason to explicitly be written for "dogs", then that's good.   But if you want the calling code to be generic and work with any animal (what's that? an "animal-abstraction layer") you can still support special functions if you define the right methods.  Writing code where, if you click on a dog, you get a button marked "bark", doesn't require that code to explicitly work with anything other than animals.

  11. Another option is to push greater responsibility down into the specific classes and have the application-specific code continue to deal in parent-class methods.  For example, your power supply with a special feature probably needs a way for the User to configure that feature and observe the results.  The application code could call methods like “Has special features.viâ€, “Show Configuration window.viâ€, “Get text description of status.viâ€.   If the power supply has special features then show a description of the status of those features and show a button that lets the User open the Configuration window (possibly in a subpanel).   

    • Like 2
  12. Hi Thanks for the reply.

     

    I'm not sure i understand your point 2a.  completely.  Where does the case structure go?  Does that end up inside event loop and inside the event case to actually trigger the message?

    Yes, inside the event case.  Show your dialog only on events where the button goes True.

  13. Re 1) The Event Structure has a Timeout, which you can set to zero if you want.

     

    Re 2a) Use a Case Structure to do things only on True.

     

    Re 2b) the “Value Changed†event is somewhat misnamed as it really is a “new value†event; there is no filtering out of where the new value is the same as the old value.  The Event has the old value as well as new value so you could do this yourself, but a far better solution would be using a case structure and only trigger an event on True.

  14.  So as an example: If my Actor acquires some data and provides it for the outside world, it might have its own visual representation and maybe you can control it (so basically MVC in one Actor). On the other hand I require multiple visual representations to fit the data on different screen resolutions (pure VC units). There are boundaries I have to define. I can either have a 'default' resolution in my core Actor with additional VC Units, or the core Actor is never shown and all resolutions are from separate Actors as VC units.

    You can also treat the core Actor’s Front Panel as the “debug†UI, since it is easy to add a lot of indicators.

     

    Personally, I usually have a lot of actors that are MVC-in-one-actor for their own part of the application.  So ‘temperature control’ actor probably has control/view of the SetPoint, PID and other parameters, and can be inserted into a subpanel in the main app.  Then additional Views or Control can come from elsewhere (a summary screen of many temperature controllers, say) but these VC tend to deal with smaller subsets of “Model†(such as just the SetPoint).

    • Like 1
  15. Most of the web references to MVC is about frameworks and architecture, where the M, V, and C are distinct and clearly separable things.  I’m less interested in how to define boundaries between things than in flow.  Directions and arrows.   The User exerts control on the state of the application.  The User views the state of the application.  

     

    Here’s the Wikipedia diagram for MVC

     

    post-18176-0-33662000-1445378402.png

     

    If you search, you’ll be confused by seemingly different diagrams, which divide up Controller and View differently, but they all have the key flows between User and Model.  I follow the principle, rather than trying to have specific application layers identified as M, V, or C.  

     

    — James

     

    PS>  a link to the video referenced.

     

     

     

    • Like 1
  16. If I were looking at improving an old program I would first look for and refactor any natural ‘objects’, bits of data and actions on that data.  You, for example, might have a ‘Camera’ object for taking images, or a “Sample Positioner’ object.   Only after this would I ask if some of these objects should exist in separate loops so they can do things in parallel.  

     

    Re the various QMH designs, I gave a talk recently about some of the issues (main point: don’t use the NI QMH template; use something like the JKI template).

×
×
  • Create New...

Important Information

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