Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

High sampling-rate data acquisition

Dear all,

I am using a PCI-MIO-16E acqusition card to acquire simultaneously from three analog channels at a rate of ~100KS/s per channel. I am using DAQmx 8.3 in a VB.NET 2003 program. I use asynchronous continuous acquisition (i.e. BeginReadMultiSample). I have ran into two problems with my program:

1. The first problem occours when I specify too low a number of samples to read in the BeginRead command. Every few callbacks there will be a gap in the acquired data (I plot the data later and find a small jump in the measured data which is timed to when the callback functio nwas called). I have managed to aleviate the situation by acquiring a larger number of samples in each read (several tens of thousands at the sample rate of 100KS/s per channel). Also I ofund that I can improve the situation by making my callback function more efficient than it was. I found that even when I acquire 100,000 samples at each read, I might get (on relatively rare occaisions) the aforementioned gaps inthe acquisition. Is there some way to get rid of these problem completely?

2. The second problem I've been runing into is a problem of CPU usage. I found out that when the sampling rate is 80KS/s per channel The CPU usage is ~1%. for 90Ks/s per channel it's up to 10% and when I sample at my desired rate of 100KS/s it's already up to a little over 50%. This is a serious problem for me, since when I tried to add image acquisition capabilities to my program (using IMAQ and PCIE-1429 card in IOD mode) The combined CPU usage was too much for my computer and it locked up (wouldn't response). The sharply nonlinear rise in CPU usage with the sampling rate makes this behaviour seem suspicious to me. Any suggestions as to how to go about it?

Many thanks,

Oded Ben-David.
0 Kudos
Message 1 of 9
(5,049 Views)
Oded,

What is the Operating System that you are running on?  Also, what is the RAM on your machine.  What is the number of samples that you are acquiring every iteration of your loop?  We have a bunch of PCI-MIO-16E cards, could you specify which one exactly you are using?  It also seems like you are not receiving any error and that the CPU is just locking up.  Make sure that you are not using any of the start task or stop task functions inside a loop, as they could be taking up memory and processor speed.

Regards,
Raajit L
National Instruments
0 Kudos
Message 2 of 9
(5,003 Views)
Raajit,

I am using a windows XP system, with 2GB of RAM. I found the same behaviour when acquiring between 1000 to 100000 samples each iteration.
I am using a PCI-MIO-16E-1 card (that's what it's called in MAX), I hope this is specific enough. If not, please tell me where I may find a more specific information. 

I am using asynchronous reading, so there is are no loops in my code. I issue a single Start command and then the first BeginReadMultiSample command. I pass a callback function to the beginread function which calls the next beginread command and deals with logging my data into an Object Collection.

Thank you for your assistance,

Oded
0 Kudos
Message 3 of 9
(4,940 Views)
 Hi Oded,

 1. Do the gaps in the measured data persist when you change the sampling rate lower?  What type of signal are you measuring in terms of frequency? Is it a periodic signal?
   
    If you run a shipping example, such as ContAcqVoltageSamples_IntClk, do you see this same behaviour?

 2. The CPU usage does seem abnormally high, perhaps using a WaitUntilDone() would help. Here is a forum post where this did the trick:
      http://forums.ni.com/ni/board/message?board.id=232&message.id=357&requireLogin=False

     Here is a second forum post where they had a similar problem: http://forums.ni.com/ni/board/message?board.id=232&message.id=4416&requireLogin=False
     The problem was a graph rendering a high amount of data without any graphics hardware acceleration.
 

Thanks, have a great week!

MatthewW
Applications Engineer
National Instruments


0 Kudos
Message 4 of 9
(4,913 Views)
Hi Matthew,

1. The gaps disappear when I lower the sampling-rate enough. It seems that I solved the problem by increasing the size of the input buffer. Now measuring 10,000 samples pre read seems enough to make the problem go away, and this is a workable number for me. I did not get this problem when I used the ContAcqVoltageSamples_IntClk_ToFile example. The only main difference I found so far is that the example program only acquires from a single channel, while I use three channels in parallel.

2. I was not ablt to understand how, ore where, I am supposed to use WaitUntilDone(). I do not have any loops in my code. I must be missing something here. I also tried changing the task.Stream.ReadWaitMode to Sleep but I did not see any effect on the CPU usage. I am currently using the Yield mode. I am getting the same high CPU usage problem when using the shipped in sample codes.

Thanks for your help,

Oded.
0 Kudos
Message 5 of 9
(4,878 Views)
 Hello Oded,

 1. That shipping example,ContAcqVoltageSamples_IntClk_ToFile, could be modified to increase the channel count to 3. I would be curious to hear back if it performed equivalently to your code, if not
then there is some programming difference that is causing the issue.

 2.  Here's the definition of WaitUntilDone() from the NI-DAQmx C Reference Help:   

