Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

continuous analog acquisition with DAQmxBaseReadAnalogF64

I want to continuously acquire an analog signal, to process it real time.
I therefore use the code given in the example /usr/local/natinst/nidaqmxbase/examples/ai, but change the DAQmxBaseReadAnalogF64
pointsToRead to -1 so that I get all the signal up to the current time :
DAQmxBaseReadAnalogF64(taskHandle,-1,timeout,DAQmx_Val_GroupByScanNumber,data,bufferSize,&pointsRead,NULL));
 
I tried to increase the buffer size, reduce the frequency, whatever I do, there is always only 2 points read in the buffer.
Any idea where the problem comes from ?
 
Thanks a lot for your help,
 
Elisabeth
0 Kudos
Message 1 of 14
(5,399 Views)
Is there any error code returned from the call?

How do you set up the scanning task?

Are you reading immediately after starting the task?

What is the timeout?

The path you give for the example suggests a Linux or Unix platform, but it's always a good idea to include information on the operating system, and development system being used.

It may be best to actually post the code relevant to the system. That often answers a lot of the sorts of questions I have just asked, and gives us a chance to check for problems that you don't think are problems.
John Weeks

WaveMetrics, Inc.
Phone (503) 620-3001
Fax (503) 620-6754
www.wavemetrics.com
0 Kudos
Message 2 of 14
(5,375 Views)

Thanks a lot John for this remarks and your kindness; I am new to this kind of list, and I was a little lost to post my message.

I am working on a Linux redhat PC, using a gcc compiler. My OS is not specified as supported, but I installed the

driver without any issue, and the code /usr/local/natinst/nidaqmxbase/examples/ai/contAcquireNChan.c works fine.

The slittly modified code that does not work is the following :

    // Timing parameters
    char        clockSource[] = "OnboardClock";
    //uInt64      samplesPerChan = 1000;
    float64     sampleRate = 250.0;//5000.0;

    // Data read parameters
    #define     bufferSize (uInt32)1000
    float64     data[bufferSize];
    //int32       pointsToRead = bufferSize;
    int32       pointsRead;
    float64     timeout = 10.0;
    int32       totalRead = 0;

   // test
   FILE *testfile;
   if ((testfile = (FILE *)fopen("/srv/gxre-napp3/vol4/soubeel/to/tmp/ecg.txt","w"))==NULL) {
  fprintf(stderr,"cannot open test file");
  exit(-1); }
 
    printf("Press Ctrl-C to exit\n");
    DAQmxErrChk (DAQmxBaseCreateTask("",&taskHandle));
    DAQmxErrChk (DAQmxBaseCreateAIVoltageChan(taskHandle,chan,"",DAQmx_Val_Cfg_Default,min,max,DAQmx_Val_Volts,NULL));
    DAQmxErrChk (DAQmxBaseCfgSampClkTiming(taskHandle,clockSource,sampleRate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,));
    DAQmxErrChk (DAQmxBaseCfgInputBuffer(taskHandle,100000)); //use a 100,000 sample DMA buffer
    DAQmxErrChk (DAQmxBaseStartTask(taskHandle));

    // The loop will quit after 10 seconds

    startTime = time(NULL);
    while( time(NULL)<startTime+10 ) {
       DAQmxErrChk (DAQmxBaseReadAnalogF64(taskHandle,-1/*pointsToRead*/,timeout,DAQmx_Val_GroupByScanNumber,data,bufferSize,&pointsRead,NULL));
        totalRead += pointsRead;
        printf("Acquired %d samples. Total %d\n",pointsRead,totalRead);
        // Just print out the first 10 points of the last data read
        for (i = 0; i <pointsRead ; ++i)
            fprintf (testfile,"%f\n",data[i]);

    }
    printf("\nAcquired %d total samples.\n",totalRead);

