Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

Intermittent 200010 errors

I now have a small test program, that contains only the NI data collection routines, without any of the rest of my app.

I have attached the code below. When I run this on my new machine, it fails around 40% of the time, in DAQmxReadAnalogF64, with error 200010.

(When I try to clean up after this, I then get error -200088 when I call StopTask on the handle.)

 

Am I doing something wrong here?

 

First the error handling code...

 

// ni_test - Test call of NIDAQ functions.

#include <stdio.h>
#include "../NationalInstruments/NIDAQmx.h"

class Nidaq_Exception
{
public:
    int32 error_code;
    Nidaq_Exception (int32 _error_code)
    {
        error_code = _error_code;
    }
};

void CheckNidaqError (int32 error_code)
// Check the NIDAQmx return code - If non zero, print messages and raise an exception.
{
    if (error_code != 0)
    {
        // get error message
        int msg_len = DAQmxGetErrorString (error_code, NULL, 0);
        if (msg_len > 0)
        {
            char* msg = new char [msg_len];
            int result = DAQmxGetErrorString (error_code, msg, msg_len);
            printf ("NIDAQ error %d : %s\n", error_code, msg);
            delete[] msg;
        }
        // get extended error message
        int extended_msg_len = DAQmxGetExtendedErrorInfo (NULL, 0);
        if (extended_msg_len > 0)
        {
            char* extended_msg = new char [extended_msg_len];
            int extended_result = DAQmxGetExtendedErrorInfo (extended_msg, extended_msg_len);
            printf ("Extended error message:\n%s\n", extended_msg);
            delete[] extended_msg;
        }
        // if error, raise exception.
        if (error_code < 0)
        {
            Nidaq_Exception exc (error_code);
            throw exc;
        }
    }
}

void CleanupTask (TaskHandle* phandle)
// Clean up a partially-started task, in the event of an error.
{
    int32 result;
    // stop task
    result = DAQmxStopTask (*phandle);
    if (result != 0)
    {
        printf ("Failure in DAQmxStopTask\n");
        CheckNidaqError (result);
    }
    // destroy task
    result = DAQmxClearTask (*phandle);
    if (result != 0)
    {
        printf ("Failure in DAQmxClearTask\n");
        CheckNidaqError (result);
    }
    *phandle = 0;                      // clear handle value [not sure if this is the correct value]
}

0 Kudos
Message 11 of 13
(3,141 Views)

Now the A/D collection code...

 

bool Test_AD_Collect ()
// Collect data, return true if successful.
{
    const char* channels = "Dev1/ai1";
    double data [20000];
    int    data_size = sizeof (data) / sizeof (data [0]);
    double min_range = -10.0;
    double max_range = +10.0;
    int    num_samps_per_channel = 20000;
    double samp_freq_per_channel = 200000.0;
    double timeout_sec = 1.1;    // enough
    //double timeout_sec = 0.0;    // force timeout error

    bool rtn = false;
    try
    {
        int32 result;
        TaskHandle handle;
        result = DAQmxCreateTask (NULL, &handle);
        if (result != 0)
        {
            printf ("Failure in DAQmxCreateTask\n");
            CleanupTask (&handle);
            CheckNidaqError (result);
        }
        // create channel for reading voltage
        result = DAQmxCreateAIVoltageChan
            (handle,
             channels,
             NULL,
             DAQmx_Val_Cfg_Default,
             min_range,
             max_range,
             DAQmx_Val_Volts,        // units
             NULL);
        if (result != 0)
        {
            printf ("Failure in DAQmxCreateAIVoltageChan\n");
            CleanupTask (&handle);
            CheckNidaqError (result);
        }
        // get channel count
        uInt32 nidaq_num_channels;
        result = DAQmxGetTaskNumChans (handle, &nidaq_num_channels);
        if (result != 0)
        {
            printf ("Failure in DAQmxGetTaskNumChans\n");
            CleanupTask (&handle);
            CheckNidaqError (result);
        }
        // configure sample clock - frequency is based on the number of channels in task
        result = DAQmxCfgSampClkTiming
            (handle,
             NULL,                    // "OnboardClock" is ok too
             samp_freq_per_channel,
             DAQmx_Val_Rising,        // collect on the rising edge of the clock
             DAQmx_Val_FiniteSamps,
             num_samps_per_channel);
        if (result != 0)
        {
            printf ("Failure in DAQmxCfgSampClkTiming\n");
            CleanupTask (&handle);
            CheckNidaqError (result);
        }
        // read data
        int32 samps_per_chan_read;
        result = DAQmxReadAnalogF64
            (handle,
             num_samps_per_channel,
             timeout_sec,
             DAQmx_Val_GroupByScanNumber,  // interleaved
             data,
             data_size,
             &samps_per_chan_read,
             NULL);
        if (result != 0)
        {
            printf ("Failure in DAQmxReadAnalogF64\n");
            CleanupTask (&handle);
            CheckNidaqError (result);
        }
        // clean up
        CleanupTask (&handle);
        // success
        rtn = true;
    }
    catch (Nidaq_Exception)
    {
        // failed
        rtn = false;
    }
    return rtn;
}

void NiTest (int count)
{
    int num_ok  = 0;
    int num_bad = 0;
    for (int i=0; i < count; i++)
    {
        bool ok = Test_AD_Collect ();
        if (ok)
        {
            num_ok += 1;
        }
        else
        {
            num_bad += 1;
        }
    }
    printf ("A/D Test: Did %d collections, %d ok, %d errors.\n", count, num_ok, num_bad);
}

int main (int argc, char* argv[])
{
    //NiTest (50);
    NiTest (500);
    return 0;
}

0 Kudos
Message 12 of 13
(3,140 Views)

Ok, I have found my problem 🙂

 

First, I was not calling StartTask before I started to read data. I had somehow thought that was optional, but omitting it seems to make the 200010 warning much more likely, at least on this system.

 

Second, I was not handling errors properly. First, I somewhat treated the 200010 warning as an error, trying to abort and clean up the task when this happened.

Then, (much worse), I then tried to clean up the task twice.  This invalid second cleanup generated an error code, -200080 I think, with the result that my program treated the results as an error.

 

With these fixes, it seems that everything is working fine now.

 

 

0 Kudos
Message 13 of 13
(3,135 Views)