Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

Intermittent 200010 errors

I am getting intermittent error 200010 results from DAQmxReadAnalogF64(). We are using a PCI-6259 card.

 

My app is a C++ program, running under Windows 7. It does two main types of A/D reads: One is initiated by interactive user action, and can result in a large amount of  samples. The channel count is normally 1-3, while the sample time is user specified, and could be fairly large (e.g. a few hundred seconds.)

We try and sample at the highest rate the card supports (e.g. 1.25 MHz for 1 channel, or 1 MHz for 2 or 3 channels.) There is a maximum sample count

that we will try and read, currently 62.5 million samples, the size of our allocated data buffer, and if the user request exceeds this, we will drop the sample rate to fit this limit.

 

The second type of read is done periodically, c. 3 times per second, and reads for just 12.5 msec, typically for 6 channels or so. (This second provides a periodic update of the instrument state.) These second types read just 2084 samples total, at the full 1 MHz sample rate.

 

Anyways, the reads work most of the time, but occasionally fail. Failure seems most common when the first type of read is done for a long time period, say 120 sec. (By this point we would be reducing the sample frequency, assuming 1 channel, to about 520 kHz.) Interestingly, the failures then occur usually for the second type of sample (the short 12.5 msec reads), although they have occurred on the long reads (which are more critical.)

 

If I double our data buffer size to 1 GB, meaning we would read up to 125 million samples (and so maintain 1.25 MHz sample rate for longer times), then the errors become much more common.

 

I have just upgraded to NIDAQmx version 9.1, I had been using 8.9, but these errors persist with the upgrade. Previously, I had also had occasional errors 50352 [Memory allocation error], and error 50202 [Unspecified error], but I have not seen these since the upgrade. So the upgrade may have helped some, but not completely.

 

Thanks for any advice.

  - Mark

 

0 Kudos
Message 1 of 13
(8,915 Views)

Hi Mark,

 

I would look toward how many samples you are actually reading each iteration of the loop. The onboard memory for the PCI-6259 is 4095 samples.  If the data is not transferred across the PCI bus quickly enough, then the data in the FIFO is overwritten thus generating the buffer overflow error you are seeing.  Hopefully this helps!

Regards,


h_baker
National Instruments
Applications Engineer
0 Kudos
Message 2 of 13
(8,899 Views)

Thanks - I am not sure exactly what you mean, however.

Our large reads are made with one call to DAQmxReadAnalogF64(), with the number of samples requested possibly up to 50 million or so.

Our small reads (which are not attempted while the large ones are in progress), typically read 2084 samples each.

 

Would it perhaps be helpful to put a pause in the program after the large reads, to help it clean out things before asking for more?

 

- Mark

 

0 Kudos
Message 3 of 13
(8,891 Views)

Hi Mark,

 

I assumed you were doing a continuous acquisition; however, that does not sound like it is the case- my apologies.  Can you please post the DAQmx portion your code so I may see all of your configurations and calls to avoid any confusion?

Regards,


h_baker
National Instruments
Applications Engineer
0 Kudos
Message 4 of 13
(8,864 Views)

No problem - Here is an extract that has the important parts. The error handling is at the top.

ReadAnalogInterval () is the function we call for the real work.

(BTW - We do some other kinds of reads as well, i.e. some digital inputs, reading the A/D sensor temperature, writing analog voltages,

but the main work is done by ReadAnalogInterval().)

 

- Mark

 

OK, It seems that I have to post this in pieces to get this under the 10,000 character limit... So first I post the error handling code...

 

void RaiseNidaqError (int32 error_code)
// Check the NIDAQmx return code -
//   If 0, result was ok, no action is taken.
//   Else an error or warning occurred - A meaningful message string is composed, and an exception raised.
{
    if (error_code != 0)    // 0 means no error
    {
        // get error message
        string error_msg;
        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);
            // ensure the string is terminated
            if (result == 0)
            {
                error_msg = msg;
            }
            else
            {
                // failure getting error message - probably will never happen, but try and deal if it does
                char msgbuf [1024];
                safe_sprintf (msgbuf, countof (msgbuf), "Failed to get NIDAQ error message for error %d (second error %d).",
                    error_code, result);
                error_msg = msgbuf;
            }
            delete[] msg;
            msg = NULL;
        }

        // get extended error message
        string extended_error_msg;
        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);
            if (extended_result == 0)
            {
                extended_error_msg = extended_msg;
            }
            else
            {
                // failure getting extended error message
                char msgbuf [1024];
                safe_sprintf (msgbuf, countof (msgbuf),
                    "Failed to get NIDAQ extended error message for error %d (second error %d).",
                    error_code, extended_result);
                extended_error_msg = msgbuf;
            }
            delete[] extended_msg;
            extended_msg = NULL;
        }

        // if warning, just print a message.
        // if error, raise exception.
        if (error_code < 0)
        {
            // raise exception
            Nidaq_Error exc (error_code, error_msg, extended_error_msg);
            throw exc;
        }
        else
        {
            sf_print ("Nidaq Warning: %d : %s\n", error_code, error_msg.c_str());
        }
    }
}

