Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

How to sample multiple sensors in a continuous task?

Solved!
Go to solution

I need to sample one thermocouple sensor and one voltage sensor in a continuous task. My hardware setup includes a cDAQ-9172 chassis with one NI9211 TC module and one NI9221 voltage input module.

 

I started with the example C code for thermocouple measurement found here:

 

National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Analog In\Measure Temperature\Cont Thrmcpl Samples-Int Clk\ContThrmcplSamps-IntClk.c

 

I then added a few lines of code for the additional voltage measurement.

 

The task runs for about 20 seconds until the buffer overflows with error -200279.

 

I can run either task, thermocouple or voltage, indefinitely. It's only when I include them both in the same task that the buffer overflows.

 

I've tried many combinations of sample rate, buffer size and DAQmxRegisterEveryNSamplesEvent nSample size.

 

The code I'm trying to run is shown below.  Changes to the original file are highlighted in bold. I've attached a screen shot of the command line output.

 

Can anybody provide an example C program showing how to sample multpile sensors continuously in one task?

 

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

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

int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData);
int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData);

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

    /*********************************************/
    // DAQmx Configure Code
    /*********************************************/
    DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
    DAQmxErrChk (DAQmxCreateAIThrmcplChan(taskHandle,"cDAQ1Mod1/ai0","",0.0,100.0,DAQmx_Val_DegC,DAQmx_Val_K_Type_TC,DAQmx_Val_BuiltIn,25.0,""));
 DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"cDAQ1Mod4/ai0","",DAQmx_Val_Cfg_Default,-60.0,60.0,DAQmx_Val_Volts,NULL));
    DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",1000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));

    DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle,DAQmx_Val_Acquired_Into_Buffer,1000,0,EveryNCallback,NULL));
    DAQmxErrChk (DAQmxRegisterDoneEvent(taskHandle,0,DoneCallback,NULL));

    /*********************************************/
    // DAQmx Start Code
    /*********************************************/
    DAQmxErrChk (DAQmxStartTask(taskHandle));

    printf("Acquiring samples continuously. Press Enter to interrupt\n");
    getchar();

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;
}

int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
    int32       error=0;
    char        errBuff[2048]={'\0'};
    static int  totalRead=0;
    int32       read=0;
    float64     data[1000];
 uInt32 i;

    /*********************************************/
    // DAQmx Read Code
    /*********************************************/
    DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,-1,10.0,DAQmx_Val_GroupByScanNumber,data,1000,&read,NULL));

    if( read>0 ) {
 for (i = 0 ; i < 2*read ; i++ ) { printf("%.5f\n", data[i]); }
        printf("Acquired %d samples. Total %d\r",read,totalRead+=read);
        fflush(stdout);
    }

Error:
    if( DAQmxFailed(error) ) {
        DAQmxGetExtendedErrorInfo(errBuff,2048);
        /*********************************************/
        // DAQmx Stop Code
        /*********************************************/
        DAQmxStopTask(taskHandle);
        DAQmxClearTask(taskHandle);
        printf("DAQmx Error: %s\n",errBuff);
    }
    return 0;
}

int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData)
{
    int32   error=0;
    char    errBuff[2048]={'\0'};

    // Check to see if an error stopped the task.
    DAQmxErrChk (status);

Error:
    if( DAQmxFailed(error) ) {
        DAQmxGetExtendedErrorInfo(errBuff,2048);
        DAQmxClearTask(taskHandle);
        printf("DAQmx Error: %s\n",errBuff);
    }
    return 0;
}
0 Kudos
Message 1 of 10
(4,142 Views)

Hi egret2008,

 

I believe if you are trying to collect data from two different modules, you need to create two separate tasks. In other words, you need two Taskhandles. I recommend looking at the example found here:

 

National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Synchronization\Multi-Device\Continuous AI\ContinuousAI.c

 

Although this example is used for synchronization, it shows how to configure your acquisition for multiple devices. 

Tunde S.
Applications Engineer
National Instruments
0 Kudos
Message 2 of 10
(4,124 Views)

Hi Tunde,

 

Thanks for your reply.

 

I was under the impression that there can only be one AI task per cDAQ chassis.  For example, if I try to create two separate tasks in Signal Express (to measure from the two modules described in my first post) I get an error saying that the task is already reserved. But if I put both modules in the same task it works, with Signal Express at least but not with my C code.

0 Kudos
Message 3 of 10
(4,113 Views)

This link explains that my chassis (cDAQ-9172) can only run one analog input task at a time.

 

http://digital.ni.com/public.nsf/allkb/E7036C1870F6605686257528007F7A72

 

Therefore, I need a solution that allows me to sample from both AI modules using only one task.

0 Kudos
Message 4 of 10
(4,102 Views)