Error:
    if( DAQmxFailed(error) )
        DAQmxBaseGetExtendedErrorInfo(errBuff,2048);
    if(taskHandle != 0) {
        DAQmxBaseStopTask (taskHandle);
        DAQmxBaseClearTask (taskHandle);
    }
    if( DAQmxFailed(error) )
        printf("DAQmxBase Error: %s\n",errBuff);
    return 0;

This code does not generate any error, but the output is the following :
 
Press Ctrl-C to exit
Acquired 2 samples. Total 2
Acquired 2 samples. Total 4
Acquired 2 samples. Total 6
Acquired 2 samples. Total 8
Acquired 2 samples. Total 10
...
 
Whatever I change ( sample rate, bufferSize, ... ) I always get 2 samples at each reading.
 
Thanks in advance for your help
0 Kudos
Message 3 of 14
(5,368 Views)
I think the behavior you are seeing is simply because the loop executes so fast that only two samples have been taken when you call DAQmxBaseReadAnalogF64. If you add some delay to the loop, you may get more samples returned. It is a little odd that it is always two samples, and never just one.

Did you want a specific number of samples to be read in each iteration of the loop? If so, you should replace -1 with that number. Make sure the timeout parameter is set to a sufficient long time to actually scan all the samples you want.
John Weeks

WaveMetrics, Inc.
Phone (503) 620-3001
Fax (503) 620-6754
www.wavemetrics.com
0 Kudos
Message 4 of 14
(5,363 Views)

Hi All-

I second John's suggestion to explicitly set the number of samples to what you expect;  the "-1" setting for samples to read does not function properly in NI-DAQmx Base.  The most common behavior is that exactly two samples are returned, and this seems to be exactly what you're seeing in your app.

Hopefully this helps-

Tom W
National Instruments
Message 5 of 14
(5,356 Views)

Tom and John,

Thanks a lot for your help; I was thinking I was making a stupid mistake somewhere...(It is a pitty that the -1 not working is not in the README file of the DAQmx Base driver).

My goal is to read values and analyse them as real time as possible. The problem is that if I read them 5 by 5 at a frequency of 250Hz,

it takes time to read the values, and I will be more and more late compare to the current acquired values. I guess the only choice that I

have is to store the "system time" before the acquisition, then before the next acquisition, and compute how many samples have been acquired in between, knowning the sample rate of the acquisition.

Any other suggestion using the DAQmx Base C functions ?

Thanks again for this precious help,

Elisabeth

0 Kudos
Message 6 of 14
(5,353 Views)
It's been a while since I tried to do something like this with DAQmx Base. My experience made me abandon DAQmx Base and simply require a PC for our application, so I could use NI-DAQmx.

My recollection is that you can use a large number for the number of samples to return, and a short timeout (maybe even zero?). Then when the timeout occurs you will have whatever data was available, and sampsPerChanRead parameter will be set appropriately. This approach requires that you test for the error code that indicates a timeout and interpret it accordingly. That is, check for the error code DAQmxErrorOperationTimedOut (and possibly others as well) and don't abort your program on that error.
John Weeks

WaveMetrics, Inc.
Phone (503) 620-3001
Fax (503) 620-6754
www.wavemetrics.com
0 Kudos
Message 7 of 14
(5,348 Views)

Thanks a lot John, for this all lot of information.

I am working on a linux PC with an USB6008, so I think I cannot switch to DAQmx driver.

So I will keep the DAQmx Base, and try out your suggested solution.

Thanks a lot again and Happy new year !

Elisabeth

0 Kudos
Message 8 of 14
(5,331 Views)