void CleanupTask (TaskHandle* phandle)
// Clean up a partially-started task, in the event of an error.
{
    int32 result;
    // stop task
    result = DAQmxStopTask (*phandle);
    RaiseNidaqError (result);          // exception if we can't clean up
    // destroy task
    result = DAQmxClearTask (*phandle);
    RaiseNidaqError (result);          // exception if we can't clean up
    *phandle = 0;                      // clear handle value [not sure if this is the correct value]
}

0 Kudos
Message 5 of 13
(8,859 Views)

And now the main read function...

 

 void ReadAnalogInterval (
    const char* device_name,
    const char* physical_channels[],
    int    num_channels,
    int    num_samps_per_channel,
    double samp_freq_per_channel,
    double min_range,
    double max_range,
    double timeout_sec,
    bool   triggered,
    int    trigger_type,
    const char* trigger_source,
    Simulation simulants[],
    double data[],
    int    data_size)
// Sample data over an interval. The whole interval is sampled in one piece.
{
    int32 result;
    TaskHandle handle;
    result = DAQmxCreateTask (NULL, &handle);
    if (result != 0)
    {
        CleanupTask (&handle);
        RaiseNidaqError (result);
    }
    // combine channel names
    string physical_channels_combined =
        CombinePhysicalChannelNames (device_name, physical_channels, num_channels);
    // create channel for reading voltage
    result = DAQmxCreateAIVoltageChan
        (handle,
         physical_channels_combined.c_str(),
         NULL,
         DAQmx_Val_Cfg_Default,
         min_range,
         max_range,
         DAQmx_Val_Volts,        // units
         NULL);
    if (result != 0)
    {
        CleanupTask (&handle);
        RaiseNidaqError (result);
    }
    // get channel count
    uInt32 nidaq_num_channels;
    result = DAQmxGetTaskNumChans (handle, &nidaq_num_channels);
    if (result != 0)
    {
        CleanupTask (&handle);
        RaiseNidaqError (result);
    }
    // check
    assert (nidaq_num_channels == num_channels);
    assert (data_size == (num_samps_per_channel * num_channels));
    // configure trigger if requested
    if (triggered)
    {
        // trigger type
        int trigger_edge = 0;
        if (trigger_type == NIDAQ_TRIGGER_FALLING)
        {
            trigger_edge = DAQmx_Val_Falling;     // normal [VB TriggerType = 0]
        }
        else if (trigger_type == NIDAQ_TRIGGER_RISING)
        {
            trigger_edge = DAQmx_Val_Rising;      // [VB TriggerType = 1,3]
        }
        else
        {
            assert (0 && "Invalid trigger type.");
        }
        // configure trigger
        result = DAQmxCfgDigEdgeStartTrig
            (handle,
             trigger_source,
             trigger_edge);
        if (result != 0)
        {
            CleanupTask (&handle);
            RaiseNidaqError (result);
        }
    }
    else
    {
        assert (trigger_type == NIDAQ_TRIGGER_NONE);  // else set a trigger type when wanted no trigger
    }
    // 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)
    {
        CleanupTask (&handle);
        RaiseNidaqError (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 for some reason, not all samples are read, fill in the remainder with zeros.
    if (samps_per_chan_read != num_samps_per_channel)
    {
        sf_print ("A/D: Requested %d samples, but read %d instead. Remainder taken as 0.0.\n",
            num_samps_per_channel, samps_per_chan_read);
        for (int i=samps_per_chan_read; i < num_samps_per_channel; i++)
        {
            for (int j=0; j < num_channels; j++)
            {
                int index = (i * num_channels) + j;
                assert (index >= 0);
                assert (index < data_size);
                data [index] = 0.0;
            }
        }
    }
    if (result != 0)
    {
        CleanupTask (&handle);
        RaiseNidaqError (result);
    }
    // clean up
    CleanupTask (&handle);
    // leave all simulants in default state (implying no data).
}

0 Kudos
Message 6 of 13
(8,858 Views)

BTW - I think we get the 200010 error sometimes even when we have never done large reads yet, only the small 2084 sample ones (along with some digital reads, analog writes, and A/D temperature reads.) So I think we are never exceeding the buffer size you mentioned, and yet we still get errors.

 

- Mark

 

0 Kudos
Message 7 of 13
(8,856 Views)

I am getting a similiar error with a S series NI PCI-6110 board.

(Using a triggered start with external source for clocking in the data, across four channels with each channel reading 3100 data points, at rates of 1/2 -> 128 Hz; get the error from the 128Hz rate)

(DAQmxReadBinaryI16(g_thDataAcq, DAQmx_Val_Auto, 4 + g_dIntegrationTime, DAQmx_Val_GroupByScanNumber, g_ai16Buffer, 4 * 3100, &iSamplesRead, NULL)

 

Have you resolved the source of your intermittent errors?

0 Kudos
Message 8 of 13
(8,660 Views)

We have not completely resolved this. Adding more memory to my machine seemed to help, the errors are less common, but they can still happen.

 

0 Kudos
Message 9 of 13
(8,656 Views)

This problem is now happening very severely, on a new machine we just got.

 

Previously, this 200010 error was fairly rare, and so we were able to get by with it happening sometimes. On this new PC, however, the error happens about half the time, which makes our app unusable.

I have NIDAQmx version 9.2.2 installed, the same error occurred similarly with a 9.0 version as well.

 

 

 

0 Kudos
Message 10 of 13
(7,541 Views)