LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Best practices for complex recipe-based system?

Hi Folks,

 

I'm at about the intermediate level (working on my CLD), and tasked with re-vamping a tighly-developed control system(which I'm intimately familiar with) into more of a configurable 'recipe'-based system. Basically the current front-end control software does a lot of the work for the end user - it pre-defines flows, assumes certain electrical/plumbing configurations, etc. This is fine for the 'production floor', however the R&D guys would like something a bit more configurable.

 

This system comprises of several flow controllers, mostly controlled/monitored via analog I/O (compact FieldPoint). There's some static analog input channels devoted to temp, humidity, etc. There exists the possibility of 1-2 external RS232 metering devices as well.

 

Anyway I'm trying to work out the foundation for the UI. In terms of architecture think a que-ed state machine is my best bet due to the number of parallel processes occuring at once (analog acq, multiple serial comm, TDMS, UI, etc).  Basically I'd like the user to be able to add/remove/modify 'steps'. For instance, "Set Flow: controller IDx, 20cfm", or "Time Delay, Static: 10:00", "Time Delay, Psuedo-Static, based on X". 

 

I've worked out a configuration UI (utilizing the in-build NI configuration storage VIs) to associate the analog channels to external devices (ie Aout1="Controller1 SP", Ain1="Controller1 FB"). Later I'll populate a ring control, for instance, for the 'add SetFlow step', to list all of the analog OUTs for selection.

 

So I guess what I'm looking for is advice on passing all this info around without having to re-hash it all the time to present to the user. Keeping in enum/ring allows for easy user viewing, changing, and block diagram readbility (vs string constants, which are error prone) - is this something that the 'flatten to string' would be helpful for (something I have no experiance using).

 

What tips can you provide for moderate-complexity HMI control systems developed strictly in LV? We currently don't have DSC, and I'm a bit closed-minded about using it for this (but perhaps you can convince me otherwise?).

 

Thanks for your time,

Jamie

Message Edited by 8bitbanger on 04-21-2010 08:10 AM
v2009 devel. w/RT
0 Kudos
Message 1 of 10
(4,864 Views)

Rings: Use the property node 'Strings []' and index array with index=value of the ring to obtain a string.  They are good for the UI, as you can populate them at run-time. Enums cannot be populated at runtime.

 

On architecture, I like to have all the functions (SubVIs) of that piece of information together. You can use a kind of action engine or use LVOOP for it.

 

Felix 

Message 2 of 10
(4,849 Views)

F. Schubert wrote:

Rings: Use the property node 'Strings []' and index array with index=value of the ring to obtain a string. 


At first I was going to reply that this can be done easily with the 'Format Into String', but that trick only works on enums. 🙂

 

I don't understand your second point however - you're saying you compartmentalize VI's for each recipe 'step'?

v2009 devel. w/RT
0 Kudos
Message 3 of 10
(4,836 Views)

8bitbanger wrote:

 

[...]

Basically I'd like the user to be able to add/remove/modify 'steps'.

[...]

What tips can you provide for moderate-complexity HMI control systems developed strictly in LV?


I have coded several of these "recipe builder" programs, and I almost always resort to Replace Array Subset for the function that inserts, deletes, and modifies the "recipe", and the recipe being a string array. I have attached a picture of one of my recipe builders.

 

As far as the HMI, I like to use a Main Selector which allows the user to select a proper noun which will perform an action (like Pump, Valve, Wait, Laser), and a Modifier Section where the user selects what the proper noun will do. The picture also shows an example of this. As another device is selected, the Modifer Section changes (controls are stacked up in a transparent tab control).

 

Maybe this gives some ideas.

 

 

 

 

Message Edited by Broken Arrow on 04-21-2010 09:49 AM
Richard






Message 4 of 10
(4,829 Views)

Here is how I manage my recipes:

I use an Action Engine with the following Actions (Enum): Load, Save, List

The AE-VI has the data cluster (it is also a type def) as input and output. (+ some more)

There might be some SubVIs for the code of the different Actions. 

Above all there are wrapper VIs which e.g. make the data in a required input for the Save Action.

 

A nice thing is also to make the List Action having an optional input of a ring reference, and populate it if it is a valid reference. 

 

The idea behind is, that any operation you might want to do with that recipe is going to the same location in the code. This concept is native to OOP, where all methods you perform on the object data reside inside the class. 

 

Because I use recipes in all my projects, this is a template in my reuse lib, all I need to modify is the data cluster type def and the folder the recipes are stored in. 

 

