Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Problem acquiring more than 1000000 samples

I am using PXI 6120 modules and acquiring a finite block of samples.  When I set up a DAQmx task to acquire the data, all works fine as long as I acquire 1,000,000 samples or less per channel.  But when I acquire 1,000,001 samples, the DAQmx task throws no error yet the task never completes in a call to 'TaskDone.'
 
I am unable to find any references in NI documentation to a limit on number of samples.  Given that the 6120 has 32MB of memory for four channels, there shouldn't be any buffer problem, and especially, any buffer problem would seem to be a perfect power of 2, shch as 1048576 samples.
 
I am using DAQmx 8.3.0 within Visual Studio 2005.  The crucial call is mTask.Timing.ConfigureSampleClock("OnboardClock", 800000.0, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples ,  Nsamples), followed by mTask.IsDone().  The application works fine when Nsamples is 1,000,000 or less but that the task hangs and never completes when Nsamples is 1,000,0001 or more.
 
Can anyone provide an explanation and/or a fix?
 
 
David George
970 263 9714
 
0 Kudos
Message 1 of 17
(3,111 Views)

Hi David,

What you are describing is expected behaviour for this device.

The 6120 has a maximum sample rate of 800kS/s per channel (1MS/s when operated in warp mode). This is defined in the product specifications and stated on the product page.

 

Sarah

Applications Engineer | National Instruments | UK & Ireland
0 Kudos
Message 2 of 17
(3,058 Views)
Dave,

Thanks for posting to the NI Forums.  There should not be a problem when trying to acquire more that 1M samples with the PCI-6120.  However, I am surprised that you did not get an error for 1,000,001 samples.  When I use this number of samples with a simulated PCI-6120 I get error -200837: Samples per Channel must be an integer multiple of the transfer size for this device with the current Data Transfer Mechanism.   I used the default method of DMA.  The transfer size is 2 for the 6120 in DMA mode so the number of samples must be a multiple of 2.  When I changed the number of samples to 1,000,002 the program ran correctly.  Could you post the actual code that you are using?  I am going to track down a PCI-6120 this afternoon to see if I can reproduce the issue but I wanted to follow your code as closely as possible.  Also which version of the driver do you have installed?  Are you using C# or are you using VB?  I appreciate the additional details and hope to find you a solution and/or explaination soon.
Regards,

Neil S.
Applications Engineer
National Instruments
Message 3 of 17
(3,047 Views)

Apologies David,

I thought you were talking about the rate, clearly I need to ramp up after the Christmas lull!

Sarah

Applications Engineer | National Instruments | UK & Ireland
Message 4 of 17
(3,030 Views)

Neil and Sarah,  Thanks for the reply.  I have posted most if not all of the pertinent exceprts from my code below.  I have made comments in a different color to explain.  It seems to me that there is something in the DAQmx drivers that limits the number of samples to 1.00M.  Else it would seem the number of samples should be something close to a power of 2.

Neil, note that the issue of whether the number of samples is odd or even did not seem to affect anything.  I used 1000001 samples in my post because the 'break point' was between 1000000 and 1000001.  It finding that break point I used several other numbers of samples over 1000000, including (usually) even numbers.  They all failed.

As you can see, I am using VB withing VS2005.  As stated in my original post I am using DAQmx 8.3.0.  I have recently gone through the agony of downloading 500M for DAQmx 8.3.1 but have not yet gone through the agony of a few hours of uninstallation and reinstallation time.  My experience has been that every time I re-install DAQmx something breaks and it takes eons to fix but that was when I had to use traditional DAQ along side DAQmx because PXI 6120 modules were not supported in DAQmx and PXI 6123 modules were not supported in traditional DAQ.

A few notes:

My application requires producing a DO waveform that must be synchronized to AI sampling.
I use one 6120 module to produce the DO waveform and to be the master clock for AI sampling for all modules.
Producing the waveform and sampling the result requires setting up AI, DO, and Counter tasks.
The code below shows configuration and setup for all of AI, DO and Counters. 
I have two different DAQ systems. One is based on PXI 6120 modules and the other is based n PXI 6123 modules.
Therfore, you will see some code options for each of the two systems.

As a side issue, at first I tried using DAQmx with multiple AI modules assigned to a single task.
See  http://forums.ni.com/ni/board/message?board.id=232&message.id=3671
That proved to be much slower than using a single task per module and was never resolved so
I am using a single task per AI module.

