LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

how to ignore DAQmx buffer overflow error

I have a (very large) data acquisition program written on LabWindows/CVI that acquires data from an e-series board and, among other things, graphs it onto an on-screen virtual o'scope. The setup uses external triggering and is set up as:

 

    DAQmxErrChk(DAQmxRegisterEveryNSamplesEvent (Level1_Task.DAQTask_Handle,
                                                 DAQmx_Val_Acquired_Into_Buffer,
                                                 PointsToAcq,
                                                 DAQmx_Val_SynchronousEventCallbacks,
//                                                 0, //non-synchronous event callback, called from DAQmx thread
                                                 CB_Level1_DataRdy, NULL));
    DAQmxErrChk(DAQmxRegisterDoneEvent (Level1_Task.DAQTask_Handle,
                                        DAQmx_Val_SynchronousEventCallbacks,
//                                        0, //non-synchronous event callback, called from DAQmx thread
                                        CB_Level1_DataDone, NULL));

 

and the callbacks look like:

 

//callback functions ==========================================================================
int32 CVICALLBACK CB_Level1_DataRdy (TaskHandle taskHandle,
                                     int32 everyNsamplesEventType,
                                     uInt32 nSamples,
                                     void *callbackData) {
    //called when the task has finished collecting the requested number of samples.

    //  Note: Param 6 wants the TOTAL number of samples, not the samples/channel.  Param 7, however is in samples/channel.
    DAQmxErrChk(DAQmxReadAnalogF64 (taskHandle, DAQmx_Val_Auto, 0,
                                    DAQmx_Val_GroupByChannel,
                                    Level1_Task.DataBuffer,
                                    Level1_Task.BufferSize, &samplesRead, 0));

    ... do stuff with data
    
    //done
Error:
    
     DAQHNDLR_HandleDAQmxError(DAQmxStatus, taskHandle); //does nothing if DAQmxStatus == 0;
    return (0);
}

int32 CVICALLBACK CB_Level1_DataDone (TaskHandle taskHandle, int32 DAQmxStatus_in, void *callbackData) {
    /* //from the help file for DAQmxRegisterDoneEvent ()
    The status parameter contains the status of the task when the event occurred.
    If the status value is negative, it indicates an error.
    If the status value is zero, it indicates no error.
    If the status value is positive, it indicates a warning.
    */

    Level1_Task.Running = FALSE;
    ChannelInfo[DAQ_RECEIVER].Running = FALSE;
    ChannelInfo[DAQ_POWER_METER].Running = FALSE;
    
    if (DAQmxStatus_in < 0) {
        DAQHNDLR_HandleDAQmxError(DAQmxStatus_in, taskHandle);
    }

Error:
    return (0);
}

I'm running the input data at a 30 Hz trigger rate (with an acquisition clock of 50 kHz and acquiring perhaps 1000 points/trigger) around , and the scheme works pretty well MOST of the time. However, if I open another window or otherwise do something that uses a bunch of CPU time I'll get a DAQmx "buffer overflow" error (-200222) because the computer is too busy to run the data handler, or can't get there quickly enough, or some such. This, of course, calls the CB_Level1_DataDone routine with the error and crashes the entire DAQmx task.

1) How can I properly handle the error in the CB_Level1_DataDone routine to clear and reset the acquisition so that it doesn't bring down the task? I don't normally care if I lose data at this point, since it's only going to the screen - during critical data acquistion periods I'll warn the user not to do anything to overload the CPU. I'd really like to tell the DAQmx task to simply ignore it entirely.

2) What are the benefits of handling the data "in the DAQmx thread", (the non-synchronous event callback option in DAQmxRegisterEveryNSamplesEvent)? I can't seem to find any advice on when to use and when to not use this option. I presume that if I do this that I have to use proper multi-threading methods to synchronize between the data handler and end user routines. 

0 Kudos
Message 1 of 10
(4,679 Views)

Passing that error code to DAQmxGetErrorString returns the following description which is quite self-explicative and offers some informations on how to avoid it:

 

Acquisition has been stopped to prevent an input buffer overwrite. Your application was unable to read samples from the buffer fast enough to prevent new samples from overwriting unread data.

To avoid this error, you can do any of the following:
1. Increase the size of the buffer.
2. Increase the number of samples you read each time you invoke a read operation.
3. Read samples more often.
4. Reduce the sample rate.
5. Change the data transfer mechanism from interrupts to DMA.
6. Reduce the number of applications your computer is running concurrently.

In addition, if you do not need to read every sample that is acquired, you can configure the overwrite mode to overwrite unread data, and then use the Relative To and Offset properties to read the desired samples.

If I were you, given that you are simply echoing some measure on the screen and int this case you can loose some data, I'd set the overwrite mode with

DAQmxSetReadAttribute (Level1_Task.DAQTask_Handle, DAQmx_Read_OverWrite, DAQmx_Val_OverwriteUnreadSamps);



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 10
(4,670 Views)

Yes, I get the error; I was hoping for some way to simply avoid getting it in the first place. I'll try the overwrite suggestion and see what happens.

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

The overwrite settings do exactly what you want: you'll loose some data but you'll get no error.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 4 of 10
(4,659 Views)

If I'm acquiring triggered data, (in this case 1000 points @ 50 kHz sample rate, 30 Hz trigger rate) will it properly start at the beginning of the buffer each time - so that it always overwrites an entire buffer? Or do I have to keep track of where things are?

0 Kudos
Message 5 of 10
(4,656 Views)

Um, now I get error -200279 in the data handler routine - "Trying to read samples already read....". when I call

 

    DAQmxErrChk(DAQmxReadAnalogF64 (taskHandle, DAQmx_Val_Auto, 0,
                                    DAQmx_Val_GroupByChannel,
                                    Level1_Task.DataBuffer,
                                    Level1_Task.BufferSize, &samplesRead, 0));

 

to read the data.  nSamples in the data handler parameters = 1000, like it's supposed to

 

Do I have to reset a read buffer pointer attribute somewhere?

0 Kudos
Message 6 of 10
(4,647 Views)

As of my understanding, unless you stop and restart the task data are added sequentially to the buffer up to its end, restarting from the beginning afterwards. In this scenario you should keep memory of the position in the buffer and read from there. Alternatively, there may be an option that configures the reading process so that it always reads the last samples acquired: I haven't CVI installed on this machine so I cannot verify this option,

 

Regarding your last error, it's not clear to me why you are receiving it: RegisterEveryNSamplesEvent should guarantee that you have new data to read when reading. Nevertheless, did you receive that error even if you replace DAQmx_Val_Auto with the correct number of samples to read?



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 7 of 10
(4,641 Views)

Yes, I got the same error when I replaced DAQmx_Val_Auto with the number of samples from the callback parameter, which I checked as being 1000 as it should be. That's what's puzzling: why is the callback getting called at all unless there are samples to read? 

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

Oh, and the buffer is sized to equal the number of samples to be read (in this case 2000: 2 channels x 1000 samples/channel), so it should always start at the beginning each time (and does when the system is working properly).

0 Kudos
Message 9 of 10
(4,632 Views)

I'm surprised that is what your error message said. This KB talks about how error is about samples being overwritten. Try increasing your buffer size and see if that resolves the error. For information about how to increase your buffer size, go here.

 

Rohama K.
0 Kudos
Message 10 of 10
(4,611 Views)