Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

PCIe 6537 maximum sample clock ANSI C

Solved!
Go to solution

I am programming a PCIe 6537 card with ANSI C. The application uses continuous sampling, with a callback to analyse the samples.

 

The maximum sample rate should be 50,000,000 samples/sec. The internal sample clock is supposed to be 200MHz/N where N>=4.

 

I can get it to work at 40,000,000 samples/sec (N=5), but if I set the sample clock to 50,000,000 samples/sec (N=4) the callback never gets called.

 

I set up the task with the following calls.

 

DAQmxCreateTask(TaskName.c_str(), &m_TaskHandle);

 

I calculate ThisLine = "Dev1/portX/lineY for X=0..3 and Y=0..7, and for each I call

DAQmxCreateDIChan(m_TaskHandle, ThisLine.c_str(), "", DAQmx_Val_ChanPerLine);

 

Then I set up the sample clock.  This works:

DAQmxCfgSampClkTiming(m_TaskHandle,  NULL,
                           40000000, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 16000000
                                       );

This doesn't:

DAQmxCfgSampClkTiming(m_TaskHandle,  NULL,
                           50000000, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 16000000
                                       );

I register the callback so:

DAQmxRegisterEveryNSamplesEvent(
                           m_TaskHandle,
                           DAQmx_Val_Acquired_Into_Buffer,
                           4000000,
                           0,
                           NI6537_EveryNSamplesCallback,
                           this
                                                        ) ;

 

 

The callback increments an integer which is output when I terminate the program by hitting Esc. 

Is there some trick needed to get the sample clock to work at the higher rate? Or is it limited by the PC in some way, so that the callback just won't happen at 50Ms/s?

 

Frank

 

 

0 Kudos
Message 1 of 14
(4,755 Views)

Hi Frank,

 

I've noticed that I too have trouble getting 50MHz acquisition to work if I use the "one channel per line" mode in DAQmx (through LabVIEW).  Can you try setting up your task to use "one channel for all lines" mode?  This constant is called "DAQmx_Val_ChanForAllLines".

 

You can use "dev1/line0:31" to get all 32 lines in a single string.

 

Also, I think these functions return error values.  Are you getting any return codes from these functions?

 

Thanks,

 

Keith Shapiro

National Instruments R&D

0 Kudos
Message 2 of 14
(4,745 Views)

Keith.Shapiro wrote:

Hi Frank,

 

I've noticed that I too have trouble getting 50MHz acquisition to work if I use the "one channel per line" mode in DAQmx (through LabVIEW).  Can you try setting up your task to use "one channel for all lines" mode?  This constant is called "DAQmx_Val_ChanForAllLines".



 Thanks for your reply. I'll try that mode and post back. Will have to see what format the data come to me in the callback... 

 


You can use "dev1/line0:31" to get all 32 lines in a single string.

That's good to know. I thought I could specify at most 8 lines at a time, for each of port 0..3. It didn't seem to make any difference to the returned samples, I still get 32 sample lines in 32 bits, so I thought DAQmx must be combining the lines internally.


Also, I think these functions return error values.  Are you getting any return codes from these functions?

They do return error values, and I do check them. But my post was big enough without that code, so I left it out for clarity.

 

I abort if an error happens, and I also dumped the return value after DAQmxCfgSampClkTiming() and DAQmxRegisterEveryNSamplesEvent() to the screen; it was 0.

 

Frank

 

0 Kudos
Message 3 of 14
(4,743 Views)

Unfortunately, when I changed to

DAQmxCreateDIChan(m_TaskHandle,
                  "Dev1/line0:31",
                  "",
                  DAQmx_Val_ChanForAllLines
                 )

I still got no callbacks with the sample rate set to 50000000, but got callbacks with  40000000.

 

Frank

 

0 Kudos
Message 4 of 14
(4,738 Views)

Frank,

 

It is very likely that the boar's FIFO is overflowing when you run at 50 MHz. You are not getting any error back since the driver does not get a chance to report the hardware error. When the task starts, the device starts acquiring data and before it gets to the N samples to fire-up a callback, the hardware overflows and stops taking in data. Since the device never acquired N points, it never fires the callbacks and you never get notified of the error. 

 

My advice would be to start the task, which will eventualy call the callback in it's own thread, and then start a loop that calls DAQmxIsTaskDone(taskHandle, &Done). This second loop will be constantly checking the state of the hardware regardless of the callbacks. I suspect that by doing this you'll get the appropriate device overflow error. 

 

