LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Array of instances ?

Hi Labview Community

I've programmed a little vi (called rbuf) , which takes incoming array
data and appends it to a ringbuffer array. The vi is defined as
"reentrant", so that several instances can be used.

Everything works fine. I aquire data from 2 measurement channels,
which is given to two different rbuf-vis.

Now i want to extend my application to 16 channels. The acquisition of
data is done now in a loop, but how should i call the correct and
different instances ?

In IEC programming i could use something like that:
Declaration
Q : array [0..15] of rbuf;

Program

for k:=0 to 15 do
Q[k].data_in:=messkanal[k]; (* array data of a measurement
channel *)
Q[k](); (* execute instance for
ringbuffer *)
bufdata=Q(k).output;
end_for

I guess, in C# or C++ it is more a less the same principle.

How can i call in LabView (8.6) an instance of a vi by a proper index
number ?

Thanks in advance
Andreas
0 Kudos
Message 1 of 13
(3,406 Views)

Is the subvi sending the ringbuffer array back to the main vi?   If so, I'm not sure why you need separate instances. 

 

If not, just use a 2-D array and index the array column to the channel that you want to change.  You can store the data in an initialized shift register.

 

 

>

"There is a God shaped vacuum in the heart of every man which cannot be filled by any created thing, but only by God, the Creator, made known through Jesus." - Blaise Pascal
0 Kudos
Message 2 of 13
(3,403 Views)

You need 16 separate instances of the same VI. The easiest method is to generate them dynamically by calling the Open VI Reference primitive in a for loop and building the resulting references into an array. You can then use the references to call the VI using the Call By Reference node.

 

Note that you will need to use the VI's type as an input to the open function (use a static VI reference) and that you need to tell the function that you want to call the VI as reentrant (using the flags input. It's documented in the help for the function). You can also use the static reference to get the VI name using a property node.


___________________
Try to take over the world!
Message 3 of 13
(3,384 Views)

Another (less scalable) option is to put a case structure inside the for loop and link the iteration counter to the case selector.

Now create 16 cases (0 through 15) with the ringbuffer in each case. This way you load the VI 16 times into memory.

 

Ton

Free Code Capture Tool! Version 2.1.3 with comments, web-upload, back-save and snippets!
Nederlandse LabVIEW user groep www.lvug.nl
My LabVIEW Ideas

LabVIEW, programming like it should be!
0 Kudos
Message 4 of 13
(3,357 Views)

TonP wrote:

Another (less scalable) option is to put a case structure inside the for loop and link the iteration counter to the case selector.

Now create 16 cases (0 through 15) with the ringbuffer in each case. This way you load the VI 16 times into memory.

 

Ton


 

Yes but he has not asked about reading from them so he would half to use uniquely named VI_Ring_Buffers in each case and an equivilent to read the data out.

 

I wrote a number of these years ago but even since the introduction of polymorphic queues, the ring buffers have been rare.

 

I would like to suggest the questioner concider using an array of queue references instead of an array of refs to ring buffers. I have not used the new lossy queues yet but that feature reads like a ring buffer. If they will fit the app req's they will out perform a ring buffer since they can operate in-place.

 

Just trying to through out other ideas....

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 5 of 13
(3,343 Views)
On Jan 21, 7:51 am, Andreas <AJ.Geiss...@googlemail.com> wrote:
> Hi Labview Community
>
> I've programmed a little vi (called rbuf) , which takes incoming array
> data and appends it to a ringbuffer array. The vi is defined as
> "reentrant", so that several instances can be used.
>
> Everything works fine. I aquire data from 2 measurement channels,
> which is given to two different rbuf-vis.
>
> Now i want to extend my application to 16 channels. The acquisition of
> data is done now in a loop, but how should i call the correct and
> different instances ?
>
> In IEC programming i could use something like that:
> Declaration
> Q : array [0..15] of rbuf;
>
> Program
>
> for k:=0 to 15 do
>    Q[k].data_in:=messkanal[k];   (* array data of a measurement
> channel *)
>    Q[k]();                                   (* execute instance for
> ringbuffer            *)
>    bufdata=Q(k).output;
> end_for
>
> I guess, in C# or C++ it is more a less the same principle.
>
> How can i call in LabView (8.6) an instance of a vi by a proper index
> number ?
>
> Thanks in advance
> Andreas