Hi egret2008,

 

It looks like your code has the buffer set to 1000 samples and your EveryNSample Event is set to run at 1000 samples. This is not recommened because any jitter from the software side could result in a buffer overflow. You can resolve this in 2 ways. First is to increase the buffer. You can do this by changing this line:

 

DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",1000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));

 

Instead of setting it to the sampsPerChanToAcquire parameter (the last one) to 1000, increase it to something like 10,000.

 

The second way is to have your EveryNSample Event happen more often. You can do this by changing this line:

 

DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle,DAQmx_Val_Acquired_Into_Buffer,1000,0,EveryNCallback,NULL));

 

Decrease the nSamples parameter (the third one) from 1000 to 100. This will cause the event to happen more frequently so the buffer does not overfill.


Steven K.
National Instruments
Software Engineer
0 Kudos
Message 5 of 10
(4,084 Views)

Hi Steve,

 

I have tried your suggestion, and many other combinations of sampsPerChanToAcquire, nSample and rate, but I always get a buffer overflow.

0 Kudos
Message 6 of 10
(4,073 Views)
Solution
Accepted by topic author egret2008

One more thing that I noticed is that size of data[] hasn't be increased to accomodate the additional channels. Increase it to 2000 and also increase arraySizeInSamps (5 parameter) to 2000 in the DAQmxReadAnalogF64 function call. Since it was only set to 1000 samples, it will only get 500 samples per channel causing the overflow.

Steven K.
National Instruments
Software Engineer
Message 7 of 10
(4,069 Views)

Thanks Steve. That works!

 

So, putting it all together, the example code now looks like this:

 

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

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

int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData);
int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData);

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

    /*********************************************/
    // DAQmx Configure Code
    /*********************************************/
    DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
    DAQmxErrChk (DAQmxCreateAIThrmcplChan(taskHandle,"cDAQ1Mod1/ai0","",0.0,100.0,DAQmx_Val_DegC,DAQmx_Val_K_Type_TC,DAQmx_Val_BuiltIn,25.0,""));
    DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"cDAQ1Mod4/ai0","",DAQmx_Val_Cfg_Default,-60.0,60.0,DAQmx_Val_Volts,NULL));
    DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",1000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));

    DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle,DAQmx_Val_Acquired_Into_Buffer,100,0,EveryNCallback,NULL));
    DAQmxErrChk (DAQmxRegisterDoneEvent(taskHandle,0,DoneCallback,NULL));

    /*********************************************/
    // DAQmx Start Code
    /*********************************************/
    DAQmxErrChk (DAQmxStartTask(taskHandle));

    printf("Acquiring samples continuously. Press Enter to interrupt\n");
    getchar();

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;
}

int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
    int32       error=0;
    char        errBuff[2048]={'\0'};
    static int  totalRead=0;
    int32       read=0;
    float64     data[2000];
    uInt32      i;

    /*********************************************/
    // DAQmx Read Code
    /*********************************************/
    DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,-1,10.0,DAQmx_Val_GroupByScanNumber,data,2000,&read,NULL));

    if( read>0 ) {
        for (i = 0 ; i < 2*read ; i++ ) {
            printf("%.5f\n", data[i]);
        }
        printf("Acquired %d samples. Total %d\r",read,totalRead+=read);
        fflush(stdout);
    }

Error:
    if( DAQmxFailed(error) ) {
        DAQmxGetExtendedErrorInfo(errBuff,2048);
        /*********************************************/
        // DAQmx Stop Code
        /*********************************************/
        DAQmxStopTask(taskHandle);
        DAQmxClearTask(taskHandle);
        printf("DAQmx Error: %s\n",errBuff);
    }
    return 0;
}

int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData)
{
    int32   error=0;
    char    errBuff[2048]={'\0'};

    // Check to see if an error stopped the task.
    DAQmxErrChk (status);

Error:
    if( DAQmxFailed(error) ) {
        DAQmxGetExtendedErrorInfo(errBuff,2048);
        DAQmxClearTask(taskHandle);
        printf("DAQmx Error: %s\n",errBuff);
    }
    return 0;
}

 

0 Kudos
Message 8 of 10
(4,062 Views)

Could I ask though, how do you make this function truly continuous? It seems that you have to manually allocate the sizes of arrays beforehand but how do you allow it to continually grow with the number of samples retained?

 

Best,
Paolo

0 Kudos
Message 9 of 10
(3,698 Views)

Paolo,

 

I would recommend asking your question on a new thread as it appears this one has not been used in around 3 years. Using a newer thread will allow you to recieve a stronger community response.

Matt P.
Applications Engineer
National Instruments
0 Kudos
Message 10 of 10
(3,681 Views)