Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

M-series analog input performance degradation

Hi Aaron.

Have you tried with this instead ?

aiSampleStart(board,
    convertDelayDivisor+convertPeriodDivisor*numInputs,
    3,
    tMSeries::tAI_START_STOP_Select::kAI_START_SelectSI_TC,
    tMSeries::tAI_START_STOP_Select::kAI_START_PolarityRising_Edge);

where convertDelayDivisor is the convert period delay divisor passed to aiConvert() ?

When I look at the available timing diagrams for the M Series, it looks like without this adjustment, aiSampleClock could be generated before the current sample is finished. For example with a convertPeriodDivisor of 80, convertDelayDivisor of 3, for 2 inputs, aiSampleClock would occur every 8µS but a complete scan of the two inputs would take 8.15µS [ (convertDelayDivisor + convertPeriodDivisor*numInputs) * 1/20000000)]. This is assuming your using the internal timebase of 20MHz. But I'd like to hear from NI about this as I am probably missing something.

There is something kind of strange about your results. I can't figure out why it is actually working when you slow down the acquisition rate since it should actually take longer to generate the 48 samples (48 samples @ 250kHz:192µS vs 48 samples @ 245kHz:195.9µS). Maybe this is some timing issues related to aiSampleClock being masked when convertDelayDivisor is not taken into account?

Too bad I don't have acces to a M Series board at the moment as I would have done some testing myself.

Danny

 

 

Message 11 of 15
(5,713 Views)
I'm working on this right now.  So far, I've found if I use 2 for the AI Convert Clock timebase, I get the same results.  Using this I get,

4 inputs, 250 kSa/sec, 12 Sa/input/main loop, convert period divisor = 80, samples measured per sec = 37 (WRONG because 12 Sa*4 inputs = 48 samples per main loop)
5 inputs, 250 kSa/sec, 10 Sa/input/main loop, convert period divisor = 80, samples measured per sec = 41 (WRONG because 10 Sa*5 inputs = 50 samples per main loop)

The M-series boards definitely masks any
aiSampleClock signals if a acquisition is in progress, and this appears to be what is happening.  Because it is a timing issue, certain situations will probably work while others will not, and it may not be a completely predictable situation.

Next, I took Danny's solution and adapted the code as follows:

Iteration 1:
aiSampleStart(board,
    1+
convertPeriodDivisor*m_numInputs,
    3,
    tMSeries::tAI_START_STOP_Select::kAI_START_SelectSI_TC,
    tMSeries::tAI_START_STOP_Select::kAI_START_PolarityRising_Edge);
aiConvert(board,
    convertPeriodDivisor,
    3,
    kFalse);

Iteration 2:
aiSampleStart(board,
   
convertPeriodDivisor*(m_numInputs+1),
    3,
    tMSeries::tAI_START_STOP_Select::kAI_START_SelectSI_TC,
    tMSeries::tAI_START_STOP_Select::kAI_START_PolarityRising_Edge);
aiConvert(board,
    convertPeriodDivisor,
    3,
    kFalse);

Both yielded:

4 inputs, 250 kSa/sec, 12 Sa/input/main loop, convert period divisor = 80, samples measured per sec = 48 (CORRECT because 12 Sa*4 inputs = 48 samples per main loop)
5 inputs, 250 kSa/sec, 10 Sa/input/main loop, convert period divisor = 80, samples measured per sec = 50 (CORRECT because 10 Sa*5 inputs = 50 samples per main loop)

I'm not sure about all the implications of what I've done, but it appears to work for a number of configurations.  I also don't understand how running a lower frequencies would allievate this problem.  I've tried to determine where I came up with most of the number for this stuff.  The DDK examples use hard coded numbers, so I determined most of it through experimentation and the forum here.  Thanks to Danny L.