Wouldnt it be just as easy to build a 2D array? You can continuously
append data in a loop to it. If your application is not too CPU
intensive using the "enable indexing" feature may be your best bet.
0 Kudos
Message 6 of 13
(3,262 Views)

Andreas probably doesn't need this answer any more, but his method has several advantages over using a 2D array -

  1. It allows you to have arrays of different lengths. If you're using a 2D array, each row and column has the same length.
  2. It allows you to use several blocks of memory instead of a single block. If your data is large, this is important.
  3. It allows you to more easily access the different arrays in different parts of the code.
  4. He defined his VI as a ring buffer, which means it probably maintains a constant size of the buffer while rotating the data. This is harder and more inefficient in a 2D array.

There are probably some others, but this is just off the top of my head.


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

tst wrote:

You need 16 separate instances of the same VI. The easiest method is to generate them dynamically by calling the Open VI Reference primitive in a for loop and building the resulting references into an array. You can then use the references to call the VI using the Call By Reference node.


tst,

 

Will spawning the required no. VI instances from a VIT set with Reentrancy be a better approach compared to this?

 

I need idea/opinion on this for my application (which is not a ringbuffer, of course), that need something similar to this.

I need to decide on how many times I must perform some operation on data based on the no. of devices connected to the H/W & group each of those datasets seperately & write to result file.

- Partha ( CLD until Oct 2024 🙂 )
0 Kudos
Message 8 of 13
(3,245 Views)

Hi Partha,

 

If speed is an issue and you can't process your data in-place (not moving data is always faster than moving it Smiley Surprised ) then I push for using queues.

 

Here is a rough outline of how I see the various comm mechanisms from fastest to slowest.

 

 

 

If I have something wrong in this list please feel to reply with your thoughts.

 

1) "In-Place" Nothing is faster (aside from not doing anything). AE's can take advantage of this. Issue is AE can become a bottle-kneck.

 

2) "Queues" when passing data from one place to another and there is no wire-forking only the pointer to the data has to be moved. Draw backs: Wire-forking can cause data copies (like when posting to two queues). Can not p operate cross context (one projects queues can not interact with the queues from another running project) Same applies to between computers.

 

3) "Local variables" Can operate without switching to UI thread. Draw backs; Force data copy for each local in app. Prone to race conditions.

 

4) "Property node >>> Value" No data copies required but force a switch to the UI thread.

 

5) "UDP" can talk cross context and fast but are "lossy" so the data may not make it there.

 

6) "TCP/IP" Not lossy but more overhead. Can talk cross context and anywhere you have conectivity.

 

7) "File I/O" Survives power failures but speed limited by disk sub-system.

 

9) "Tape" - If it were not for old Star Trek episodes or airline crashes is the term "tape" evn used these days?

 

10) "Paper" - Long term storage. Papyrus or velum recomnded.

 

11) "Stone" - If you really want info to stay around stone just can not be beat.

 

Have fun!

 

Ben

 

 

 

 

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

parthabe wrote:

 

Will spawning the required no. VI instances from a VIT set with Reentrancy be a better approach compared to this?


Since 8.something, there isn't really a difference between a reentrant VI and a VIT. Before that, reentrant VIs didn't have separate front panels or diagrams, but now that they do, they're essentially the same. There are some corner cases (e.g. placing into subpanels or if enable clone sharing for reentrant VIs). In any case, you should note that there is no need to make a VIT reentrant, since once you open a reference to it, you get a new VI anyway.

 

As for your question, I can't say I understood your architecture, but if you do need to keep all the data, I would go with Ben's suggestion of generating N queues, which is simpler.


___________________
Try to take over the world!
0 Kudos
Message 10 of 13
(3,212 Views)