Jump to content

drjdpowell

Members
  • Posts

    1,969
  • Joined

  • Last visited

  • Days Won

    172

Posts posted by drjdpowell

  1. Whatever timing method you choose, you will get the maximum flexibility by making it a separate loop from your actual periodic task.  Have the separate timing loop signal the main loop handling the task via some messaging method such as a User Event.  That way the main loop is not constrained by the timing technique; the OP’s process could be reading data every 15 sec AND saving to disk every 5 min AND updating some UI element every 500 ms (by using three external timing loops). And as a message-handler, the main loop can accept (and immediately act on) other messages than just “stop”.  Meanwhile, the dedicated timing loop can be made a reusable component (as it only does timing).

  2. Why would he be handling mouse-move events in his data collecting loop?  Handle that somewhere else.

     

    Any finite timeout is unreliable if there can be repeated events; your 100ms timeout would fail during a mouse move.  The only reliable timeouts are 0, −1, and a timeout recalculated after each event based on the previous time the timeout case executed.

     

    Added later: actually, 0 isn’t that reliable either.

  3. I don't mind this idea, the one thing I wasn't sure of is the fact that now the main VI which owns the subpanel has access to all the other VIs references. To me, it feels like these references should be private and other VIs shouldn't have access to them. 

    Also, isn’t this unnecessarily complicated.  You already are keeping track of the communication references to these subcomponents; now your going to have to keep track of the VI refs of their VIs (plus whatever mechanism you use to get the VI refs to the top-level subpanel owner).  An “Insert into the attached subpanel” message is trivially simple.

  4. Why does each VI have a copy of the subpanel reference?  I would just have the top-level owner of the subpanel just send send the subpanel ref to the chosen subView, after calling “Remove VIEW”.  The receiving subView would call “Insert VI” as part of handling the message, but wouldn’t bother saving the reference.

  5.  I've so far thought that the only way to avoid getting blocked by the root loop was to populate the asynchronous call pool (and hope that the pool is large enough to meet the demand during a blocking event...).  Populating the call pool is only required for a speed gain then, or?

    Getting the ref with “Open VI Ref” is blocking, but increasing the size of the pool when needed does not, so there isn’t a need to prepopulate the clone pool.  

     

    On my benchmarks adding an extra clone is about 1000us, while reuse of a clone in the pool is about 100us (LabVIEW 2011).  

  6. As a word of warning to anyone reading this, be aware of the issue of Root Loop blocking by things such as the User opening a menu.  Safety-critical code must never be dependent on Root-Loop blocking functions, such as “Open VI ref” or “Run VI”; the User can open a menu then walk away.  If in doubt, test it by opening a menu and leaving it open just before your critical code executes.  If it doesn’t execute until you dismiss the menu then you have the problem.  The simplest fix is to open necessary references once at the start of the program, and use the ACBR node instead of the “Run VI” method.

    • Like 1
  7. I would suspect it is a “Root Loop” issue.  I know that Open VI Ref can require LabVIEW’s Root Loop, and this loop is blocked by the User opening a menu.  Perhaps a LV dialog also blocks root loop?  



    BTW, if it is Root Loop, then a method used to get around this problem is to use a single reference to a pool of clones to do all asynchronous running of VIs.  Then the ref is only acquired once, before any action that blocks root loop can happen.  The latest Actor Framework’s “Actor.vi” is an example of this.

    • Like 1
  8. I don’t have a consistant plan, but I usually tend to assume it modifies the object (or could at some future point be changed such that it modifies the object).  If I’m sure it doesn’t (and never will), then I consider removing the object output, which is the clearest indication you can have that you aren’t changing the object.  

     

    One can also use the IPE structure to unbundle, instead of a private accessor method as you are using.   Then one is required to connect up the output.  Connecting the output never hurts.

    • Like 1
  9. A solution can be to not output the unit string with number, and convert it to raw number in unit base, using the "Strip Units" VI from OpenG Data library. This is what variant config library does, in the  "SGL PQ".."EXT PQ" case of "Read key (variant).vi".

    That might be best, and easy to do.

     

    The other point I'd like to share is that I have some classes that I would like to serialize. Can we imagine the following thing, à la AQ Character lineator:

    Also easy to do (just one abstract class with two empty methods).  I would have the “to” and “from” methods deal in JSON Value objects rather than a cluster in variant; the User can always call the Variant to JSON methods if they want, and they have the option of using the direct JSON methods as well.

     

    — James

  10.  So, I'm curious... when you folks are writing your applications, have you started leaving out File >> Exit? What are your thoughts on that trend?

    I’ve obviously not properly thought about, as I had to check my latest app and found I’ve left File>>Exit in but not trapped it to shutdown properly.  Opps!  I always trap "panel close” as a shutdown command.

  11. So what do you do when you need to execute a reasonably complicated bit of code which requires various bits of "data" in this cluster (i.e. a portion of code that screams out to be made into a sub-VI, which in my opinion is virtually anything non-trivial)?

     

    Do you unbundle the specific elements and pass them into a sub VI? I know it may be frowned upon, but by having the cluster typedef'd I then just pass the whole thing into/out of a sub-VI. Of course you could pass in a non-typedef cluster but we know how that is going to end...

    Below the top-level cluster I tend to have objects (or arrays of objects) whose methods do the “heavy lifting”.  The typical “state” will unbundle only a couple of things and call a couple of methods.  So I am doing something similar to what you do.  But the problem with the top-level cluster is that it is a grab-bag of everything; UI details mixed with INI file details mixed with analysis details.  It’s not cohesive.  

     

    Because the objects/typedefs that make up the top-level cluster ARE chosen to be cohesive, it is rare to need more the a couple of them.  If you find you’re unbundling six things, that’s a good reason to stop and consider if some of them really should be a class/typedef.  But because they really naturally go together.

    • Like 2
  12. It would be nice if the template could include a typedef for the main cluster on the shift register, I normally end up creating one.

    I actually never do that.  The main cluster is a set of data related by being “stuff this QSM needs”, rather than being a cohesive single thing.  Even when 90% of it is a cohesive thing (and then that part can be an object), there will be extra bits of data (update flags, say) that don’t belong in it.  So I never make the full cluster a typedef or object, even though it is mostly composed of typedef/objects.  

    • Like 1
  13. Uh oh.  Your right.  I hadn’t appreciated this before. I built a test project and library myself (LabVIEW 2011).  I used the Application properties to find what VIs are actually in memory as opposed to just listed in dependancies.  The unused VIs in a library are NOT actually loaded, but any libraries in dependancies ARE, and if that library is a class, then the contained VIs (and all their dependancies) are loaded.

     

    post-18176-0-62737600-1397303036_thumb.p

     

    Here “Uses Empty VI" is in the project but not loaded.  It uses “Empty VI”, which is in the same library as VI that calls a method of "Cyclic Table” class.  None of the three VIs in the chain are loaded, but the Library and Class are.

     

    NI really needs to fix the library system; it’s badly broken.

     

    Added later: a useful link.

  14. Also see “Test JSON subitems in Variant.vi”.   I’ve added the ability to use “JSON Value” class objects in the Variant JSON tools.  I should have thought of this first, before using “tagged” string names, so perhaps the tagged string stuff should be dropped.

     

    post-18176-0-76981300-1397132714_thumb.p

  15. I’ve made an addition that I could use comment on.  See “Mixed type array experiment JDP.vi” in the Bitbucket repo.  Basically it is about JSON like this:

     

    {“instruments”:[{"type":"SimMultimeter","config":{"maxV":10,"maxI":5}},
    {"type":"SimVoltmeter","config": {"Voltage":100}},
    {"type":"SimDAQ","config": 12.3}]
    }
     
    Here “instruments" is an array of objects corresponding to modules.  Each has an identifier, and also a configuration object that varies from module to module.  We can’t make a LabVIEW cluster that matches this structure, so at the moment we have to use the lower-level functions to get at it.  However, if we have a means of defining a string in a cluster as a JSON string, then we can hold arbitrary JSON subitems in this string.  To do this I have added support for a “tag”, <JSON>, at the beginning of the name of any string in a cluster.  With this, we can convert the above into a cluster containing an “instruments" array of clusters of two strings, named “type” and “<JSON>config”.  Thus we can still work with static clusters, while retaining dynamic behavior at lower levels.
     
    Have a look at the example and see what you think?
     
    — James
×
×
  • Create New...

Important Information

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