Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

DAQmxReadAnalogF64 Intermittent Warning of 1

Hi,
I think this might be one of those "it could be anything" questions but I have an intermittent problem with the analogue read function.

Everything works fine for about 30-60 secs but then all of a suddent the DAQmxReadAnalogF64 function returns a 1 rather than a 0.  Shall I just ignore it? Or is it something more serious?  Since it actually reads the data fine (from what I can see on a plot, I'm not checking every single sample).

Any Idea's?

Phil Winder
www.philwinder.com
0 Kudos
Message 1 of 10
(3,932 Views)
Couldnt find an edit post button!

I told some small porkies in that last post.  If I just ignore the warning, everything is not fine.  The callback keeps functioning, the device keeps working, but every bit of data after the warning is not new.  So Its not reading any new data in.
And I can update the times when it happens too, from  20 seconds to infinity.  Often it never happens and I have to close the program and start again.

Cheers,

Phil Winder
www.philwinder.com
0 Kudos
Message 2 of 10
(3,928 Views)
Hi Phil,

Please can you post back a code snippet that shows the setup code "DAQmxCreateTask" down to the DAQmxRead function.

This will be easier than asking for the buffer sizes you have set and so on.

Regards
JamesC
NIUK and Ireland

It only takes a second to rate an answer 🙂

0 Kudos
Message 3 of 10
(3,888 Views)
Its a bit hard as seen as all of the code is wrapped up in stuff, but here goes.

Setup:

if (errorNumber = (int)DAQmxCreateTask("",&gTaskHandle) != 0)

return 1;


if (errorNumber = (int)DAQmxCreateAIVoltageChan(gTaskHandle, toChar(QString(this->getDeviceName() + "/" + channel)),"",DAQmx_Val_PseudoDiff,

(float64)minVolts,(float64)maxVolts,DAQmx_Val_Volts,NULL) != 0)

return 1;

if (errorNumber = (int)DAQmxCfgSampClkTiming(gTaskHandle,"OnboardClock",(float64)sampFreq,

DAQmx_Val_Rising, DAQmx_Val_ContSamps,(uInt32)this->getDataBufferSize()) != 0)

return 1;

if (errorNumber = (int) DAQmxRegisterEveryNSamplesEvent(gTaskHandle,DAQmx_Val_Acquired_Into_Buffer,

(uInt32)this->getDataBufferSize(), 0, (DAQmxEveryNSamplesEventCallbackPtr )DAQCallback, this) != 0)

return 1;

Read Interrupt:

if (errorNumber = (int) DAQmxReadAnalogF64 (taskHandle, -1,0, DAQmx_Val_GroupByChannel ,

(float64*)parent->data, (uInt32)parent->getDataBufferSize()*parent->getNumberOfChannels(), &numRead, NULL) != 0)

return 1;


Thats it with lots of error checking stripped out, but I dont think you are going to get much from that. I think what I will have to do is go back to a smaller program and see if I can recreate the bug.  I just thought someone may have had a similar problem, or know what was wrong from the symptoms.


Cheers,

Phil Winder




0 Kudos
Message 4 of 10
(3,877 Views)
Ah, I think ive cracked it.
I think the errors were buffer overrun errors (annoying that the 4462 almost always returns 1 as an error.  Not very informative!).  This, I eventually figured out, seemed to be happening every time my cpu hit 100% load.  Then the DAQ would stop acquiring, post an error of 1 and quit.  To fix this I manually set the sampsPerChanToAcquire setting in the DAQmxCfgSampClkTiming function.
Just a bit of background, I am using continuous acquiring, so the sampsPerChan...  variable set the hardware buffer size.  I am also interrupting every 50000 samples.  So setting this value to 200000 or above seems to get rid of all my intermittent problems!! Woo!

Hope this helps someone in the future...

Best regards,

Phil Winder
www.philwinder.com
0 Kudos
Message 5 of 10
(3,873 Views)
Hi Phil,

I figured the error number was not 1, as this is not a DAQmx error number which start at around the 200000 mark.
The problem is occuring because you are overwriting the error number with the return(1); statement.

Pelase consider using the shipping examples as a base for your program structure. As there is a very useful function defined that will deal with error checking and reporting. Please find the shipping examples as documented in this KB.
I am going to borrow the code body from the analog input example "Acq-IntClk"

#include <stdio.h>
#include <NIDAQmx.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void)
{
    int32       error=0;
    TaskHandle  taskHandle=0;
    int32       read;
    float64     data[1000];
    char        errBuff[2048]={'\0'};

    /*********************************************/
    // DAQmx Configure Code
    /*********************************************/
DAQmxErrChk (DAQmxCreateTask("",&taskHandle));

Error:
    if( DAQmxFailed(error) )
        DAQmxGetExtendedErrorInfo(errBuff,2048);
    if( taskHandle!=0 )  {
        /*********************************************/
        // DAQmx Stop Code
        /*********************************************/
        DAQmxStopTask(taskHandle);
        DAQmxClearTask(taskHandle);
    }
    if( DAQmxFailed(error) )
        printf("DAQmx Error: %s\n",errBuff);
    printf("End of program, press Enter key to quit\n");
    getchar();
    return 0;
}
  

This uses the real DAQmx error return value so you should be able to find more information on the error on the NI website.

You can also intergrate the DAQmxGetErrorString function to get a meaningful error message, which will tell you what the error is and possible solutions to the error.

Regards
JamesC
NIUK and Ireland

It only takes a second to rate an answer 🙂

0 Kudos
Message 6 of 10
(3,849 Views)
Hi James,
Thanks for the thoughts.
That was a stipped down version of my code.  Every function ecapsulates something like this:

// Configure the sample rate and number of samples.

if (errorNumber = (int)DAQmxCfgSampClkTiming(gTaskHandle,"OnboardClock",(float64)sampFreq,

DAQmx_Val_Rising, DAQmx_Val_ContSamps,(uInt32)this->getDataBufferSize()) != 0)

{

getError(errorNumber);

return 1;

}



Where getError is:


QString QpnwNIDAQ::getError(int error)

{

if (error == 0) return "";

else

{

char errorString[charBufferSize];

DAQmxGetErrorString ((int32)error, errorString, charBufferSize);

QString errMsg = toQString(errorString,charBufferSize);

QMessageBox::warning(0, tr("DAQ Error"),

QString::number(error) + ": " + errMsg,

QMessageBox::Ok,QMessageBox::Ok);

return errMsg;

}

}




This works, since I have had error messages before.  Just most of the time, as with the buffer overrun case, the error number is 1 and returns "" as the error message.


Which brings me onto another problem with NIDAQmx, the examples everyone always keeps talking about are never installed.  There has been a couple of post about this, and apparently it has been sorted now.  I am yet to try.  Either way Ive got everything working with the help of this forum and the (at times confusing) help files.  May I suggest that examples are provided in the help files below the respective functions.  This would help a lot.

Many thanks,
Phil Winder
www.philwinder.com




0 Kudos
Message 7 of 10
(3,847 Views)
Hi Phil,

In C and C++, the assignment operator has lower precedence than the comparison operators. It looks like you're assigning the result of the Boolean expression (int)DAQmxCfgSampClkTiming(...) != 0 to errorNumber. To get the code to do what you want, add parentheses:

if((errorNumber = (int)DAQmxCfgSampClkTiming(...)) != 0)

{

   ...

}


Hope this solves your problem,


Brad

---
Brad Keryan
NI R&D
0 Kudos
Message 8 of 10
(3,838 Views)
Ah yeah, interesting point.  Well spotted.  Thanks  Brad!
0 Kudos
Message 9 of 10
(3,833 Views)
Hi Brad, I implemented the changes in the error you found and the errors are now correctly being received.  Thanks for your help.  Oh and the error message I got from the previous problem was indeed a buffer overrun.

Cheers,
Phil Winder
www.philwinder.com
0 Kudos
Message 10 of 10
(3,800 Views)