LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

32 instruments, 32 action engines?

Hello, LabVIEW community,

 

I was wondering if I could get your thoughts on something.  I enjoy a good functional global as much as the next programmer, and I use them all the time.  I really like the "Action Engine" idea (Ben's nugget was terrific) and would like to incorporate it in my next application...which I am designing now.

 

While it may not be particularly large compared to many of the large applications I've read about on this forum, I will be controlling as many as 32 separate instruments...user selectable as to which ones are present in the system and which ones aren't, of course.  Staying organized is going to be key here.

 

I am thinking about using AEs to handle my instrument communications.  The AE would have states such as Initialize, Write, Read, and Close (and maybe Idle).  Does it make better sense to have a separate AE for each instrument, or does it make better sense to use a single AE and arrays to hold the data items for each module (i.e. an array which holds the instrument session reference, one that holds the setpoints, and one that holds the query data returned by the instrument)?  I'm leaning towards separate AEs for each instrument but I'd like the community's thoughts.  I could see getting tangled up in all those arrays, but the idea of having 32 more-or-less identical subVIs also rubs me a bit wrong.  Each instrument writes only 1 parameter, and but could read a maximum of 2 parameters.

 

My client wants front panel updates of roughly a zillion parameters (yes, I am putting a LOT of thought into designing my UI so it doesn't become a cluttered nightmare -- hooray for the tab control!), but also wants to set various parameters for each instrument on the fly.  For instance, one of the instruments is an ILX controller containing 16 TEC modules.  If the user changes the temperature setpoint on one of the TECs, I don't want my "monitor" loop to have to stop querying and displaying the other 15 TEC currents and temperature readings.

 

I can think of a couple of ways to accomplish that.  I would use an event structure to capture the user events (such as flipping a switch which turns Module 0 on), while the instrument monitoring would occur in a separate loop.  When an event occurred, I could imagine sending a flag to the monitor loop which would change the AE input for that module to "Write", reverting it back to "Read" when the flag had been reset.

 

I could also imagine having the AE right there in the event structure case, but perhaps that would slow down my front panel update loop?  The AE in the monitor loop wouldn't be able to execute until the one in the event structure was finished. 

 

I would love to hear people's thoughts on these things...my questions are more of a philosophical nature, not a "how do I do this?" nature.

 

I appreciate your time!

d

 

 

Message 1 of 20
(3,994 Views)

What you want to do is to create the code for handling the instrument and then dynamically create N (32, at the moment) copies of it when the program starts running. This is fairly easy to do quite easy to do using VI server by calling Open VI Reference and the Run VI method. What you get is an array of references to the VIs which are all running in parallel (i.e. the VI will have a loop and will keep running until you send it a stop command). You can then use queues and/or notifiers (again, dynamically generated by name) to communicate with the VIs. I don't have an example on hand, but the example finder probably has some and there are probably tutorials on this site which deal with this archictecture.

 

Another thing you may want to consider is LVOOP. You say that the VIs would be more-or-less identical. If you use LVOOP, you should be able to write the shared part once. You can do this without LVOOP, but you will need to know what you're doing (which you'll actually need with LVOOP too, but that's life).


___________________
Try to take over the world!
0 Kudos
Message 2 of 20
(3,961 Views)
P.S. Near the end of Ben's nugget you should find an example I posted of GOOP (not LVOOP, which is native and different) which demonstrates the creation of N objects. It doesn't use action engines which has some advantages which are detailed there.

___________________
Try to take over the world!
Message 3 of 20
(3,959 Views)

Hello tst,

 

could you post  the link you are refering to ?

 

Best regards

 

Tinnitus

 

 

CLAD / Labview 2011, Win Xp
------------------------------------------------------
Mission d'une semaine- à plusieurs mois laissez moi un MP...
RP et Midi-pyrénées .Km+++ si possibilité de télétravail

Kudos always accepted / Les petits clicks jaunes sont toujours appréciés
Don't forget to valid a good answer / pensez à valider une réponse correcte
0 Kudos
Message 4 of 20
(3,929 Views)

http://forums.ni.com/ni/board/message?board.id=170&view=by_date_ascending&message.id=305242#M305242

 

You should read the rest of the thread as well. You can search to find a download of dqGOOP or try using LVOOP.

 

Diane, here's the VI posted there:

 

 

The Create VI returns a reference to the object. In your code, the create VI could dynamically run the process VI and then return a reference to the queue you use to communicate with it (or you could have a number of references in a cluster, in which case you might be better off using LVOOP). Then, you just call the VI N times to have N objects.


___________________
Try to take over the world!
0 Kudos
Message 5 of 20
(3,917 Views)

Hi tst!

 

Thanks very much for the reply!  I actually did go back and look at the nugget, find your post, and download your code so I could take a look inside it.  I was going to reply to you and then the website went down. 

 

LVOOP might be a good way to go here.  I hadn't considered it as a solution, and you now have me thinking in a different direction...which is exactly what I was hoping for when I posted the question.  I am familiar with OOP concepts and have done a couple of tutorials on LVOOP, but I have not actually used it in an application yet.

 

I was originally told by the EE that specified the power supplies that they all use a GPIB interface.  Turns out that's not true.  (I downloaded all the manuals yesterday.)  It's actually going to be a master/slave architecture via RS-422.  The master communicates with the computer via GPIB, but then does an internal translation so that all of the slaves are communicating serially.  They're separately addressable, but I actually can't query them in parallel or I'll get a collision.  😛

 

I'll essentially have 3 sets of instruments.  Set 1 will be all of the seed power supplies, configured in a master/slave architecture as described above.  Set 2 will consist of the amplifier power supplies, again a master/slave.  Set 3 is the ILX chassis with the 16 TEC controllers in it (probably also a master/slave but I haven't had time to get further into what that interface really looks like...I'll be downloading that manual tonight).  So I'm looking at 3 parallel interfaces consisting of master/slave serial interfaces.

 

So coding it up such that I wind up with an array of references would have some nice flexibility built into it and could accommodate either serial or parallel communication.  I really like the idea of only calling as many instances of the VI as I need.  It seems like it would also be fairly straightforward to add instruments on the fly, as the program is running. 

 

Thanks for the post!  I think this is starting to solidify in my head.  If you (or anyone else!) have more ideas, I'd love to hear them.

d

0 Kudos
Message 6 of 20
(3,898 Views)

DianeS wrote:

They're separately addressable, but I actually can't query them in parallel or I'll get a collision.  😛


I would suggest a single non-reentrant VI for doing both the writing and the reading. That will guarantee a simple lock so that you don't have to worry about synchronizing this.


___________________
Try to take over the world!
Message 7 of 20
(3,883 Views)

Good discusion all!

 

Diane you have touched on a topic that I felt was outisde the scope of that Nugget but is a logical extenstion of it.

 

What Code goes into whiich AE?

 

From what I have learned rom my wife regarding DB design (fully normalized data) AE design is not far off but due to then general requirement of fast perfrormance, a slightly -de-normalized DB.

 

Now in my own words...

 

I first go through an exercise on paper that list and groups the data associated with the various widgets involved in an app. Durring this exercise I try to group values that are used together into clusters taking care to make sure that un-related values don't get grouped together.

 

THe next step is to start figuring out whcih values are "touched" by which things. This leads into characterizing the "value" and how it can move from one piece of code to another. This step tells me "where will this value Live". If the data starts out one place and is just looked at by others I try to put it into a queues since their nature is move things on modified from one place to another.

 

Whatever data I can't assign to one of the native comm services (like queues) then I turn to an AE to fill in the blanks.

 

You and tst have started this part of teh design alredy and I agree with Yiar's suggestion to use an AE to act as the traffic cop cotrolling access to the GPIB.

 

So I think the best I can do for you at this point is to encourage you to sit down and document all of your data structures. Cast them using native LV operations and whatever does not fit, list all of the operations (types of touches) that occur with each set of data. These operations become you "Actions" and the associated paratemters that goe with these actions define the interface of your AE.

 

Last point for now...

 

I have been gradually moving more of my code under a LVOOP umbrella since LVOOP methods are close to AE Actions and LVOOP operations can be code to operate on a "Core" that looks a lot like an AE.

 

Now if there is someone out there that knows DB design and teach us alittle about "what goes where", please step-up and enlighten us!

 

Have fun!

 

Ben

 

PS Thanks to both of you (and anyone else ) for citing the AE Nugget. I am very pleased that that document has served the community to a greater extent than I ever imagined. It was worth the time.

Message Edited by Ben on 05-11-2009 07:55 AM
Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 8 of 20
(3,855 Views)

Read's Digest reply to original Q

 

Use a single non-reentrant VI to control access to the hardware (make sure your response goes with your query).

 

If the widgets interact in some manner and that interaction can not be sliced off in some manner (like the non-reetrant above) then use a single AE to ensure proper syncronization between each widget.

 

IF they can be sepearated then slam each instance into an instance of the LVOOP based state machines and interaqct with them using queues. ( THe queues can be kept in an AE if many "things" need to touch the widgets.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 9 of 20
(3,850 Views)

Thanks for chiming in, Ben!  As always, your comments are very helpful.

 

I got started last night on trying to rough out what this would look like if I used LVOOP.  I decided that the parent class would be "Instrument".  The child classes are "Seed driver", "Amp driver", "TEC driver"...and, it turns out, perhaps also "Chiller".

 

Now.  What types of data (properties) do these things have in common?  They each have an instrument address...they have the same methods ("Open Comm", "Write", "Read", "Close")...they all send ON/OFF commands...they all send setpoints...they all receive ON/OFF status...they all receive data readings.

 

What's different about them?  Well, command syntax, for one.  The number of parameters they read, for another.

 

Do they need to interact?

 

Yes...the seed can't turn on until the TEC has stabilized at the temperature setpoint.  The amplifier can't turn on unless the seed is on and its power level is stable.  The seed can't turn off unless the amplifier is off.

 

So one element from each class combines to form a module, and those modules work as a team.  I had already decided to use a single VI (what I was thinking of as my AE) to handle all of the methods for each instrument, so that they couldn't collide -- that is, to prevent attempting to do a Read and a Write simultaneously.  Poking around the LVOOP shipping examples, I liked the idea of using Enqueue and Dequeue to lock and unlock the data.  That allows my event structure to execute Write commands if a value is changed or a switch is flipped, while not colliding with what is going on in the monitor loop.  I believe that what tst is telling me, though, is that doing it that way isn't necessary if I use a single non reentrant VI.

 

To execute a Write command, I have to go through a series of checks.  If any of the checks fails, I'd have to exit the VI and perform the necessary action (on a different instrument), then try the Write command again.  Or perhaps it's not necessary to exit the VI.  Hmm.

 

Ok.  I'll need to think about that a bit more.

 

Now I move on to the question of assigning the correct data (instrument ID, for instance) to each instrument when I'm dynamically spawning VIs.  I think that could be handled by assigning another identifier to each instrument (module number?), and using the identifier to select the appropriate value from an array constant if that module is enabled.  Those values would be used to initialize the instrument properties.

 

Am I unnecessarily complicating things here?  Are there major flaws in my thought process?

 

Thanks guys!  Your thoughts have been extremely helpful and I really appreciate your taking the time to respond.  Keep those comments and suggestions coming!

d

0 Kudos
Message 10 of 20
(3,823 Views)