Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

Double buffer manipulation

Solved!
Go to solution

Hello? My system is using a double buffer based code and I have to use them. I tested a stand alone DAQmx program dealing with a double buffer technique and it is working pretty much fine with my system. Since I am not only one wrote my system c++ code since 1980s, I'm not sure how to manipulate the DAQmx double buffer system.

 

Here is my old c++ code dealing with a double buffer code to display on a graph.

 

I attached these codes and the last one is DAQmx code and there are error points; //<******************** Error occurs here. 

The rest of them is old c++ and EvenBank and OddBank are representing double buffers. Their types are

 

double* EvenBank; double* OddBank;

 


 

and these are manipulated/initialized in this way later

 

EvenBank = new double[ iTotalSize ]; //iTotalSize = 7200 OddBank = new double[ iTotalSize ]; int i; for( i= 0; i< iTotalSize; i++ ) EvenBank[ i ] = OddBank[ i ] = 0;

 

 

Then the thread function attached in here. I don't have any idea how to assign the acquired sample to even and odd bank to display them in the graph.

 

Thanks for help.

 

1.Thread display:

 

unsigned int ThreadDisplay( LPVOID pParams ) { static unsigned long count = 1; static unsigned long traceNum = 1; CNatAcqView* ptr = (CNatAcqView*) pParams; if( traceNum %2 ) { traceNum = 1; //reset counter ptr->StartEvenIntScanATD(); if( ptr->WriteEnable ) ptr->WriteToDisplayBuffer( FALSE ); // ODD, Calling startScan() } else { ptr->StartOddIntScanATD(); if( ptr->WriteEnable ) ptr->WriteToDisplayBuffer( TRUE ); // EVEN, Calling startScan() } ptr->WriteEnable = TRUE; Check_Daq( ptr, ptr->iTotalSize ); // wait till end of signal window traceNum++; Sleep( 50 ); //minimum for checking keys and menu bars ptr->PostMessage( WM_DISPLAY_BUFFER, count, (long)0 ); // if done exit ,else restart... AfxEndThread( 0 ); return 0; }

 

 2. Display data on the screen:

 

int CNatAcqView::WriteToDisplayBuffer( bool even ) { int i,j; for( i= 0; i< iChannel_Acq; i++ ) //display buffer depends on IRIS model { for( j= 0; j< fdat.trace_size; j++) { if( even ) { if( gd.ch[i].active == 1 ) gd.ch[ i ].iatd[ j ] = EvenBank[ i + j*iChannel_Acq ]; //iChannel_Acq = 6 else gd.ch[i].iatd[j] = 0; } else { if( gd.ch[i].active == 1 ) gd.ch[ i ].iatd[ j ] = OddBank[ i + j*iChannel_Acq ]; else gd.ch[i].iatd[j] = 0; } } } //PreProcessing for ( i= 0; i< MAX_RADARS; i++ ) { //if( i < 4 ) //for BatteryLevel //{ if( processFlag == 1 && gd.ch[i].active == 1 ) AcqPoll_ProcessSignal( i ); //} } for( i= 0; i< iChannel_Acq; i++ ) //MAX_CHANN { if( gd.ch[i].active == 1 ) { for( j= 0; j< fdat.trace_size; j++ ) iAveBuffer[i][j] = iAveBuffer[i][j] + gd.ch[i].iatd[j]; //average calculation, not important } } if( SampleTimeFlag != 1 ) { for( i= 0; i< MAX_RADARS; i++ ) { gd.ch[i].blength = fdat.trace_size; gd.ch[i].sampleTime = .000001 * fdat.period * fdat.its[i]; // display text info on a screen if( i >= IRIS_SYSTEM ) gd.ch[i].sampleTime = fdat.period; } } else //if( SampleTimeFlag == 1 ) { for( i= 0; i< MAX_RADARS; i++ ) { gd.ch[i].sampleTime = fdat.period; gd.ch[i].blength = fdat.trace_size; } } return 1; }

 

3. Check_Daq:

 

BOOL Check_Daq( LPVOID pParams, int expect) // int expect is a total size of the sample buffer. { short done; unsigned long number = 0; int status; status = DAQ_Check( 1, &done, &number ); CNatAcqView* ptr = (CNatAcqView*)pParams; AfxMessageBox("Check_Daq is called", MB_OK, 0); ptr->bAbortAcquire = FALSE; ptr->bRadarTrigger = TRUE; ptr->iTriggerLED = 1; //Trigger On int i=0; while( done != 1 ) { status = DAQ_Check( 1, &done, &number ); ptr->bRadarTrigger = FALSE; ptr->uiTriggerCheck++; //protect overflow data type if( ptr->uiTriggerCheck >= MAX_DMI_COUNT ) ptr->uiTriggerCheck = 0; if( ptr->bAbortAcquire ) //from OnAcquire Mode done = 1; } ptr->uiTriggerCheck = 0; if( number == (unsigned long) expect ) return TRUE; else { //throw ERROR_DAQ_CHECK; return FALSE; } }

 

 4. DAQmx conversion:

 

//I will comment out Check_Daq() in ThreadDisplay function. Then this whole single function will be called. unsigned int CollectingSamples(LPVOID pParams) { CNatAcqView* ptr = (CNatAcqView*) pParams; int32 error=0; char errBuff[2048]={'\0'}; double gainValue = 0.5f; uInt32 numChannels; uInt32 reading=0; static bool32 isDone; ptr->totalRead = 0; unsigned long HalfSize = (unsigned long)ptr->iTotalSize/2; double DataBuffer[1000]; int32 read; //TaskHandle taskHandle = ptr->taskHandle; TaskHandle taskHandle=0; ptr->dataA =0; DAQmxErrChk (DAQmxCreateTask("",&taskHandle)); DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0:5","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL)); DAQmxErrChk (DAQmxSetAIGain(taskHandle, "Dev1/ai0:5", gainValue)); // buffer(14400) setting with internal clock("") and continuous sampling(DAQmx_Val_ContSamps), DAQmx does double buffering basically in case of continuous sampling. DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",40000,DAQmx_Val_Rising,DAQmx_Val_ContSamps,14400)); //14400 = iTotalSize x 2; double buffer. //DAQmxErrChk (DAQmxSetAIConvTimebaseDiv(taskHandle, (int)iSampInt*10));//sampleTicks*10 was 500 //iSampInt*10 //DAQmxErrChk (DAQmxSetSampClkTimebaseDiv(taskHandle, (int)iScanInt*10));//GroupTicks*10 was 2000 //iScanInt*10 //double buffer acquisition; the board transfers data when half its internal buffer is full DAQmxErrChk (DAQmxSetAIDataXferReqCond(taskHandle, "Dev1/ai0:5", DAQmx_Val_OnBrdMemMoreThanHalfFull)); //Overwriting samples in the buffer that you have not yet read. DAQmxErrChk (DAQmxSetReadOverWrite(taskHandle, DAQmx_Val_DoNotOverwriteUnreadSamps)); //Collecting data from buffer //DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle,DAQmx_Val_Acquired_Into_Buffer,10,0,AcquireCallBack,NULL)); // call back result DAQmxErrChk (DAQmxStartTask(taskHandle)); while (!isDone) { ptr->IsTaskDone_ContAcqIntClkDigStartRef(taskHandle, &isDone); //DAQmxErrChk( DAQmxIsTaskDone(staskHandle, isDone)); DAQmxErrChk (DAQmxGetReadAvailSampPerChan(taskHandle,&reading)); if( reading>0 ) { // Each reading DAQmxErrChk (DAQmxGetReadTotalSampPerChanAcquired(taskHandle, &ptr->dataA)); //Accumulated reading while(reading > HalfSize ){ //More than a half full DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,-1,10.0,DAQmx_Val_GroupByScanNumber,DataBuffer,1000,&read,NULL)); //Read the buffer ptr->totalRead+=read; if( ptr->totalRead == ptr->iTotalSize || ptr->totalRead > ptr->iTotalSize ) { if(ptr->iAvailableSample == 2){ //ptr->EvenBank=DataBuffer; //<******************** Error occurs here return ptr->iAvailableSample == 1; } else if(ptr->iAvailableSample == 1){ //ptr->OddBank=DataBuffer; //<******************** Error occurs here, too. return ptr->iAvailableSample == 2; } isDone = 1; //Stop }//End of if( ptr->totalRead == ptr->iTotalSize || ptr->totalRead > ptr->iTotalSize ) }//End of while(reading > HalfSize ) }//Enf of if(reading>0) }// while (!isDone) AfxEndThread( 0 ); DAQmxErrChk (DAQmxStopTask(taskHandle)); DAQmxErrChk (DAQmxClearTask(taskHandle)); Error: if(error) CleanUp (error, taskHandle); }

 

 

 

 

 

 

 

I'm converting DAQ to DAQmx..from Parkoz.com
0 Kudos
Message 1 of 2
(6,718 Views)
Solution
Accepted by topic author anarkie

OK, I figured out why it is not displaying the right data. The data type of even and odd bank must be short* and DAQmx AI function should be

 

DAQmxReadBinaryI16, not DAQmxReadAnalogF64. Now it is working fine.

 

So, if anyone of you convert DAQ function SCAN_Start to DAQmx, please use DAQmxReadBinaryI16, not DAQmxReadAnalogF64.

Because the return data type of SCAN_Start is i16 ( integer 16bit. short*), you must use DAQmxReadBinaryI16.

 

Otherwise you will lose many data points.

 

 

Message Edited by anarkie on 07-16-2009 07:56 AM
I'm converting DAQ to DAQmx..from Parkoz.com
0 Kudos
Message 2 of 2
(6,703 Views)