mabuchilab / Instrumental

Python-based instrumentation library from the Mabuchi Lab.
http://instrumental-lib.readthedocs.org/
GNU General Public License v3.0
120 stars 80 forks source link

NIDAQ device memory underflows before max sample rate #4

Closed sashagaz closed 9 years ago

sashagaz commented 9 years ago

Hi, First, thank you for sharing your code. I have a question regarding the maximum output frequency I can get from my NiDAQ (6361). I am running your example to generate a sine wave: data = sin( 2_pi * linspace(0, 1, 101) )_5_u.V + 5_u.V daq.ao0.write(data, duration='1s', freq='100Hz') The maximum output frequency that I can get is 7.5kHz from an analog output. Above it, I am getting an error in the DAQmxWaitUntilTaskDone function which means that there is not enough time for the DAC conversion. Although there is an internal 10Mhz clock in the device.

I was wondering if you have encountered this problem, and can give me a hint on how to fix it.

Thanks again!

Sasha

natezb commented 9 years ago

Hi Sasha, thanks for your report!

Unfortunately I'm not around the lab right now, so I won't be able to check this myself with our DAQ for a few days.

But first, what exactly is the code that you're running? Since this is outputting a sampled sine function, you won't be able to generate a sine that runs at your full clock frequency, only at the max analog output frequency divided by the number of samples per period.

Also, could you provide the exact error message you are getting?

sashagaz commented 9 years ago

Hi Nate,

Thank you for the prompt answer!

Here is the code I am running:

from instrumental.drivers.daq.ni import NIDAQ, list_instruments
from instrumental import u
from numpy import pi, sin, linspace, sinc
from scipy import signal

daq = NIDAQ('Dev2')
data1 =signal.sawtooth( 2*pi * linspace(0, 1, 101) )*5*u.V + 5*u.V
data2 =signal.square( 2*pi * linspace(0, 1, 101) )*5*u.V + 5*u.V
data3 =sin( 2*pi * linspace(0, 1, 101) )*5*u.V + 5*u.V
while(1):
print 'Squareawtooth'
daq.ao0.write(data1, duration='1s', freq='800000Hz')
print 'Square'
daq.ao0.write(data2, duration='1s', freq='750000Hz')
print 'Sine'
daq.ao0.write(data3, duration='1s', freq='750000Hz')

And here is the error message:

Traceback (most recent call last):
  File "waveform.py", line 12, in <module>
    daq.ao0.write(data1, duration='1s', freq='800000Hz')
  File
"C:\Python27\lib\site-packages\instrumental-0.1.0-py2.7.egg\instrumental\
drivers\daq\ni.py", line 563, in write
    t.t.WaitUntilTaskDone(-1)
  File "<string>", line 3, in WaitUntilTaskDone
  File "<string>", line 2, in function
  File "build\bdist.win32\egg\PyDAQmx\DAQmxFunctions.py", line 28, in
mafunction

PyDAQmx.DAQmxFunctions.DAQError: Onboard device memory underflow. Because
of sys
tem and/or bus-bandwidth limitations, the driver could not write data to
the dev
ice fast enough to keep up with the device output rate.

Reduce your sample rate. If your data transfer method is interrupts, try
using D
MA or USB Bulk. You can also reduce the number of programs your computer is
exec
uting concurrently.
Task Name: _unnamedTask<0>

Status Code: -200621
 in function DAQmxWaitUntilTaskDone

With 100 samples resolution the following function: daq.ao0.write(data1, duration='1s', freq='800000Hz') corresponds to 8kHz sine wave. However, when I am decreasing the number of samples in order to increase frequency, I am still getting the same error, and it seems that the maximum frequency that I can get is 7.5Khz.

Please let me know if I am missing something. Thanks. Sasha

On Fri, Feb 20, 2015 at 3:07 PM, Nate Bogdanowicz notifications@github.com wrote:

Hi Sasha, thanks for your report!

Unfortunately I'm not around the lab right now, so I won't be able to check this myself with our DAQ for a few days.

But first, what exactly is the code that you're running? Since this is outputting a sampled sine function, you won't be able to generate a sine that runs at your full clock frequency, only at the max analog output frequency divided by the number of samples per period.

Also, could you provide the exact error message you are getting?

— Reply to this email directly or view it on GitHub https://github.com/mabuchilab/Instrumental/issues/4#issuecomment-75336194 .

natezb commented 9 years ago

I just pushed some changes to NIDAQ, see if they fix your problem. Also note that I made some other changes to the interface of the AnalogOutput.write() method, so your code will require some minor modifications (e.g. start using 100 samples instead of 101, and use endpoint=False in linspace). See http://instrumental-lib.readthedocs.org/en/latest/ni-daqs.html for updated example code and method documentation. As for the content of the fix...

I read up on the error and it sounds like this is what's happening (keep in mind I'm not a DAQmx expert):

  1. You're passing an array with 101 samples
  2. duration is 1s and freq is many kHz, so the DAQ will repeat the waveform many times
  3. Instead of loading the data into the on-device FIFO and just looping over that data until the output ends, it seems like DAQmx is trying to stream the data repeatedly from your PC memory, even though the data never changes. So, if the sample frequency is too high the data bus can't stream fast enough from your PC to the device.
  4. You should be able to change this behavior by enabling what DAQmx calls "regeneration" (in C this uses functions like SetAOUseOnlyOnBrdMem to force use of onboard-only memory)

Let me know if the usage of onboard-only memory solved it--it fixed the issue for me.

natezb commented 9 years ago

I'm closing this as solved. Feel free to reopen if you have issues.