Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

problems with asynchronous acquisition and traditional NI-DAQ

EDIT: apologies for the double post. there's no new content here...
 
hi,
 
I am having some problems collecting asynchronous data with my NI-DAQCard 6024E with Traditional NI-DAQ v 7.4.1. I'm using Visual Studio C++ with Windows XP. I would like to collect data from two analog inputs every 10 msec during which time I'll be running a virtual driving simulation. It would be nice to collect the data into a buffer while the simulation is crunching its numbers and doing its thing. Then when it needs to read the signals, it can look at the buffer, take the last few samples for each channel, average them together (because of noise in my source), and use the results as the readings. Unfortunately, I am having trouble using DAQ_Monitor() and DAQ_Check().
 
I started out using DAQ_Monitor() because it was claimed that it can read a block of data from the buffer and that the most recently acquired data may be returned. But, it appears that the block size is 1024 points. That is, it isn't until I have acquired 1024 samples that I can get a new reading from DAQ_Monitor(). I /could/ be fine with this if my sample rate is 200 kHz, but in that case my sample may be as much as 5 msec old and, more importantly, it is not certain when the sample occurred within the last 5 msec of the function call.
 
I then tried DAQ_Check() because this at least outputs the number of samples acquired at the time the function is called. I could then use that as the pointer into the input buffer to get my most recent samples. But, I run into the same problem as with DAQ_Monitor(), where the index pointer doesn't update itself until 1024 samples have been acquired.
 
The problem does not appear to be dependent on the buffer size. Even if the buffer is small (<1000 pts or <50 pts), the pointers are not updated until 1024 samples have been acquired. I almost don't mind a small buffer size because I don't need the samples during the 1 to 8 msec that the simulation is running. But in this case, I run into the overWriteError when double buffer mode is enabled. If I ignore the error, I still need to wait for the next half buffer to be filled (which seems to be another bug in the system), which sort of negates using asynchronous acquisition in the first place.
 
I have attached the code I've been using as a testbed. It is based NI's example code with additional calls suggested by the Traditional NI-DAQ User Manual. The results demonstrate how the index pointer and reading are updated only after 1024 samples are acquired.
 
If you have any suggestions to fix the problem, they are greatly appreciated. Let me know if I can provide more information, too. Thank you for your consideration.
 
-kb

Message Edited by -kb on 08-10-2006 11:47 AM

Download All
0 Kudos
Message 1 of 16
(6,644 Views)

Hello -kb,

I see that you are using an NI-DAQCard 6024E with Traditional DAQ 7.4.1 in Visual Studio C++.  If you are just starting your application (from your post seems to be the case), I would definitely recommend using the NI-DAQmx driver.  The driver you are currently using only supports our older hardware, while the NI-DAQmx driver supports all new hardware and most of the old hardware. 

This means you could take the code you write for your DAQCard 6024E and use it with a USB M series or a PCI-6251 without any changes.  Beyond the hardware compatibility it is far easier to program.  From your explanation you simple want to perform continuous acquisition and read the data every 10ms.  This is really easy to do in DAQmx.  You can find all DAQmx shipping examples here once DAQmx is installed:

C:\Program Files\National Instruments\NI-DAQ\Examples\DAQmx ANSI C

The continuous acquisition examples use an event to trigger your data acquisition.  This allows the DAQmx driver to create a thread and only notify your application when a specific number of samples have been acquired.  You do not have to use the callback functions if you do not want to.  You could just as easily modify the finite sample examples and perform your data acquisition in a loop.

If you use a callback function, and you specify a sampling rate of 1000Hz, you would set the callback function to occur every 10 samples.  Inside this callback function you could then read all the available data.  Alternatively, you could in a loop perform the data read (if you do not register a callback function) and specify to read 10 samples.

I would highly recommend moving to DAQmx if you are just starting your application.  If you do not have it installed, you can find your device and the newest supported  driver here.

Regards,

Jesse O.
Applications Engineering
National Instruments

Jesse O. | National Instruments R&D
0 Kudos
Message 2 of 16
(6,613 Views)

Jesse,

