LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

multiple task analog input call back

The code shown below is a callback for 1 to 3 analog input tasks.  Why would is throw a random error of "Array argument too small" on the second task's DAQmxReadAnalogF64 call?  Is this the best way to handle continous data from multiple tasks?  This is the way I do it in VB.NET/Measurement Studio.

 

int32 CVICALLBACK AIDataReady(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
	int32   error=0;
	char    errBuff[2048]={'\0'};
	int     numRead;

	// Read DAQmx data
	if (taskHandle == ai0TaskHandle)
		DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,nSamples,10.0,DAQmx_Val_GroupByChannel,aiTask0RawData,nSamples*numTask0Channels,&numRead,NULL));
	else if (taskHandle == ai1TaskHandle)
		DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,nSamples,10.0,DAQmx_Val_GroupByChannel,aiTask1RawData,nSamples*numTask1Channels,&numRead,NULL));
	else if (taskHandle == ai2TaskHandle)
		DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,nSamples,10.0,DAQmx_Val_GroupByChannel,aiTask2RawData,nSamples*numTask2Channels,&numRead,NULL));

	// Call function calculate engineering units from raw voltages
	DAQCalculateAverages(); 
	
Error:
	if( DAQmxFailed(error) ) 
	{
		DAQmxGetExtendedErrorInfo(errBuff,2048);
		/*********************************************/
		/*/ DAQmx Stop Code
		/*********************************************/
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
		ai0TaskHandle = 0;
		if(aiRawData) 
		{
			free(aiRawData);
			aiRawData = NULL;
		}
	}   
	return 0;
}
Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 1 of 12
(5,200 Views)

Hi Michael,

 

What have you defined as aiTask1RawData? The "Array argument too small" error code should specify the number of array elements required. 

Julia P.
0 Kudos
Message 2 of 12
(5,160 Views)

They are global variables.  The error is completely random.  It can work for 5 minutes, or last night it ran all the way through with no issues.  It is always on the second task.  The error box does tell me how many bytes it is expecting and how many it gets.  Why would it work most of the time and then fail to return the proper number of bytes?  The chassis is an older 9178 cDAQ chassis (white, not grey).

 

static float64        *aiTask0RawData=NULL;   
static float64        *aiTask1RawData=NULL;   
static float64        *aiTask2RawData=NULL;

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 3 of 12
(5,138 Views)

Here is the error it throws.  The number of bytes received is random.

 

Error.jpg

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 4 of 12
(5,128 Views)

Michael,

 

Have you tried reallocating memory to aiTask1RawData before reading data to ensure that there are at least nSamples*numTask1Channels elements in the buffer?

Julia P.
0 Kudos
Message 5 of 12
(5,100 Views)

Does this error mean that the array is too small or that the amount of data going into it is too little?

 

If the array is too small, how it is changing sizes at run time when I set it up to be as large as it needs to be at the beginning of execution and leave it alone the rest of the time?

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 6 of 12
(5,077 Views)

What do you set the array length as?

Is it fixed, or dynamic?

 

The behaviour you describe suggests a race condition. Is it possible for AIDataReady to be called for ai1TaskHandle when AIDataReady is actually executing ai0TaskHandle already?

0 Kudos
Message 7 of 12
(5,064 Views)

This is how the array is built.  lastTask is just a task count.  If there is one task, it will be and the loop will iterate only once.

 