Felix 

0 Kudos
Message 5 of 10
(4,803 Views)

Cool, thanks for the screenshot!

 

This request for more customization was anticipated, so I began working things in last year with other minor revs. The first was this 'hardware configuration' utility. Right now I'm only using the MFC Config page for channel scalling/name info. (the production version still relies on 'static' channel associations to control devices). The enum 'card/slot' selector does exactly as you mentioned - it controls a tab value, which loads other pages (with similar info).

 

config_UI.JPG

 

The second 'generator' page is used to populate a list of generators available for the user to select, and works quite well - users can add somewhat custom generators to the list w/out having to specify "custom" every time (and I don't have to rebuild to add such a simple thing).

 

You can see the 'Flow Control' and 'Monitor' channel that have not yet been implimented. 🙂

 

generators.JPG

 

Lastly the mockup is where I want to end up. I *wish* that labview was able to incorperate enum/ring drop-downs within a table cell (without the hacks that I've seen suggested).

 

I intended to setup a similar format for the 'steps' - an Action (or noun as you say), Target (ie file path, device name, etc), Value (setpoint, other pertinent data), etc. Do you pass this info around as a cluster in your VI then simply parse out to the UI in the steps listing? My hurdle is how to ellegantly relate, say, a CSV file back to the enums without a lot of hard-coded (constant) strings.

 

mock-up.JPG

 

 

Cheers,

Jamie

::edit:: *Finally* found the button to insert images... ::edit::
Message Edited by 8bitbanger on 04-21-2010 10:30 AM
v2009 devel. w/RT
Download All
Message 6 of 10
(4,791 Views)

8bitbanger wrote:

Cool, thanks for the screenshot!

[...]

Do you pass this info around as a cluster in your VI then simply parse out to the UI in the steps listing?

 


You are welcome Smiley Happy

 

The shown recipe builder uses strings, and I carry around the data in a string array. For each recipe step, the parameters are seperated by a colon in the string.  I limit each step to a known quantity of parameters, so the parsing is as easy.

Richard






0 Kudos
Message 7 of 10
(4,762 Views)

It sound like you are going about the re-development smartly.

 

One tip I might add-  essentially your "steps" form a "matrix" with "Vectors" of "common elements" and "State specific options" 

 

Steps run in states many steps may call the same state with different options

 

common elements are available to all states  (like Limits, result, measurement, flow control[I use Auto, Skip, DNP, BK, BKoF to normally run, skip, do not populate, Break after or Break after if result is not pass] etc... )

 

Options pass as varients. so the same queue can give different data types to different states.

 

OR: consider TestStand-  for a high-mix testing where divergent station configurations can support multiple tests on various flavors of targets (or control different plants) you might want a common base to store your reasources, plant configurations and execution model options.

 

I'm not a "big" TS adopter- but acknowledge its usefulness for this type of "over-all system" level consistancy for the user and adaptability for the developer


"Should be" isn't "Is" -Jay
0 Kudos
Message 8 of 10
(4,748 Views)

Jeff Bohrer wrote:

[...]

common elements are available to all states  (like Limits, result, measurement, flow control[I use Auto, Skip, DNP, BK, BKoF to normally run, skip, do not populate, Break after or Break after if result is not pass] etc... )

[...]


I was on the same page as you up until this - other than error reporting (ie the state handler was unable to receive an ACK from the device), I think adding conditional states is a bit much for me right now! I suppose this all depends on the process as well - some are more heavily dependant on process feedback than others. Even say a 'tank fill 90%' step, I would think would be handled by a subVI that also processed the feedback.

 

I envisioned a producer/multiple-consumer queue regime. The producer would handle stepping down through the states, and que out actions. Send the 'Set Flow' step/state, with (variant) parameters to the 'FlowController' que, send the RS232 command to the RS232 queue, etc.

v2009 devel. w/RT
0 Kudos
Message 9 of 10
(4,737 Views)

F. Schubert wrote:

[...]I use an Action Engine with the following Actions (Enum): Load, Save, List [...]

 

 A nice thing is also to make the List Action having an optional input of a ring reference, and populate it if it is a valid reference. 

 

Felix 


 

This was how I anticipated doing this as well, but hadn't thought of streamlining into an Action Engine - great idea! The wrapper VI's may change depending on the defined 'steps', but none-the-less...

 

v2009 devel. w/RT
0 Kudos
Message 10 of 10
(4,732 Views)