01-28-2011 05:44 PM
Hi All:
Now I am trying to develop a project with CRio.
But I am not sure how to build a array with high sampling rates signal, like >1K. (Sigle-point data)
Before, I would like to use "Build Arrary" and "Shift Register" to build a arrary, but I found it is not working for high sampling rates.
Is there anyother good way to build a data arrary for high sampling rates??
Thanks
01-28-2011 05:54 PM
If you know the final size (or a reasonable upper size limit) of the array, you should initialize the shift register with with an array of zeroes (for example) and a size corresponding to the upper size limit and then use "replace array subset" to fill in the real data. This avoids allocation problems. If you stop early, you can always trim the unused tail as a last step.
Keep track of the insert point in another shift register or calculate it based on [i], depending on the rest of the code.
01-28-2011 11:33 PM - edited 01-28-2011 11:41 PM
>1 k means you must be using FPGA right? NI really only recommends using the scan engine for data up to 1 kHz, you shoudl do some bench marking to make sure you are getting the rate you think you are if you are using scan engine.
That said, Altenbach is right, you need to intialize an array and replace array subset. What I have done on past projects is intialize an array that can hold 1 second of data (or less, it really depends on your cRIOs memory, processing power, etc). I replace array subset and keep a counter until I get however many points I am saving in the array, then I send it out to a host application via TCP/IP.
Now at this point I reset the counter to 0 and start replacing array subset on the same array.
A word of advice, open the distributed system manager and you can watch the memory on your cRIO. If you have properly architected your code and all arrays are initialized, you should never see the memory growing. If it shows more and more memory being used on the graph, you either have a queue queing up elements faster than you dequeue, arrays are causing memory to be allocated at run time, or you have some form of a memory leak. You can use RT FIFOs rather than queues to check if they are overflowing via a boolean returned by the RT FIFO Write VI. Ideally, your memory should spike at initialization as memory is allocated then remain constant throughout the entire runtime of your program on the cRIO.
Edit: didn't see your screenshot, you are using FPGA. The more standard way to do this is use an DMA Target to Host FIFO to pass data rather than reading a control. Reading a control results in lost data because it is pretty much impossible for your RT code to keep up with the FPGA. Controls are typically used more for handshaking between the RT and FPGA. Afterall, why take data at a fast rate on FPGA if your read rate is limited by the speed of your RT processor? If that was the case you could just use cDAQ, DAQmx and save a lot of money! If you use DMA FIFOs you can take data, at say, 10,000 hz, much faster than the RT processor can go, and on the RT side, read an array from the FIFO of size 10,000 elements. This requires your RT code to only have to loop at1 hz and get 10,000 data points, while the FPGA is going at 10,000 hz to acquire them all.
Sorry thats so wordy, I'll try and post some screenshots tomorrow when I have a computer with LabVIEW on it.
01-31-2011 10:24 AM
Thanks a lot, can you give a simple sample code?
01-31-2011 01:40 PM - edited 01-31-2011 01:49 PM
Can't give a sample of the FPGA right now but here is a sample bit of RT code I recently used. I am acquiring data at 51,200 samples every second. I put the data in a FIFO on the FPGA side, then I read from that FIFO on the RT side and insert the data into a pre-initialized array using "Replace Array subset" NOT "Insert into array". I keep a count of the data I have read/inserted, and once I am at 51,200 samples, I know I have 1 full second of data. At this point, I add it to a queue which sends it to another loop to be processed. Also, I don't use the new index terminal in my subVI because I know I am always adding 6400 elements so I can just multiply my counter by 6400, but if you use the method described further down below , you will want to use the "new index" to return a value because you may not always read the same number of elements using that method.
The reason I use a timeout of 0 and a wait until next ms multiple is because if you use a timeout wired to the FIFO read node, it spins a loop in the background that polls for data, which rails your processor. Depending on what type of acquisition you are doing, you can also use the method of reading 0 elements, then using the "elements remaining" variable, to wire up another node as is shown below. This was not an option for me because of my programs architecture and needing chunks of 1 second data. Had I used this method it would have overcomplicated things if I read more elements then I had available in my 51,200 buffer.
Let me knwo if you have more qeustions