Thank you very much for your response. Back in February, I think it was, when I was investigating using NI-DAQmx or Traditional NI-DAQ, I could not find any support documentation for using NI-DAQmx with Visual Studio C++. It also appeared that NI-DAQmx was compatible only with versions 7.0 and later of Measurement Studio, while my lab has verion 6.0. In any case, I am using VS C++ and you seem to indicate that this is compatible with NI-DAQmx. I imagine I would do the same thing in VS as with the Traditional NI-DAQ, where I include the nidaq and nidaqex libraries in the project and be sure to point to the appropriate include and lib folders? Also, if I install NI-DAQmx, will I still be able to use applications that use Traditional NI-DAQ? Thanks again.

-kb

0 Kudos
Message 3 of 16
(6,611 Views)

Hello -kb,

You can use DAQmx in Visual C++.  When you install DAQmx, there will be an option to include the DAQmx C Support.  When you install this you will get the C API support, along with shipping examples (mentioned in my last post), and a bunch of documentation. 

The DAQmx C Reference Help is located under Start >> Programs >> National Instruments >> NI-DAQmx >> NI-DAQ C Reference Help. 

NI-DAQmx was first release with Traditional DAQ in version 7.0.  Later Traditional DAQ and DAQmx where split into two separate drivers.  You can have both DAQmx 8.3 and Traditional DAQ 7.4.1 installed on the same machine at once.  This allows you to use either DAQmx or Traditional DAQ on your different cards.  You can even use DAQmx or Traditional DAQ on the same card (just not at the same time).  For more information on programming in different text based languages please see an online document found here.

Now you also mentioned Measurement Studio compatibility of DAQmx.  It is true that Measurement Studio 7.0+ take advantage of DAQmx in Visual Studio .NET, however you can still have applications with Measurement Studio 6 and DAQmx 8.3 in Visual Studio C++ 6.  Measurement Studio 7.0 + has the ability to use the DAQ Assistant to allow you to point and click program.  From the wizard that appears you simply make you selections and it codes that section in your program.  In Measurement Studio 6, this option is not available but you can still definitely use DAQmx in your application for its other functionality (i.e. graph and mathematic operations).

Regards,

Jesse O.
Applications Engineering
National Instruments

Jesse O. | National Instruments R&D
0 Kudos
Message 4 of 16
(6,608 Views)

Hi,

I installed NI-DAQmx 8.3 and got some test programs running. Things still aren't working out so well.

My loop isn't as stable as I'd like it to be, so having an event occur every nth time as you suggested won't provide the timing that I need. Unless... let's say I have the sample rate set to 50 kS/s and every msec, or every time 50 samples are acquired, it writes the data to an input buffer, overwriting what was previously there. Then, when I use the input buffer, that data will be at most 1 msec old. I assume then I'd need something to check that the event is not writing to the buffer when my routine is reading from it, correct?

In the meantime though, I have been attempting to use the RelativeTo and Offset properties. Here, I set RelativeTo to DAQmx_Val_MostRecentSamp and Offset to -n samples to read. My understanding of the help files says that whenever I use the read function to read samples from the (continuous) task, NI-DAQmx will determine the index where data is being read into the buffer (End of Data) at that specific time and subtract n samples. That range of End of Data minus n to End of Data is what is returned. However, it does not appear to be working that way. Instead, the data that seems to be returned are Current Read Mark minus n to Current Read Mark, where Current Read Mark is the End of Data index from the previous read. Am I interpreting the help files incorrectly? Do you have any suggestions for determining the End of Data index?

Thanks again.

-kb

0 Kudos
Message 5 of 16
(6,567 Views)

Hello -kb,

First, you do not have to worry about the DAQmx buffer overwriting data while you are reading it.  DAQmx uses a circular buffer, and you should be reading from one end, when it fills in the other.  When you perform a DAQmx read, it will give you the oldest samples.   If you look in the shipping examples, you will see that the buffer size is not explicitly set.  Although you can set the buffer size, DAQmx computes what it thinks is appropriate based on your sampling rate and number of samples to read.  If your application cannot keep up with the rate the DAQ card is filling the buffer it will generate an overflow error and report that it has over written samples.

Therefore, if your computer is fast enough, you should be able to create a loop with a DAQmx read inside it.  I have modified an example program and attached the c file below.  It has the DAQ card read data in at 10KHz and has a loop acquire 100 samples as fast as it can.  It displays to the screen when it has read the 100 samples, and how many samples are still in the buffer. 