I've never run across any timing diagrams for the M-series.  Danny, can you point me towards these so I can understand this more?  The poking in the dark has worked with some guidance, but some documentation would really have shed light on the situation.  I'm still not convinced that everything is correct, but I am convinced it is a timing issue and maybe a timing diagram could put my mind at ease.

For future people that might follow my path, I'm currently using Iteration 1 with 3+ instead of 1+ because it introduces the smallest delay and hopefully keeps everything synchronized.

Aaron
Message 12 of 15
(5,694 Views)

Hi Aaron.

There is a section called "Analog Input Timing Signals" in "Chapter 4 Analog Input" of the M Series User Manual.

http://digital.ni.com/manuals.nsf/websearch/B53FA1760200AF86862573A3006F9E56

The E-Series RLP manual and DAQ-STC Reference Manual can also be helpful since most of the "concept" on the E-Series applies also to the M-Series.

http://digital.ni.com/manuals.nsf/websearch/5978CE4A83119E50862566FA0075F424

http://digital.ni.com/manuals.nsf/websearch/E929838D7D0EE50986256728007FEADF

Danny

Message 13 of 15
(5,682 Views)
Well, I ran into problems again only this time with 7 or more inputs.  Gathering what I could from previous experience and the literature that exists, I came up with the following relationships for running running a task that will end in 200 us or slightly less and gathering the maximum number of points for a given number of inputs.

m_convertPeriodDivisor = 20 MHz/acquisition rate (250kHz is the max and default in my case)
convertPeriod = m_convertPeriodDivisor/20MHz
desiredSamplePeriod (desired) (us) = m_convertPeriod*m_numInputs+3*0.15us
m_sampleClockDivisor (unitless) = ceil(20 MHz * desiredSamplePeriod)
m_samplePeriod (us) = minSampleClockDivisor/20MHz
m_numSamplesPerInput (maximum number of times an input can be read in 200 us) = floor(200 us/m_samplePeriod)

aiNumberOfSamples(board,  
    m_numSamplesPerInput, // posttrigger samples
    0,                 // pretrigger samples
    kFalse);           // continuous?
aiSampleStart(board,
    m_samplePeriodDivisor,
    3,
    tMSeries::tAI_START_STOP_Select::kAI_START_SelectSI_TC,
    tMSeries::tAI_START_STOP_Select::kAI_START_PolarityRising_Edge);
aiConvert(board,
    m_convertPeriodDivisor, //80,     // convert period divisor
    3,       // convert delay divisor
    kFalse); // external sample clock?

For 8 inputs, I get
m_convertPeriodDivisor = 80
convertPeriod = 4 us
desiredSamplePeriod = 32.45 us
m_sampleClockDivisor = 649
m_samplePeriod = 32.45 us
m_numSamplesPerInput = 6

I should gather 48 total samples every 200 us, and that was the result.  I'm currently limited by software to 8 inputs so I haven't been able to easily test above this number.

The 3*0.15us above is because the M-series manual says that the sample clock to convert clock delay is configurable but "by default, this delay is three ticks of ai/ConvertClockTimebase," which is then 3*3/20MHz or 3*0.15us.  I have the 3 hardwired everywhere at this point, although it appears it can be as low as 2.

This seems to working for a wide range of inputs, so this *may* be the correct method for the given situation.

Aaron
0 Kudos
Message 14 of 15
(5,583 Views)
I was previously limited to testing 8 input channels by the software that uses the DDK, but I've recently been able to expanded it to 16.  When I got to 13 inputs, my previous solution failed once again.  Knowing the way to solve the problem, I increased the the hard-wired 3 to 6.  Upon testing with up to 16 inputs, everything is again working as expected.  It appears I don't completely understand the timing issues, which shouldn't come as a surprise.  Nevertheless, things continue to work with minimal added time delays.  I'll continue to increase the channel count to 32 eventually after I can limit the memory usage problem that is compounded by quadrupling the number of inputs.
0 Kudos
Message 15 of 15
(5,518 Views)