Jump to content

todd

Members
  • Posts

    335
  • Joined

  • Last visited

  • Days Won

    13

Everything posted by todd

  1. This isn't completely correct, but it doesn't clear the history: ChartDemo_1.vi
  2. It is a cluster of strings, not of string arrays. The names of the cluster elements are derived from the indices of the input array - "[0]" is the name of the first string array element. With context help open, hover the wiring tool over the output of Array To Cluster to see its type.
  3. If you know how to view a block diagram, turn on execution highlighting and start pushing buttons.
  4. Yes. I believe you were asking for a different kind of comment, but it's all I have Ok. I like to put the debugging/logging code in each component (each one for me tends to be just different enough). And I can select debugging capability separately in each component, depending on what I'm looking for.
  5. I'm not much ahead of you on the LVOOP curve, but my take is that you need to code something up and see what happens. A "simulated" instrument class may help during early development. Actor Framework or daklu's create.vi and execute.vi loop are very good starting points for encapsulation. I have custom instruments with different evolving capabilities, and I'm having success (so far) grouping their classes all together in create.vi as private data in the instrument's class. It's not that much work, after you get used to it.
  6. Mike, I think crelf means the type descriptor VIs (like Get TDEnum from Data), not the string ones. However, it looks like 1F is not specified.
  7. All of the examples run, here. The only comment I have is somewhat superficial and simplistic (meaning not entirely thought through): since the logger display is called by reference based on a relative path, couldn't it somehow be included in the Create.vi of CommandMessenger[A,B]? Then, instead of the observer being CC'd in the Controller, the Messenger's "Receive" could send the copy. I'm thinking only of keeping the top level VI's diagram simple.
  8. Here is most of the state of my noodling with this. Some obvious stuff is left out (gracefully stopping some loops; low-level VISA and other comm methods; proprietary stuff). main.vi is the top-level VI. Some goals (maybe I should have written these BEFORE coding - just kidding, I knew this would be an iterative approach): - Provide simple access to instruments in test VIs, as in "Test 1.vi" - Allow one-time selection of instrument "descriptor" data from the top-level (hide the controls and use INI files for production code), as in main.vi. In fact, such an INI file would eliminate the notifiers in main. But I need to be able to choose them for now. - Provide a live front-panel for each instrument, as in Execute.vi - Allow simulated instruments with live front-panels and with APIs, as in Execute.vi - All instruments must support immediate response data, as in Version.vi - Some instruments must support streaming data with multiple versions of data manipulation, as in Execute.vi and "Read and Queue Bytes.vi". Kind of. My current real app does dynamic dispatch of Execute.vi, but does not have some aspects properly abstracted - such as the comm method (serial vs dll - each with their own versions) and data parsing. It still "feels" as if I haven't got the traditional kind of OO philosophy, but if I can just find the right place to override methods and encapsulate data, I'll be in flexibility heaven. It also feels as if the controls and indicators on Execute.vi could all be private class data. Sample Project.zip
  9. I'm still swimming here, so here's the standard disclaimer: beware my imprecise and disorganized statements below! I'm finally beginning to understand this thread, and I have a question that relates to Steven's about multiple "execute" slave loops that handle the same type of instrument: Why not use non-classed VIs for create, execute and destroy and make them reentrant? Is classing "create" and "execute" just a handy way to bundle up the input queue, output queue, object, and mediator's queue? Oh, perhaps this: I made an API (set of VIs) that basically just send/receive messages to/from the slave's input/output queues. If the APIs are methods of a class, they have to match the object (bundle of queues) sent to them. I don't like having the instrument's object available in the mediator loop, though.
  10. Terminals! For the same reasons as above: averse to change; small size; label says it all. If you want to see all the type information in the diagram, how about creating a wire style that has all the type-text from the context help? (Yes, that's sillly.)
  11. Or I'm being too impatient Actor Slave Object Loop: ASOL - everyone has one! Ha! (Nothing like sophomoric humor.) I'm just now "internalizing" that an output queue is actually required. I just have to massage my existing data queues to output data the same way as an immediate measurement. Exactly - but just a single top level VI to control the simulated instruments. I strive to make things as simple as I can. That said, I consider my current confusion a result of being mid-way through a programmer's continuous learning process that you mentioned in another thread, once. And that is exactly the type of simple answer that I've missed. I shall do it this way. Exactly my intent. I use an enum to choose the class that gets created. At the moment, if an instrument is being used in one test, any other test that tries to use that instrument will throw an error. This is not entirely built out, but I consider it my responsibility to understand the complexities required to support this kind of flexibility. PM about my location (with which you are familiar, according to local NI folks) is forthcoming. I live near 'F', though. So far, the development cycles have been beneficial in that I have time (and my manager gives me leave, as long as stuff works when needed) to iterate the test architecture - with the help of experts, here. This is an intriguing concept, and I have been wondering how soon I would have to try to instantiate a class of test the same way as an instrument actor. Excellent! This will be by next peak to ascend. This is an excellent method, and one toward which I've iterated towards over the last two months of my re-immersion into LabVIEW. Thank you both!
  12. Ahh - it's nice to be able to follow 99% of your post! (Not sucking up - just happy that I'm getting it.) By the way, thanks for your time. I finally understood this last week - helped along by Evil AQ. My next hurdle was/is making it happen, and sharing the interface with a few other VIs. That makes sense. I've used an error cluster constant just inside the while-loop for that sequencing. Ah! I missed that. I like it! I used to put a dequeue timeout case that just checked for errors on the SR. I've just been throwing in Simple Error Handler.vi, during development. I like the possibility of logging errors after deployment, though. Yes, quite clear. I was coding out loud. I'm not yet unhappy with the two-way notification shown in post #16 above. The instruments I use can vary wildly (in many ways) over their development cycle, and I need to support each version. The abstract class helps me flesh out the simplest methods to expose, and to drop the simulated one in place so I can write tests before the instrument arrives, or before announced functionality is added to the real metal. I didn't really plan it that way, but I'm happy with it, so far. (I haven't seen delegation - time to study.) I usually start loops that way, too, just to see what inputs they need when they're sub-VIed (before I have a standard for the current project). I have enough screen real estate to have them all open, and I have several existing loop objects that I will massage into the new message standard. Thanks, again!
  13. This works, so far: Now to create instrument APIs that can be called in the tests (wrap the message enqueue in a VI, as James mentioned), and see how those work for returning data to the test. If that works, on to OOPifying the Loops and seeing if they work as reentrant, for multiple of the same "class" of instrument.
  14. "If I can't explain it simply, I don't understand it well enough." Yes! What is that kind of loop called? I call it the Instrument Loop. "Driver" almost works, except that term tends to be reserved for the lowest-level functions. "Actor" almost works, given AQ's definition of it as state data in a module - however, the loop itself is more like his Actor Core.vi instead of the Actor.vi which spawns it. "API" almost works, because the messages handled by that loop (which are, again, the ONLY way to act on the real-world instrument) are the only messages allowed - except the API is actually the set of VIs that wrap possible messages. In my code so far, the Instrument Loop carries an instrument's class in a shift register. The instrument's class provides the inherited methods (such as "Take a Measurement" and "Set Scan Rate") that call some level of the instrument's driver. Please pardon my lack of clarity, and thank you for taking the time to correctly suss things out. One note that is beside the point: I do make the Instrument Loop VI a method in a class, because several of the real-world instruments require loops that are parallel to the Instrument Loop (similar to the Image Display Loop in daklu's image here: http://lavag.org/topic/15089-dequeue-element-timeout-state-control/page__view__findpost__p__90891). Also, each Instrument Loop has a "Show" message so it's front panel can be brought up - so the Instrument Loop also has a paraller User Event structure loop (which only uses the available Instrument Loop message API. But I still consider those parallel loops part of the Instrument Loop functionality. I've only been back on these forums for the last few months, and have been looking at every VI I can find - ramping up on inheritance. Now that the terminology is better defined - at least in this thread - (Instrument Loop is the only place to communicate with a real-world instrument; API is the set of messages that can be sent to the Instrument Loop), I can be clear about the problem: Think about the one-panel VIs many people start with: open a VISA session, initialize an instrument, take several measurements, save data to file, close the VISA session. Now imagine a top-level VI like the one in Daklu's post mentioned above. Add a button to the front panel called "Run Test 1". The User Event structure tells the Mediator Loop to run a one-panel VI (invoke node, do not wait for completion). I want to send the by-reference message queues to the one-panel VI so it has access to the real-world instruments via the Instrument Loop's API. I also want the by-reference message queues to be available to another top-level VI so messages can be injected (typically used for simulating instruments that are not present, or that don't have fine-enough controls for checking the test's logic).
  15. Yeah, named queues haven't bit me, yet - but I've been making single application instances, so far. I like it the idea of sending a slave queue out - trying it now with non-OOP Create + Execute. Baby steps. Yes, exactly! Just have to figure out how to transport their control across BD lines. I'm picturing having the Execute method hold the class (with its private data) in a shift register - example below. Because I haven't figured out how to send all instruments' classes into invoked test VIs - although now I'll try bundling up all their message queues and passing them in. I like this idea because it allows me to send that bundle to the simulator loop, too! It's not difficult, now that I've used it. It's just a matter of taking the time to build up an app - starting from your example. Little extra for filling in error handling, etc. I'm still at the point where I'm trying to figure out why you wired a loop's error out to the error in of ReleaseQueue.vi, and why errors are in SRs. Here's my initial attempt. I used LapDog - just to keep your attention. I haven't yet figured out where to put the Create and Execute VIs (not yet classed, as mentioned above). Perhaps a "dispatcher" loop at the top-level that receives Create-required information and spawns Execute loop VIs - don't know, yet. Sample Project.zip
  16. Here's what I've been mostly using - except that the two lower while loops are in subVIs, and they each have Init or Open cases that store an instrument class in a USR. Also, I name the queues and create a helper VI for each queue/loop that obtains the named queue and enqueues elements. One problem I'd like to solve is the most useful way to return data (haven't wrapped my head around lapdog or anything, yet). Sometimes I put it in a "global" data AE in a parallel loop in the instrument's handler VI. Also needed is a cleaner (more debuggable) method of talking to the instruments' queues inside test VIs and from the simulator (a separate loop at the top level that listens to another set of buttons and sliders - so the water-spraying can be tested without first setting fire to the city). Another problem is "instantiating" multiple instances of an instrument's loop without duplicating code. I've "classed" the instrument loop (several of the same kinds of instruments behave differently), but that pushes the instrument class creation into the top-level loop, which I don't like. I'd like to create the object in the top-level and send it as the variant to the instrument loop, except the instrument loop is a method of the class... Robot Usage.vi
  17. It was really slick. He could identify all instruments on several different busses/comm methods (including custom), show them all to the user, and allow them to select names for them all. Saved the config to a file for later automation. He's in Lynnwood. Then I have made a lot of friends! Okay, time to put some nodes where my mouth is. I know I've seen many discussions about this on LAVA (duplicate class wires make a new copy of the object), but I'm not ramped up, yet. All I can come up with is that I need a SINGLE VI that can access the specific instrument's class. Not there, yet. Yes! This is what I've converged upon. But I have resorted to using named queues with the "standard" string+variant to handle all of the instruments' handles/actors/slaves. I'm searching for a method that, for lack of a better term, "feels better than" passing commands via named queues. For example, some instruments have a method that gathers streamed data and adds it to an AE. Other instruments just have simple read/write access. Just haven't unified them, yet - not for the sake of unification for its own sake, but for ease of use of the reusable API.
  18. The waveform in the attached image has sample rate of 1kHz. "input signal 3" stops at Nyquist.
  19. No. For the last few applications, I managed to keep the code modular enough that refactoring was basically painless - but I can see a ceiling to the scalability. Reading the discussions, here, of everyone's design patterns has helped immensely. If you have time, create a bunch of classes with fake instruments and do trial-and-error. If you have money, follow Daklu's advice. I could not find suitable examples, either. The hardware abstraction examples are wonderful for teaching inheritance. I get the feeling that people who use LabVIEW to develop applications have their own methods, and that people who use it develop one-panel data-grabbing VIs are overwhelmed by (and don't need) complex examples. A few experts have shown me their code, and it seems to me that it is more complicated than it needs to be - lots of upcasting and downcasting, etc. One gentleman has a base class called Instrument from which all other instrument classes inherit. This allows him a huge amount of flexibility, but it is hard for me to keep it all in my head. (What's the G equivalent of the old Linux book's quote: "400 lines of code is all most people can keep in their head at once"? 400 VIs? 400 classes?) My plan of attack, at the moment, is a single cluster of Somethings that can be accessed by name in any test (and in an emulator). Each Something is an Action Engine class, and includes an instrument class in its private data. Create the single cluster at the top-level and pass it around to the tests. Perhaps this is easier to do with some of the messaging systems mentioned on LAVA, but I'm not there, yet. Plenty of words from me, but no code, this time. A VI's worth 400 lines.
  20. This is exactly the kind of problem I've been trying to solve. I really like using classes, since the instruments must sometimes be swapped out. But I can't quite figure out where to keep the class wires so that they're available to the tests AND to some other processes (simulation, for example). Some are kept in AEs, which makes it easier to access them from tests with a set of AE wrapper VIs. Now I'm trying to instantiate an AE class in order to create multiple AEs - but that brings back the original problem of where to keep that class wire.
  21. I'm not yet able to keep up with this discussion. At the risk of being a distraction from the topic at hand - and at the greater risk of causing more confusion than clarification by posting incomplete code - here is a stripped down project. (Note that queue destruction and error handling are not completely implemented, here. Nor are all the accessor, and such. In the production code, many other helper VIs are in place.) The biggest pieces not included are the tests (which interact with instruments only via Data AEs and named queues), and the emulator - which also uses named queues to control what the simulated instruments are doing. A user (or a VI) can move sliders and push buttons in the emulator in order to test the tests. Sample Project.zip
  22. My code has evolved into a similar (if less refined and sophisticated) pattern. Each physical instrument's slave loop responds to "show" and "hide" messages to display the front panel. Many of the instruments are streaming, so there are Start and Stop buttons, and appropriate displays of data that's being sent off to data queues (AEs). There are several different test VIs. Each test calls some of the instruments and some of the data queues (flexibility is key). Each test is called by reference so that "Main.vi" can do other stuff - such as run parallel tests with the other instruments, or allow the user to click Show and Hide buttons so they can watch the pretty data stream on by (or view the current collection rates or dropped packet count). The way I initially chose to use an instrument in a test is: 1. create a class in the top-level VI 2. send it to a dynamically dispatched* "handler" - the slave loop, which has a named queue 3. from a test, send messages to the named queue I'm trying to figure out how to get more flexibility in a test. If I add a duplicate instrument, I have to create a second named queue handler - along with its associated "add to queue" VIs. Perhaps I'll try bundling up all the instruments' classes and send them to the test. However, I also have "simulator" child classes of each instrument. A different top-level VI (separate app) has buttons for sending fake data on any instrument that was defined by the user as being simulated. Class methods are used for setting private data, and are accessed via the named queue. I want to start using a class that holds an instrument's class in private data (due to one version of an instrument having a custom GPIO interface that consists of several NI DAQ resource names, and another version having ethernet), but I haven't figured out how to access that class from another top-level VI without using something like a named queue. * This is dynamic because multiple versions of multiple protocols for multiple instances of multiple instruments must be continuously supported.
  23. Apparently, it's okay for a Slave to miss a Master's command (slow Slave, quick Master) - but not for a Consumer to miss a Producer's.
  24. You are writing to the graph twice - once with a local variable. Cluster To Array may be useful, here. Thermocouple Detection b.vi
×
×
  • Create New...

Important Information

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