LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Using Refrences with Express VI's.

Hello everyone,

 

I am currently working on merging two functional VI's together.  They both work as intended, but they both need to run inside of independent while loops.  The issue I am running into is writing the data from both loops into the same spreadsheet.  I have tried using refrences to these values and merging the refrenced variables with the signals in the other while loop, but the refrences simply aren't the right data type.  I have attached a small chunk of my block diagram below to show my issue.  

Thank you,

Jackson

0 Kudos
Message 1 of 9
(3,451 Views)

You are going to have serious problems as you are over-using Express VIs and creating a potential nightmare of a data file.  I don't understand why you are merging two independent streams (which might be running at different rates) into a single file -- how do you plan to disentangle and disambiguate them?  At the least, you'd have to write an ID ("From Loop N") in front of each record.

 

I think this needs further thought and design from you.  You'll help yourself a lot by learning about the basic LabVIEW (non-Express) VIs for File I/O (they are not so difficult).

 

Bob Schor

0 Kudos
Message 2 of 9
(3,369 Views)

Hello Jackson,

 

I also feel like you could probably resolve this problem more easily if you extricated yourself from the Express VIs.

That being said, in general if I wanted to store data from two sources in one file, I'd create a single loop with the purpose of writing to file, and then send data into that loop as needed.

This is in general, a Producer/Consumer setup with 2 producers and a single consumer.

 

As Bob_Schor already pointed out, unless you have some way of labeling them, it will be difficult (impossible?) to distinguish the values in the file (except by value, perhaps?).

Attaching the Channel Names, as you appear to be trying to do (although I think the way you posted it, it won't work how you want - perhaps you simplified when posting to this thread?) is one possible solution.

Other systems are possible, but tricky with text files.

 

Writing directly via the Text File methods is likely to simplify the reading, understanding and manipulation of your code.

Here's a link to the help pages for the File I/O Functions, of which you probably want to consider Open/Create/Replace File, Close File, and Write to Text File.


GCentral
0 Kudos
Message 3 of 9
(3,359 Views)

Thank you both for your responses.  I can now see why express VI's can begin to cause issues, but I would not have thought to delete the express VI. I will be setting this program up with the File I/O pallete instead of the Express VI in the next few days. 

 

I've started trying to implement the producer/consumer structuring, but am struggling to see how to implement it with my VI (attached below).  In every example I have seen the producer is dependent on user events, but I need both programs to read without a button dependence.  They are currently functioning in this way.  How would you suggest approaching this?

 

Thank you,

Jackson

0 Kudos
Message 4 of 9
(3,313 Views)

If you open LabVIEW, click File, New ... (the three dots are important), then choose the From Template, Framework, Design Patterns, Producer/Consumer Design Pattern (Data).

 

This will show you a Producer, where data are Generated (think a DAQmx structure with a Start DAQ function to the left of the While Loop, a Read DAQ inside, with the data wired to the Queue (make the Queue type the same as the DAQmx output, e.g. 2D Array of Dbl, 1D Array of Waveform, etc.), and Stop DAQ function when the loop exits.

 

There is a slightly "bad" aspect to this Template.  You should (probably) not stop a Producer/Consumer Design by having the Producer kill the Queue, thereby causing an Error to be generated in the Consumer (because there's no Queue and you are trying to do a Dequeue).  Yes, this can be used to mean "The Producer has quit", but means you can't meaningfully use the Error line in the Consumer "downstream", such as doing something "inappropriate" in processing the data.

 

A "better" way is to pass a "Stop" signal from the Producer to the Consumer.  For example, if you are sending data from DAQmx, and your Queue element is an Array, you could send an empty Array to the Consumer when the Producer exited (replacing the Release Queue).  The Consumer, when it dequeued the data, would add a test for an Empty Array (which takes essentially 0 time) and use the "True" case to mean "Time to Exit", and "False" to mean "Process the data".  Now, when the Consumer exits, it knows (a) that the Producer has finished, and no more elements are coming from it, and therefore (b) it is safe, once it exits its While loop, for the Consumer to Release the Queue.

 

Bob Schor

0 Kudos
Message 5 of 9
(3,294 Views)

I have recently for examples and perhaps soon for real code found I quite like explicitly bundling a boolean into my queue datatype indicating a last element. 

 

For me, this is the most valuable part of the new(ish) channel wires, and so I've decided (more or less) to simply copy it.


GCentral
0 Kudos
Message 6 of 9
(3,286 Views)

I also like having the sentinel built into the Stream Channel.  By being "separate" (not part of the data), it expresses a unique function.

 

Bob Schor

0 Kudos
Message 7 of 9
(3,276 Views)

Hi all,

 

I have been working to impliment this structure, and ultimatly I have gotten lost.  I do not want to push a button to record the data, but it seems like simply pulling this out of the event structure is not the correct way to do this. I have attached the updated VI below with the hopes that I am simply making a mistake in the set up.  If you have a chance could one of you take a look at it for me? 

Thank you,

Jackson

0 Kudos
Message 8 of 9
(3,239 Views)

Hi Jackson,

 

I took a look at the VI you uploaded and can see that it is based on the template that was already mentioned, but I think you have not quite understood a key point:

  • In LabVIEW, we use something called "dataflow" programming
  • Essentially, any function operates as soon as all of its inputs are available
  • Outputs all become available from a function (or a structure) at the same time
    • Queues and similar tools (notifiers, references, etc) are something of a deviation from this - they allow communication "through" the edges of structures
  • A structure (like a While loop, For loop, Case structure) will not start (either at all, in the case of a Case Structure, or the next iteration in the case of a loop) until all the inputs are available
  • Loops do not finish an iteration until everything in the iteration is complete
  • Therefore crucially, your producer loops must wait for the Event Structure to be triggered in order to iterate
  • This means that the producers will only go to the next iteration (and re-read values etc) when a triggering event occurs:
    • For the first loop, this requires the clicking of Stop2, which stops the loop
    • For the second loop, this requires the clicking of either Stop or Write Button 2.
    • These are likely not what you want.
  • You could implement a timeout case, but it's likely this isn't the structure you need in exactly this form. I believe you had a previous forum thread on this application with some significant number of posts trying to guide you in your design.

I'd suggest looking at some more of the introductory training material until you're comfortable with the "dataflow" concept. It is really very important to the entire way in which LabVIEW works. These may be a possible starting location: LabVIEW Basics: Dataflow, Getting Started Videos, Module 5 (Block Diagram Dataflow) (although I'd say watch more than just that module of the videos if you don't hate videos for learning...)


GCentral
0 Kudos
Message 9 of 9
(3,229 Views)