John, I tried your suggestion but it does not work. The code is the following :

    float64     sampleRate = 250.0;//5000.0;

    // Data read parameters
    #define     bufferSize (uInt32)1000
    float64     data[bufferSize];
    int32       pointsToRead = bufferSize;
    int32       pointsRead;
    float64     timeout = 0.1;
    int32       totalRead = 0;

   // test
   FILE *testfile;
   if ((testfile = (FILE *)fopen("/srv/gxre-napp3/vol4/soubeel/to/tmp/ecg.txt","w"))==NULL) {
  fprintf(stderr,"cannot open test file");
  exit(-1); }
 
    printf("Press Ctrl-C to exit\n");
    DAQmxErrChk (DAQmxBaseCreateTask("",&taskHandle));
    DAQmxErrChk (DAQmxBaseCreateAIVoltageChan(taskHandle,chan,"",DAQmx_Val_Cfg_Default,min,max,DAQmx_Val_Volts,NULL));
    DAQmxErrChk (DAQmxBaseCfgSampClkTiming(taskHandle,clockSource,sampleRate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,pointsToRead));
    DAQmxErrChk (DAQmxBaseCfgInputBuffer(taskHandle,100000)); //use a 100,000 sample DMA buffer
    DAQmxErrChk (DAQmxBaseStartTask(taskHandle));

    // The loop will quit after 10 seconds

    startTime = time(NULL);
    while( time(NULL)<startTime+10 ) {
       sleep(1);
       error = DAQmxBaseReadAnalogF64(taskHandle,pointsToRead,timeout,DAQmx_Val_GroupByScanNumber,data,bufferSize,&pointsRead,NULL);
       if( DAQmxFailed(error) ) {
   DAQmxBaseGetExtendedErrorInfo(errBuff,2048);
       printf("DAQmxBase Error: %s, err or code : %d\n",errBuff,error);
       }
      
       if(taskHandle != 0) {      
   totalRead += pointsRead;
   printf("Acquired %d samples. Total %d\n",pointsRead,totalRead);
   // Just print out the first 10 points of the last data read
   for (i = 0; i <pointsRead ; ++i)
      fprintf (testfile,"%f\n",data[i]);
  
       }
    }
    printf("\nAcquired %d total samples.\n",totalRead);

Running this code gives the following output :
 
Press Ctrl-C to exit
DAQmxBase Error: <err>Some or all of the samples requested have not yet been acquired.
To wait for the samples to become available use a longer read timeout or read later in your program. To make the samples available sooner, increase the sample rate., err or code : -200284
Acquired 0 samples. Total 0
DAQmxBase Error: <err>Some or all of the samples requested have not yet been acquired.
To wait for the samples to become available use a longer read timeout or read later in your program. To make the samples available sooner, increase the sample rate., err or code : -200284
Acquired 0 samples. Total 0
DAQmxBase Error: <err>Some or all of the samples requested have not yet been acquired....
 
Therefore, the return error code is not DAQmxErrorOperationTimedOut but DAQmxErrorSamplesNotYetAvailable, and nothing is retrieved from the buffer. ( but if I try to retreive 100 samples with a timeout of 1s it works fine ). Any idea what is going on here ?
 
Thanks in advance,
Elisabeth
0 Kudos
Message 9 of 14
(5,295 Views)
>Therefore, the return error code is not DAQmxErrorOperationTimedOut but DAQmxErrorSamplesNotYetAvailable,
>and nothing is retrieved from the buffer. ( but if I try to retreive 100 samples with a timeout of 1s
>it works fine ). Any idea what is going on here ?

Yes- my memory is failing me. I thought yesterday that DAQmxErrorOperationTimedOut didn't sound familiar (but it sounds logical, you have to admit). DAQmxErrorSamplesNotYetAvailable is the one I checked for. My apologies for the inaccurate info. (Although I did say something to the effect of "DAQmxErrorOperationTimedOut and maybe others" 🙂

Retrieving 100 samples with a timeout of 1 s. works because you are sampling at a rate of 250 s/s, so the timeout is longer than necessary. If that works for you, I think it is the preferred solution. My situation was that I couldn't tell in advance what the sampling rate would be (that is controlled by the user, and could be the result of an external clock), so I couldn't make firm predictions of how long it should take. As long as you have a fixed, known sampling rate adjusting the timeout should be a good solution.
John Weeks

WaveMetrics, Inc.
Phone (503) 620-3001
Fax (503) 620-6754
www.wavemetrics.com
0 Kudos
Message 10 of 14
(5,284 Views)