'--------------------CONFIGURE DAQ--------------------
Call Configure()
See the entire subroutine below.
That subroutine does most of the set-up of the DAQ.
There are lines of code in that task that are commented out -- they are left there as notes.

'-----------------COMMIT DAQMX TASKS-----------------------------
'Commiting significantly speeds up AI task and can't hurt others
For k = 0 To mTEMData.DataPoint.AcqParams.nModules - 1
mAITask(k).Control(TaskAction.Commit)
Next
mDOTask.Control(TaskAction.Commit)
mCntrTask.Control(TaskAction.Commit)
'Start-------------------------
mDOTask.Start() 'Start DO, set for continuous output
DO is started first but is set to trigger from the first pulse from the counter
that also starts AI. So the Start command here only enables the actual start that
happens when the counter is started.

'---------------------Initial start-----------------
For k = 0 To mTEMData.DataPoint.AcqParams.nModules - 1
mAITask(k).Start()
Next
mCntrTask.Start()
mCPUTime.Time = Now

'--------------------------WAIT FOR ADCs-----------------------------
This is the section of code that hangs when the number of samples
exceeds 1M.   See the commented lines in subroutine Configure
to see the conditions in which this section of code hangs and in which it
does not.


My.Application.DoEvents()
Do
If mAITask(0).IsDone() Then
Exit Do
Else
System.Threading.Thread.Sleep(1)
End If
Loop

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Private Sub Configure()
Dim k&, s$, n&, iCh&
Dim x# 
Dim mChan As AIChannel

'Tasks----------------------
mDOTask = New Task
mCntrTask = New Task

'AI chans-------------------------
iCh = 0
s = ""
For k = 0 To mTEMData.DataPoint.AcqParams.nModules - 1
mAITask(k) = New Task
'AI channels, input, type, gain
For n = 0 To mTEMData.DataPoint.AcqParams.nChannelsPerModule - 1
s = mDeviceName(k) + "/ai" + CStr(n)
x = 10.0# / mTEMData.DataPoint.AcqParams.Gains(Me.LogicalChannel(iCh))      

Dim TermConfig As AITerminalConfiguration
#If DaqSystem = "NAVEOD" Or DaqSystem = "SERDP" Then

This statement is for 6120 modules
TermConfig = AITerminalConfiguration.Pseudodifferential
#ElseIf DaqSystem = "CRREL" Then

This statement is for 6123 modules
TermConfig = AITerminalConfiguration.Differential
#End If
mChan = mAITask(k).AIChannels.CreateVoltageChannel(s, "", TermConfig, -x, x, AIVoltageUnits.Volts)
These statements work only for 6120 modules
#If DaqSystem = "NAVEOD" Or DaqSystem = "SERDP" Then
mChan.LowpassEnable = True
mChan.LowpassCutoffFrequency = 50000
'mChan.LowpassEnable = False
#End If
iCh = iCh + 1
Next n
Next k

'AI timing
For k = 0 To mTEMData.DataPoint.AcqParams.nModules - 1
If k = 0 Then
s = "OnboardClock"

This statement was tried in an attempt to get around the difficulty
I am having with more than 1M samples. I was postulating that the
difficulty was with a counter overflow, counting at the rate of 50 MHz
or 20 ns.
's = "100KHzTimebase" 'Causes error in task

Else
s = "/dev1/ai/sampleclock"
End If
n = mTEMData.DataPoint.AcqParams.NPtsPerInBlock

These statements were used in debugging to narrow down the source of
the hangup. Note that the code runs fine for n=1000000 but that
it hangs (or stalls) for anything larger. It does not seem to
be dependent on whether n is even or odd.
'n = 1024 * 1024 / 2 + 1 'OK
'n = 1000000 'OK
'n = 1020000 'Stalls
'n = 1010000 'Stalls
'n = 1002000 'Stalls
'n = 1000000 + 16 'Stalls
'n = 1000000 + 8 'Stalls
'n = 1000000 + 1 'Stalls


