Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

32-bit lmitation of the NI-DAQmx int32 DAQmxSetReadOffset() function?

Solved!
Go to solution

I have a data acquisition application where I am continuously acquiring 5 channels of data at 40KHz/channel.  I am also reading the data soon after it is acquired in 0.1 second chunks.  This successfully works perfectly for over 14 hrs continuous acquisition.  However, when 14hrs, 54 min and 47 seconds is passed the program hangs up and I get this DAQmx error message:
    "Measurements: Invalid combination of position and offset.  The position and offset specified a sample prior to the first sample acquired (sample 0).
    Make sure any negative read offset specified will select a valid sample when combined with the read position.
    Property: DAQmx_Read_RelativeTo
    Corresponding value: DAQmx_Val_FirstSample
    Property: DAQmx_Read_Offset
    Corresponding value: -2147483296
    Task Name: _unnamedTask<6>
    StatusCode: -200277"

 

The relevant code for configuration is this:
    DAQmxErrChk (DAQmxCreateTask("",&hAItask));
    DAQmxErrChk (DAQmxCreateAIVoltageChan(hAItask, "Dev1/ai0:4", "", DAQmx_Val_NRSE, -10.0, 10.0, DAQmx_Val_Volts, NULL));
    DAQmxErrChk (DAQmxCfgSampClkTiming(hAItask, "/Dev1/ao/SampleClock", 40000.0, DAQmx_Val_Rising, DAQmx_Val_ContSamps, (uInt64)(300 * 4000) )); 

    DAQmxErrChk (DAQmxSetReadOverWrite(hAItask, DAQmx_Val_OverwriteUnreadSamps));
    DAQmxErrChk (DAQmxSetReadRelativeTo(hAItask, DAQmx_Val_FirstSample));

where the number of 0.1sec buffers(=300) * number of samples/channel in a 0.1sec buffer)(=4000)

 

And the error seems to occur with the DAQmxSetReadOffset() function in this code:
    int32   DAQmxInternalAIbuffer_Offset;
    long    BufferToRead;
    DAQmxInternalAIbuffer_Offset = BufferToRead * 4000;                                                   // 4000 is the nuimber of samples/channel to read into the AI buffer
    DAQmxErrChk (DAQmxSetReadOffset(hAItask, DAQmxInternalAIbuffer_Offset));
    DAQmxErrChk (DAQmxReadBinaryI16(hAItask, 4000,10.0,DAQmx_Val_GroupByScanNumber, ReadArray, 20000, &NumAIsamplesPerChRead, NULL));

where 20000 = 4000 samples/ch in 0.1sec buffer * 5 AD channels.

 

Since the highest int32 value is 0x7FFFFFFF = 2147483647, and if the highest 32bit int was divided by 4000 buffers (number of samples/channel to read into the AI buffer), the highest BufferToRead would be:
    2147483647 / 4000 = 536870.91175

which in time is:
    536870 * 0.1 sec buffers = 53687 sec = 14hrs + 54min + 47.0 sec which is exactly when the code fails, apparently in the DAQmxSetReadOffset() function.

 

My questions are:
    1) Is there a 64bit integer equivalent for the int32 DAQmxSetReadOffset() function (like the 64 bit DAQmxGetReadTotalSampPerChanAcquired() )?
    2) Is there any way that when the int32 offset value would be > 0x7FFFFFFF then I would subtract 0x7FFFFFFF from the value?  This seems messy because I am reading 4000 samples/channel every 0.1 seconds, so 0x7FFFFFFF does not fit on a 4000 sample boundary.

    3) Or should I be doing something completely different?

 

This seems to me to be a real limitation of the 32bit DAQmxSetReadOffset(), and it would be much cleaner if it were like the 64 bit DAQmxGetReadTotalSampPerChanAcquired().

 

I am using DAQmx 9.2, C++Bulder, and a PCIe-6259

 

Thanks,

 

Bill Anderson

 

0 Kudos
Message 1 of 5
(4,083 Views)

Hi Bill,

 

As far as I know, the actual read position is 64-bit, even though the read offset property used to control it is 32-bit. During the DAQmx port to 64-bit Windows, some work was done to make it possible to support 64-bit read offsets on 64-bit systems, but this was not completed, so it's not possible to set a 64-bit read offset through the API.

 

You should be able to advance the read position past the 2^31 mark by reading relative to the current read position (DAQmx_Val_CurrReadPos) or the most recent sample (DAQmx_Val_MostRecentSamp) instead of the first sample. Do you think that this could work for your application? It kind of sounds like you're trying to read consecutive chunks of data, but I'm not entirely sure.

 

Brad

---
Brad Keryan
NI R&D
0 Kudos
Message 2 of 5
(4,077 Views)
Solution
Accepted by Bill_Anderson

Hi Brad,

 

Thank you for the prompt reply.  I think in my program it would be very difficult to change from using the DAQmx_Val_FirstSample as I have several threads, where one thread sequentially reads the latest consecutive chunk, and two other threads just occasionally read chunks when necessary.  To change such a fundamental setting would be to change a lot in my application and risk introducing many errors.

 

I hope that National Instruments fixes this limitation in their API, not just for 64-bit Windows, but also for 32-bit Windows.  Maybe you could have a DAQmxSetRe​adOffset64() ?  I know that this is a kludge, but it would be a very useful kludge.

 

Anyways, for the time being I'll stick to my code and the 14hr 54 min limitation with the hopes that a fix will eventually be put in if there is more interest.

 

Many thanks for your info.

 

Bill 

0 Kudos
Message 3 of 5
(4,047 Views)

Hi Bill,

 

It should be feasible to write a wrapper for DAQmxSetReadOffset() + DAQmxReadBinaryI16() that accepts an absolute read position (relative to 1st sample) and translates it to a relative read position (relative to current sample). You would have to keep track of the 64-bit current read position in your code and set the relative read offset to (newPosition - currPosition). Note that performing a read updates the current read position.

 

This would also require serializing access to the DAQmx task and the cached read position, but your current approach probably needs that too. Individual operations in the DAQmx API are thread-safe (serialized per task), but that doesn't make a sequence of operations such as "set the read offset and then perform a read" thread-safe. You need a mutex or critical section to ensure that another thread doesn't set the read offset in between the call to DAQmxSetReadOffset() and the call to DAQmxReadBinaryI16(), unless you have some other way of ensuring that these calls don't get interleaved.

 

I recommend posting the 64-bit read offset idea to the Data Acquisition Idea Exchange. That way, other users who are interested can vote on it and we can gauge how much interest there is.

 

Brad

---
Brad Keryan
NI R&D
0 Kudos
Message 4 of 5
(3,973 Views)

Hi Brad,

 

Thanks for the idea.  I just posted the 64-bit DAQmxSetReadOffset() request to the Data Acquisition Idea Exchange, and I will see how that goes before trying to implement your solution (which takes 14hr 54min to test!).  (I do have my DAQmxSetReadOffset() and DAQmxReadBinaryI16()in a critical section.)

 

Many thanks,

 

Bill Anderson

0 Kudos
Message 5 of 5
(3,938 Views)