Therefore, if you first start your acquisition and you read in 100 samples and there are 2 remaining, your loop took 102/10000 = 0.0102 seconds.  The next time you read from the buffer the two samples that were remaining before are read in.

Please let me know if this helps you out.  If you find that you are reading in 100 samples and a lot are remaining it is because your software/PC cannot keep up.

Regards,

Jesse O.
Applications Engineering
National Instruments

Jesse O. | National Instruments R&D
0 Kudos
Message 6 of 16
(6,550 Views)
hi,
 
You said that the DAQcard will generate an overflow error if the application cannot keep up with the rate at which the buffer is being filled. But isn't this what SetReadOverWrite(taskHandle, DAQmx_Val_OverwriteUnreadSamps) is for? In this case it should be okay to overwrite data before it is read.
 
Also, I'm not sure if I'm understanding the output of your program on my machine correctly. I have modified your code slightly to ensure that lines are not overwritten in the output screen, and I added a system clock. The samples acquired is as expected, with 100 each read. But the samplesInBuffer changes.
 
Read     Samples Left     Time since StartTask (msec)*
100        412                    104
100        312                    104
100        212                    105
100        112                    105
100        12                      105
100        424                    155
100        324                    155
...           ...                       ...
 
It seems as though access to the input buffer is not granted until ~1000 samples have been acquired (10 S/msec * 104 msec). Afterwards, it seems like data is provided in blocks of 512 samples. This would explain why there are 412 left after the first read of 100, and the next time new data is available occurs after a 50 msec delay (155-105 msec * 10 S/msec = ~512).
 
Well, I guess blocks of 512 is better than the 1024 with the Traditional NI-DAQ. But, is this a "feature" of the DAQcards or drivers? Or do you think the blocks of data is a result of settings on my machine? Cheers.
 
-kb
 
*I'm using Windows' multimedia timer with the granularity set to 1 msec, so the accuracy of the timing should be +/-1 msec
0 Kudos
Message 7 of 16
(6,542 Views)
Hello -kb,

As far as I know DAQmx does not require 512 samples of data to be transferred to read it out of the buffer.  I have attached the output of the program I posted below:

Acquired 100, Remaining in Buffer2 6.
Acquired 100, Remaining in Buffer2 4.
Acquired 100, Remaining in Buffer2 0.
Acquired 100, Remaining in Buffer2 18.
Acquired 100, Remaining in Buffer2 0.
End of program, press Enter key to quit

Because I specify a sampling rate of 10KHz, each of these loop iterations took approximately 100ms.  If you notice that I was able to read in the first 100 samples pretty much as soon as they were available.  How fast you can read the data out of the buffer will completely depend on the performance of your system.

Also, to be a little clearer on how DAQmx overwrites samples.  DAQmx will overwrite samples if you do not read them out of the buffer fast enough.  As soon as you read data out of the PC buffer, that memory location is available again for use.  If you do read fast enough the buffer runs out of space and it overwrites data.  You do not have to worry about this until you get overflow errors.  If you get overflow errors you know data has been overwritten.  If you do not get any errors you are keeping up with the acquisition and you are not losing any data.

Regards,

Jesse O.
Applications Engineering
National Instruments

Jesse O. | National Instruments R&D
0 Kudos
Message 8 of 16
(6,538 Views)

hi,

This is very weird. What system are you running on? What I showed before was the read results when i was between 0 and 600. Here is my output for i>9500 to be consistent with your output:

Acquired 100, Remaining in Buffer2 400     1051
Acquired 100, Remaining in Buffer2 300     1053
Acquired 100, Remaining in Buffer2 200     1055
Acquired 100, Remaining in Buffer2 100     1056
Acquired 100, Remaining in Buffer2 0         1059

where the last number is the time in msec since the task started. What does your data look like for i<600?

-kb

0 Kudos
Message 9 of 16
(6,529 Views)

Hello -kb,

I believe the difference is because you used a DAQCard (pcmcia), and I was using a PCI device.  I have modified the original code I posted so that it changes the data transfer request condition.  Now you should see numbers similar to mine.  Please see the attached c file below.

Regards,

Jesse O.
Applications Engineering
National Instruments

Jesse O. | National Instruments R&D
0 Kudos
Message 10 of 16
(6,516 Views)