For this statement, Delt is 1.25 us for 6120 modules.
mAITask(k).Timing.ConfigureSampleClock(s, 1.0# / mTEMData.DataPoint.AcqParams.Delt, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, n)

'AI reader
mAnalogInReader(k) = New AnalogUnscaledReader(mAITask(k).Stream)
Next k

As a side issue, I would like to know if there is a faster way to gain
access to analog samples that should already be in memory.
It seems as if the
reader is copying unscaled analog samples from its own buffer
to a new buffer.  It takes on the order of 10 ms to read samples from 7 PXI6120 modules using the
UnscaledAnalogInReader. It seems I should be able to gain almost instant access to a buffer
that is already in memory.

'DO-----------------------------
s = mDeviceName(0) & "/port0"
mDOTask.DOChannels.CreateChannel(s, "", ChannelLineGrouping.OneChannelForAllLines)

'DO timing

UpdatePeriod is on the order of 10's to 100's of milliseconds.
s = "Ctr0Out"
x = 1.0# / UpdatePeriod()
n = Me.NUpdates
mDOTask.Timing.ConfigureSampleClock(s, x, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, n)

'DO Write
Call Me.MakeWaveform()
Dim mDigitalChannelWriter As New DigitalSingleChannelWriter(mDOTask.Stream)
mDigitalChannelWriter.WriteMultiSamplePort(False, mDOBuf)

'Cntr0-------------------------
'Cntr0 channel
s = mDeviceName(0) & "/Ctr0"
Dim mCntrChannel As COChannel
x = 1.0# / UpdatePeriod()
'x = 0.2#
mCntrChannel = mCntrTask.COChannels.CreatePulseChannelFrequency(s, "", COPulseFrequencyUnits.Hertz, COPulseIdleState.High, 0.0#, x, 0.5)
'Cntr0 timing
n = NUpdates()
mCntrTask.Timing.ConfigureImplicit(SampleQuantityMode.FiniteSamples, NUpdates)

'AI trigger
s = "/dev1/Ctr0out"
mAITask(0).Triggers.StartTrigger.ConfigureDigitalEdgeTrigger(s, DigitalEdgeStartTriggerEdge.Rising)
End Sub
0 Kudos
Message 5 of 17
(3,022 Views)
Dave,

I have one question about your code.  I noticed that you set the number of samples for the AI task using the variable mTEMData.DataPoint.AcqParams.NPtsPerInBlock.  However, your counter that you use as a sample clock is also a finite task.  The number of pulses generated seems to be set by NUpdates.  If NUpdates < mTEMData.DataPoint.AcqParams.NPtsPerInBlock then the program will hang at the point at which you are running into the problem.  Actually I am confused about two points in your program:

1.
n = Me.NUpdates
mDOTask.Timing.ConfigureSampleClock(s, x, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, n)

What is Me.NUpdates set to?

2.
n = NUpdates()
mCntrTask.Timing.ConfigureImplicit(SampleQuantityMode.FiniteSamples, NUpdates)

Why do you set n to NUpdates() and then not use n?  What is the variable NUpdates set to and what does the NUpdates function return?

As far as the issue that you mentioned in the other forum, I would like to look into the claim that placing multiple S-Series devices in a single task slows acquisition.  I also want to explore whether this behavior is only apparent through the .NET API or if it also occurs in the other DAQmx APIs.  I will post my findings on the other forum.

It is not possible to read directly from the DAQmx buffer.  The API does not provide this functionality for several reasons.  First, in most cases our customers are interested in scaled data not unscaled data as you returning.  Data stored in the DAQmx buffer is the actual data read from the card not the scaled floating point values that most of our customers actually desire.  To make this conversion the data must be changed from a U16 or U32 to a floating point value which would require copying the buffer anyway.  Second, allowing direct access to the buffer would decrease the ease of use of our driver.  As the acquisition is proceeding the buffer continues to be modified.  If the data is read before the buffer is completely filled the data is invalid.  While for a few customers this direct access could be beneficial it would add additional complexity that could cause issues for many of our customers.  This becomes even more pronounced when performing a continuous acquisition where the buffer is continually filled.  Since the buffer is circular it would be difficult to know where the buffer is currently .  This could potentially cause race conditions and other nasty issues for many of our customers.  We have tried to make an extremely flexible API while retaining ease of use; however, some tradeoffs had to be made.  In this case we chose usability over efficiency.

Let me know if you have any additional questions.

Regards,

Neil S.
Applications Engineer
National Instruments
Message 6 of 17
(2,984 Views)

[NOTE TO WEB SITE MANAGER -- I just spent a good long while composing a message.  After clicking Post, I got a screen that said Authentication Failed.  My entire message was gone and seems to need to be re-generated.  It is quite frustrating.

 

Neil,

Thanks for the reply, this one will be be shorter.

My application goes like this.

The DO Waveform is driven by the Counter and the AI Sampling is triggered, but not timed by the Counter.  It goes like this,

The DO Task is started but nothing happens because there are no counter pulses.
The AI Tasks are started but nothing happens because it has not been triggered.
The counter task is started.  The first counter pulse triggers AI and all of the counter pulses provide timing for the DO waveform.

The AI Tasks and the Counter/DO tasks should be independent once the AI tasks are triggered.  The AI tasks and the Counter/DO tasks should proceed to completion independently, even if their total times are different.  The AI uses internal timing for AI sampling.

Typically a data block is 0.1 seconds.  In each data there are 80,000 AI samples per channel (i.e. NPtsPerInBlock = 80000).  Typically there are 36 counter pulses per in block, thus there are 36 DO states (actually 4 states repeated 9 times, such as in nine cycles of a repeated waveform).  Thus NUpdates = 36 and the counter frequency is 36 pulses per 0.1 sec or 360 Hz.

In my application, a data block can be 0.3333, 0.1, 0.3, 0.9, or 2.7 seconds.  The application works fine for all block times except 2.7 sec.  The failure at 2.7 sec is what led me to discover that the AI tasks failed when asked to acquire more than 1,000,000 samples.  Note that for 0.9 sec, there are 720,000 AI samples per block and at 2.7 sec, there are 2,160,000 samples per block. 

------------------

r/e your question about the code

n = NUpdates()
mCntrTask.Timing.ConfigureImplicit(SampleQuantityMode.FiniteSamples, NUpdates)

The statement n = NUpdates was added during debugging to make it easier to check the value of NUpdates.  As written it does not change the execution of performance of the code.

------------------

r/e DAQmx

I would like to see an optional DAQmx call that allows the user to provide the memory buffer to DAQmx.  There are already calls that allow the user to override the size of the buffer (DAQBuffer.InputBufferSize()). It would seem easy to add a Method such as DAQBuffer.SupplyInputBuffer( byRef theUsersBuffer() as short).  Perhaps your DAQmx software people would consider adding such a call.  It would not complicate any user's life unless they chose to use that call.  When choosing that call, the user becomes responsible as you say to determine whether data in the buffer are valid.

Regards,

Dave George

Message 7 of 17
(2,976 Views)
Dave,

Thanks for your patience while I troubleshoot the issue.  I was able to track down 2 PXI-6120s and have run a few tests.  Your application is quite complicated so I wanted to reduce the complexity to see if the issue is still reproducible.  I created a single task in MAX with all four channels from two 6120s.  I then tried 3 different configurations.  First, I tested running both cards in continuous mode at max rate (800k) and was able to do this without issue.  Next I tried running the two cards at 800k in finite mode with the number of samples set to a low number 5000 or so.  This was also successful.  I performed the same test but increased the number of samples to 1,000,001.  This too was successful.  I also tried to acquire 2,000,000 and was also successful.  I then tried to run the same task but triggered the task on an external pin.  This was also successful.  I was not able to reproduce either error.  I was using a newer system with DAQmx 8.3.1, it is possible that this is a system dependent issue.  Could I have you try a few things on your system?  First, could you follow the same procedure that I did in MAX to see if this also fails or if it works properly?  Second, are you able to read any data despite the task never reports that it has completed?  If you are able to get data have you tried the WaitUntilTaskDone method?  The isTaskDone method should work but I would like to narrow down where the issue is arising.  Are you able to reproduce the same behavior when you remove the counter and digital tasks from your application?  You mentioned in the other thread that you had two systems: one newer one with 16 channels and an older one with 28 channels.  Are you using one of these systems for this application or are you using a different system altogether?  How many channels are you acquiring from in your application?  How many 6120s do you have in your chassis?

I appreciate the details.  I am sorry you lost your first post.  There is some timeout on the forum, and there is also a character limit.  Hopefully in the future we will be able to fix some of those issues with the forum.  I started using the practice of copying my post before posting so if it is lost I still have the post.

I look forward to hearing back from you.

Regards,

Neil S.
Applications Engineer
National Instruments
0 Kudos
Message 8 of 17
(2,952 Views)

Neil,

I have made several more tests in accordance with your last post.  Here I will speak of two systems.  System 1 is a system with Seven 6120 modules.  System 2 is a system with Two 6123 modules. 

I installed DAQmx 8.3.1 in System 1.  It made no difference.
I tested any difference between Task.IsDone() and Task.WaitUntilDone(TimeOut).  There was not difference.
As I am writing this message, it has occured to me that I could try using AnalogUnscaledReader(-1) and setting ReadAllAvailableSamples to false.  I just made a brief test and it looked to function OK.  It's too late tonight to try a full fledged test but tomorrow I will.

Here is some more information for you and a short program you can use that should reproduce the error.  It has now turned up for me in two different systems.  That fact that it is exactly 1,000,000 samples just sounds to me like a software test that is failing -- one of your software gurus may know exactly where it is.


System 1:
 a.  In MAX and In VB.net:  Cannot set up multiple modules in one task.  Causes Error 200072 Duplicate channels inthe list of physical channels are not supported by this device. 
 b.  In MAX:  One module:  Can collect 2,000,000 samples per channel (4 channels)
 c.  In VB.Net, fails when 1,000,001 samples or more per channel, for either one module or two.

System 2: 
 a.  In MAX:  Can set up multiple modules in one task. 
 b.  In MAX:  Can collect 2,000,000 samples per channel (16 channels)
 c.  In VB.Net, fails when 1,000,001 samples or more per channel.  Did not test just one module.


Below is a short program that fails in System 1.  It hasn't been tested in system 2.

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim mChan As AIChannel
        Dim mAITask(6) As Task
        Dim mAnalogInReader(6) As AnalogUnscaledReader
        Dim k, n As Integer, s As String, x As Double
        Dim nModules As Integer = 2

        'Reset all DAQ modules
        Dim mDevice(nModules - 1) As DAQmx.Device
        Dim mdaqsystem As DaqSystem
        mDaqSystem = DaqSystem.Local
        For k = 0 To nModules - 1
            mDevice(k) = mdaqsystem.LoadDevice("dev" & CStr(k + 1))
            mDevice(k).Reset()
        Next k

        'Set up tasks, one per module
        For k = 0 To nModules - 1
            mAITask(k) = New Task
            For n = 0 To 3
                s = "/dev" & CStr(k + 1) & "/ai" & CStr(n)
                x = 10.0#
                Dim TermConfig As AITerminalConfiguration
                TermConfig = AITerminalConfiguration.Pseudodifferential
                mChan = mAITask(k).AIChannels.CreateVoltageChannel(s, "", TermConfig, -x, x, AIVoltageUnits.Volts)
                mChan.LowpassEnable = True
                mChan.LowpassCutoffFrequency = 50000
            Next n
        Next k

        'AI Timing
        For k = 0 To nModules - 1
            If k = 0 Then
                s = "OnboardClock"
            Else
                s = "/dev1/ai/sampleclock"
            End If
            'n = 1000    'Test
            n = 1000000 'OK
            'n = 1020000 'Stalls
            'n = 1010000 'Stalls
            'n = 1002000 'Stalls
            'n = 1000000 + 16    'Stalls
            'n = 1000000 + 8 'Stalls
            'n = 1000000 + 1 'Stalls
            n = 2000000     'Stalls
            mAITask(k).Timing.ConfigureSampleClock(s, 800000.0, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, n)
            'AI reader
            mAnalogInReader(k) = New AnalogUnscaledReader(mAITask(k).Stream)
        Next k

        'AI Commit and Start  Start Task(0) last because it controls timing for other tasks
        For k = nModules - 1 To 0 Step -1
            mAITask(k).Control(TaskAction.Verify)
            mAITask(k).Control(TaskAction.Commit)
            mAITask(k).Start()
        Next

        'Wait for AI done
        Try
            mAITask(0).WaitUntilDone(10000)
            MsgBox("ADC's read")
        Catch ex As Exception
            MsgBox("AI read failed")
        End Try

        'Read AI data
        Dim mData(,) As Short, mData2(,) As Short
        mData = mAnalogInReader(0).ReadInt16(n)
        mData2 = mAnalogInReader(1).ReadInt16(n)

    End Sub
End Class

0 Kudos
Message 9 of 17
(2,939 Views)

Neil,

I forgot to mention in my post that:

When Task.IsTaskDone() or Task.WaitUntilDone(timeout) is called and doesn't return (i.e. the root of the problem)

YES:  the data is present in the buffer and when AIReader is called, the data appears to be correct.  I haven't been able to check that waveforms are synchronized but I suspect they are.

Therefore, it is beginning to appear that the problem is within IsTaskDone or WaitUntilDone.  It just seems that some programmer, some time, just believed that no one would ever want to take more than 1,000,000 samples in one acquisition block, so he wouldn't check beyond that.  But so much for a wild-a__ guess.

 

Dave

 

0 Kudos
Message 10 of 17
(2,921 Views)