for (ctrChannels = 0; ctrChannels < lastTask; ctrChannels++)
	{
		switch (ctrChannels)
		{
			case 0:
				TempTaskHandle = ai0TaskHandle;
				numTempTaskChannels = numTask0Channels;
				aiTask0RawData=malloc(DAQNumSamples*numTask0Channels*sizeof(float64));			
				break;
			case 1:
				TempTaskHandle = ai1TaskHandle;
				numTempTaskChannels = numTask1Channels;
				aiTask1RawData=malloc(DAQNumSamples*numTask1Channels*sizeof(float64));	
				break;
			case 2:
				TempTaskHandle = ai2TaskHandle;
				numTempTaskChannels = numTask2Channels;
				aiTask0RawData=malloc(DAQNumSamples*numTask2Channels*sizeof(float64));	
				break;
			default:
				break;
		}		
	
		DAQmxErrChk (DAQmxCfgSampClkTiming(TempTaskHandle,"",1000,DAQmx_Val_Rising,DAQmx_Val_ContSamps,DAQNumSamples));
		//DAQmxErrChk (DAQmxSetChanAttribute(ai0TaskHandle,"",DAQmx_AI_Lowpass_Enable,1));
		//DAQmxErrChk (DAQmxSetChanAttribute(ai0TaskHandle,"",DAQmx_AI_Lowpass_CutoffFreq,cutoffFreq));
		//DAQmxErrChk (DAQmxGetChanAttribute(ai0TaskHandle,"",DAQmx_AI_Lowpass_CutoffFreq,&cutoffFreq));
		DAQmxErrChk (DAQmxGetTaskAttribute(TempTaskHandle,DAQmx_Task_NumChans,&numTempTaskChannels));

		DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(TempTaskHandle,DAQmx_Val_Acquired_Into_Buffer,DAQNumSamples,0,AIDataReady,NULL));
		DAQmxErrChk (DAQmxRegisterDoneEvent(TempTaskHandle,0,AIDataStop,NULL));
	
		/*********************************************/
		// DAQmx AI Start Code
		/*********************************************/
		DAQmxErrChk (DAQmxStartTask(TempTaskHandle));
	}

This is how the data is read to generate an average value for each channel (100 readings @ 1 kHz).  It is possible that the pointer is not being reset to the beginning of the array (last line of this code), but I don't understand the random nature.

 

	if (numTask1Channels)
	{
		for (indexChannel = numTask0Channels; indexChannel < (numTask0Channels + numTask1Channels);indexChannel++)
		{
			
			Sum = 0;
			for (indexSample = 0; indexSample < DAQNumSamples; indexSample++)
			{
				Sum += *aiTask1RawData++;
			}
		
			// Average value -> Raw data
			DAQAIRawData[indexChannel] = Sum / DAQNumSamples;

			// Raw data -> Engineering units
			if (!IsInfinity(DAQAIRawData[indexChannel]))			
				DAQAIEngrUnits[indexChannel] = DAQAIChannels[indexChannel]->Quartic * pow(DAQAIRawData[indexChannel], 4) + 
					DAQAIChannels[indexChannel]->Cubic * pow(DAQAIRawData[indexChannel], 3) +
					DAQAIChannels[indexChannel]->Quadratic * pow(DAQAIRawData[indexChannel], 2) +
					DAQAIChannels[indexChannel]->Linear * DAQAIRawData[indexChannel] + DAQAIChannels[indexChannel]->Offset;
			else
				DAQAIEngrUnits[indexChannel] = DAQAIRawData[indexChannel];  				
		}
		
		// Reset aiTask1RawData pointer back to its original location
		aiTask1RawData -= DAQNumSamples * numTask1Channels;
	}

I am using the task handle to select which array to work with.  The call back should send the proper task handle.

 

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 8 of 12
(5,057 Views)

Is there an obvious error in this code:

 

switch (ctrChannels)
		{
			case 0:
				TempTaskHandle = ai0TaskHandle;
				numTempTaskChannels = numTask0Channels;
				aiTask0RawData=malloc(DAQNumSamples*numTask0Channels*sizeof(float64));			
				break;
			case 1:
				TempTaskHandle = ai1TaskHandle;
				numTempTaskChannels = numTask1Channels;
				aiTask1RawData=malloc(DAQNumSamples*numTask1Channels*sizeof(float64));	
				break;
			case 2:
				TempTaskHandle = ai2TaskHandle;
				numTempTaskChannels = numTask2Channels;
				aiTask0RawData=malloc(DAQNumSamples*numTask2Channels*sizeof(float64));	
				break;
			default:
				break;
		}		

In case 2, shouldn't aiTask0RawData be aiTask2RawData ?

 

But it does seem to me that the DAQmxEveryNSamplesEvent, say for ai1Task can happen at the instant when AIDataReady is processing the DAQmxEveryNSamplesEvent for ai0Task. I do not know whether in this instance LabWindows queues the callbacks, or trys a reentrent call to AIDataReady.

 

 

 

0 Kudos
Message 9 of 12
(5,030 Views)

Good catch.  I don't have three tasks, so I didn't catch that myself.  I'll fix it now.

 

Should I have a separate callback function for each task?

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 10 of 12
(4,996 Views)