Let me know how this goes,

 

Regards,

 

Juan Carlos

NI

0 Kudos
Message 5 of 14
(4,734 Views)
Alternatively, you can register for the Done event (similar to how you are registering for the Every N Event).  Then in that callback, make sure that you call DAQmxStopTask, which will then return an appropriate error to you.
Thanks,

Andy McRorie
NI R&D
0 Kudos
Message 6 of 14
(4,712 Views)

JuanCarlos wrote: 
It is very likely that the boar's FIFO is overflowing when you run at 50 MHz. You are not getting any error back since the driver does not get a chance to report the hardware error. When the task starts, the device starts acquiring data and before it gets to the N samples to fire-up a callback, the hardware overflows and stops taking in data. Since the device never acquired N points, it never fires the callbacks and you never get notified of the error. 

 

My advice would be to start the task, which will eventualy call the callback in it's own thread, and then start a loop that calls DAQmxIsTaskDone(taskHandle, &Done). This second loop will be constantly checking the state of the hardware regardless of the callbacks. I suspect that by doing this you'll get the appropriate device overflow error. 


 

Ok, I've done that. Now my program says:

 

Measurements: Onboard device memory overflow. Because of system and/or bus-bandwidth limitations, the driver could not read data from the device fast enough to keep up with the device throughput.

Reduce the sample rate, or reduce the number of programs your computer is executing concurrently.
Task Name: Dev1DIOTask

Status Code: -200361
Callback called 0 times

 

which looks like what you were expecting. I tried this when setting the callback to every 5,000,000 samples (0.1 seconds per callback) and 500,000 samples.

 

But I'm puzzled now. The datasheet for the card said it could sample at 50MHz, and transfer 200MB/s to the PC's memory.  Once it's in the PC's memory, I hoped it could be processed faster than that; in my application I want to time the edges of some signals very accurately but there should only be a few dozen such edges per second so most samples end up discarded. According to the "determine the buffer size" linked from the documentation for DAQmxCfgSampClkTiming(), there should be a 1MS buffer, so when I set the callback to happen every 500,000 samples I expected it to be called at least once.

 

Can the card not transfer data at this rate? Or do I need to do something to the PC to get it to work?

 

 

I should mention a couple of things about my setup, in case they are important.

  • I am using the ANSI C API. The program is written in C++, compiled with Visual C++ 2008 Express edition.
  • The PC has one PCI Express slot, which contains the 6537 card. The other slots in the PC are PCI.
  • There are no programs open on the PC other than the command shell in which my application is run.
  • There are 2 CPU cores, 2.19GHz.
  • When I sample at 40,000,000 samples per second, one CPU goes to 90..99% and the other goes between 30% and 40%. The callback looks for edges in the samples it receives, and records them (carefully, because it's in a different thread) in a circular buffer which is read by the main program. Since my main program continually polls this buffer, I suspect that the CPU that is fully occupied is the one running my main program, and the DAQmx thread is running on the CPU that is only 40% busy.

Is there anything I can do to speed up the driver?

Frank
0 Kudos
Message 7 of 14
(4,699 Views)

AndrewMc wrote:
Alternatively, you can register for the Done event (similar to how you are registering for the Every N Event).  Then in that callback, make sure that you call DAQmxStopTask, which will then return an appropriate error to you.

It looks easier to call DAQmxIsTaskDone(). Is there any significant difference between the two methods?

0 Kudos
Message 8 of 14
(4,698 Views)
It's just a matter of preference.  I only mentioned it because you were using EveryNEvent callbacks as opposed to reading in a loop.
Thanks,

Andy McRorie
NI R&D
0 Kudos
Message 9 of 14
(4,684 Views)
Solution
Accepted by fpeelo

Frank,

 

You might want to check and make sure your PC's BIOS has been updated to the latest revision.  This can have an effect on the maximum transfer speed over PCI Express.

 

There are certain instances (depending on the maximum packet size allowed by your computer's chipset) where a PCIe-6537 cannot acquire 32 channels of data at 50MHz.  This is strictly a limitation of the PC.  If your BIOS is up to date and it still doesn't work, can you try your code with the PCIe-6537 on a more recent computer?

 

Keith Shapiro

National Instruments R&D 

0 Kudos
Message 10 of 14
(4,675 Views)