You might need to call the Wait Until Done function/VI to ensure that the specified operation is complete before you stop the task.

The most common example is a finite generation. If you start a task that performs a finite generation and then immediately stop the task, the generation probably has not completed when you stop the task. As a result, the generation does not complete as expected. To ensure that the finite generation completes as expected, call the Wait Until Done function/VI before stopping the task. After the Wait Until Done function/VI executes, the finite generation has been completed, and you can stop the task.

In general, use the Wait Until Task Done function/VI with finite measurements and generations.

  Basically the WaitUntilDone() will delay the program long enough for the current DAQmx function to complete before proceeding.

I'm glad to hear your application is working a little better.

Have a great week,

MatthewW
Applications Engineer
National Instruments




0 Kudos
Message 6 of 9
(4,850 Views)
Hello Matthew,

1. I have modified the sample program to acquire three channels simulatenously (just added two more myTask.AIChannels.CreateVoltageChannel commands).  Now the sample program exhibits the exact same behavior as my own program. Up to about 80,000 samples per second per channel there is no CPU problem. At 90,000 Sps per channel the CPU usage goes up to ~25% and at 100,000 Sps per channel it is already ~50%. Going further up in the Sps per channel does not change the CPU usage very much however. At 400,000 Sps per channel (almost the highest I can go to) it's only up by a few percent more (~57%).

2. I have of course read the help on WaitUntilDone, but I still do not understand how it can be relevant to my (or the sample program) code. Since I am using asynchronous acquisition, all the program does is call the BeginReadMultiSample and then run the callback function when the read is done. at the end of the callback function a new BeginReadMultiSample is called. I see nowhere to tell the task to wait. Please enlighten me, for it seems that I might still be missing something here.

Thanks again,

Oded
0 Kudos
Message 7 of 9
(4,837 Views)
Hello Oded,

1. I notice similar behavior when I run the example program with the configuration you mention. However, I was able to make a few quick changes that seemed to help a lot. First, I modified the AnalogInCallback as follows:

Private Sub AnalogInCallback(ByVal ar As IAsyncResult)

        System.Threading.Thread.Sleep(10)

        Try
            If runningTask Is ar.AsyncState Then

                data = analogInReader.EndReadMultiSample(ar)

                'Plot your data here
                dataToDataTable(data, dataTable)

                analogInReader.BeginReadMultiSample(-1, analogCallback, myTask)

            End If

        Catch ex As DaqException
            MessageBox.Show(ex.Message)
            runningTask = Nothing
            myTask.Dispose()
            stopButton.Enabled = False
            startButton.Enabled = True
        End Try

    End Sub

You will notice that I added a sleep time by adding the System.Threading.Thread.Sleep() method. This gives the processor some time to handle other operations instead of being consumed by the data acquisition. However, to add this sleep time I had to change the parameters passed to the analogInReader.BeginReadMultiSample() method as well. Instead of using the user specified Samlpes/Channel text box, I set the SamplesPerChannel parameter to -1. This tells the BeginReadMultiSample() to read all available samples rather than the user specified block size. I had to change this parameter because in specifying a wait time I had given up the determinism of how many samples were acquired between calls. Now, instead of reading the user specified number of samples, I am reading all the samples that have been acquired while the program was sleeping. This change dropped my CPU usage from ~50% to ~30%.

To decrease my CPU usage a little further I commented out the line:

                dataToDataTable(data, dataTable)

This part of the program updates the table on the user interface. This operation is pretty processor intensive, and by removing this line of code I was able to decrease my CPU usage to ~10%. If you do not need to view the data as it is being acquired, I would recommend that you remove this part of the code.

2. You are correct, the WaitUntilDone() method is not used with asynchronous callbacks. The NI-DAQmx .NET Framework 2.0 Help (Start>>All Programs>>National Instruments>>NI-DAQ) states the following:

"WaitUntilDone waits for the task to finish acquiring or generating the number of samples per channel specified on the Timing class. WaitUntilDone does not wait for pending asynchronous operations to complete. Use the methods and properties on IAsyncResult to verify that asynchronous reads and writes are complete."


Matt Anderson

Hardware Services Marketing Manager
National Instruments
0 Kudos
Message 8 of 9
(4,814 Views)
Hi Matt,

Thanks for the detailed reply (for some reason I didn't get the email notification, so I only saw it now).
In the mean time I have found another way compatible with my application to overcome the CPU usage problem. I switched to using a large finite acquisition, with hardware reference triggerring for stop-timing, instead of continously acquiring and software stopping the acquisition. When working in this mode the CPU usage is a few percent no matter what sampling-rate I use.

Many thanks again for your assistance,
Oded Ben-David
0 Kudos
Message 9 of 9
(4,721 Views)