Digital I/O

cancel
Showing results for 
Search instead for 
Did you mean: 

real time output with varying buffers without delay using PCI-6534 and NIDAQmx

Hello. I am currently using PCI-6534 and NIDAQmx to contol piezo scanner.
The piezo scanner hase three axsis and interfaces with PCI-6534 card using 16bit digital form.
My question is how to alleviate the delay when continously outputting diffent buffers.
When I output varying buffer continously, there is about 25ms delay.
To show this, I generate same output buffer(4032 number,sine curve), output that buffer and input corresponding piezo scanner output in a while loop.
See attached figure and source code.
Is there anybody to know this problem and solution?
 

int _tmain(int argc, _TCHAR* argv[])
{
    int32       error=0;
    TaskHandle  taskHandle=0;   
    TaskHandle  taskHandle1=0;
    TaskHandle  taskHandle2=0;
    TaskHandle  InputTaskHandle=0;
    uInt32      numChannels;
    bool32      done=0;
    char        errBuff[2048]={'\0'};
    char        ch;
    int32  sampsRead,totalRead=0;
 
    int outputBufferSize = num_point*6;
    signed short *outputBuffer = new signed short[outputBufferSize];
    signed short *inputBuffer = new signed short[outputBufferSize];
   

    //For real time position data output and input
    //Firstly setting input port for continuous data input
    DAQmxErrChk (Configure_ReadDigPortExtClk("Dev1/port2:3","/Dev1/PFI3",outputBufferSize+100000000,&InputTaskHandle, &numChannels, outputBufferSize+100000000));
    DAQmxErrChk (Start_DigPortExtClk(InputTaskHandle));    
    //In while loop, position data can be out and in.
    while(1){
       
        //When key in 's', then stop scanning
        if(kbhit()){
            char ch = getch();
            if(ch=='s'){
                printf("Stop scanning\n");
                break;
            }
        }
        //real-time output buffer generation and send data to the NPoint controller.
        generate_buffer(outputBuffer);
        DAQmxErrChk (Configure_WriteDigPortExtClk("Dev1/port0:1","/Dev1/PFI2",outputBufferSize,&taskHandle1, &numChannels, outputBufferSize));
        DAQmxErrChk (Write_DigPortExtClk(taskHandle1,(uInt16*)outputBuffer,outputBufferSize));
        DAQmxErrChk (Start_DigPortExtClk(taskHandle1));
        DAQmxErrChk (Wait_DigPortExtClk(taskHandle1));
        /////////////////////////////////////////////////////////////////////////////      
     
        //Continuous position data input
        DAQmxErrChk (Read_Cont_DigPortExtClk(InputTaskHandle, (uInt16*)inputBuffer, outputBufferSize, &sampsRead));      
        if( sampsRead>0 ) {
            totalRead += sampsRead;
            printf("Acquired %d samples. Total %d\r",sampsRead,totalRead);
            SaveInput(inputBuffer, sampsRead, inputData);
        }
        /////////////////////////////////////////////////////////////////////////////
       
        //For next position data output, stop output task and release reserved task handle
        if( taskHandle1!=0 )           
            Stop_DigPortExtClk(taskHandle1);
        /////////////////////////////////////////////////////////////////////////////
        Sleep(10);
    }
    printf("\nAcquired %d total samples.\n",totalRead);
   
    //Stop input task and release input task handle
    if( InputTaskHandle!=0 )
        Stop_DigPortExtClk(InputTaskHandle);
    /////////////////////////////////////////////////////////////////////////////
    
Error:
    if( DAQmxFailed(error) )
        DAQmxGetExtendedErrorInfo(errBuff,2048);
    if( DAQmxFailed(error) )
        printf("DAQmx Error: %s\n",errBuff);
    DAQmxErrChk (DAQmxResetDevice ("Dev1"));
    printf("End of program, press any key to quit\n");
    while( !_kbhit() ) {}
    ch = _getch();  
    return 0;
}
0 Kudos
Message 1 of 5
(4,486 Views)
Hi,

It looks like you're setting up your digital output task inside the while loop. Each time the while loop executes, it calls Configure_WriteDigPortExtClk, Write_DigPortExtClk, Start_DigPortExtClk, and Wait_DigPortExtClk. These look like custom functions that wrap the DAQmx API calls, so I can't really say much about them. If you could provide the function definitions, it would help me diagnose if that is where the problem lies.  Perhaps if you move some of the setup functions out of the while loop and place only the write functions inside, the delay will be removed. I would recommend starting with a shipping example to verify that your code follows the same techniques.  There is an example called Cont Write Dig Port-Ext Clk which should be installed in the following folder: "C:\Documents and Settings\All Users\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Digital\Generate Values\Cont Write Dig Port-Ext Clk\".  I believe this example would be a good starting point to verify that you're following the proper technique for continuous generation. Take a look at this example and let me know if you're having any trouble.

I would also like to mention that the 6534 also supports regeneration. Regeneration allows you to generate the same signal loaded into the buffer over and over without rewriting the same signal to the buffer.  You can find more information on the topic of regeneration in the DAQmx help manual.  This can be found by going to Start » Programs » National Instruments » NI-DAQ » DAQmx Help.  Once inside the help document you can find the regeneration topic by searching for "regeneration" or navigating to NI-DAQmx Key Concepts » Reading and Writing Data » Regeneration.
Joe Friedchicken
NI Configuration Based Software
Get with your fellow OS users
[ Linux ] [ macOS ]
Principal Software Engineer :: Configuration Based Software
Senior Software Engineer :: Multifunction Instruments Applications Group (until May 2018)
Software Engineer :: Measurements RLP Group (until Mar 2014)
Applications Engineer :: High Speed Product Group (until Sep 2008)
0 Kudos
Message 2 of 5
(4,467 Views)
Hello. These are the user defined functions used in my program.
There is some misunderstating for my question.
My program is about outputing position data that varies real time by user command.
I think that continous generation example you suggested is not proper for my application if there are no functions related to fast regeneration of buffer.
If you know about this, please describe it in detail of how to use using mx functions.
 
By the way, as you mentioned, Configure_WriteDigPortExtClk, Write_DigPortExtClk, Start_DigPortExtClk and Wait_DigPortExtClk functions in the while loop  makes noticeable delay. But if move port setup function out of the while loop and place the write, start and wait functions inside, some error messages is occured when writing new buffer on the card.  The error message is as follows. How can i solve this?
 
DAQmx Error: Measurements: Attempted to write a sample beyond the final sample g
enerated. The generation has stopped, therefore the sample specified by the comb
ination of position and offset will never be available.
Specify a position and offset which selects a sample up to, but not beyond, the
final sample generated. The final sample generated can be determined by querying
 the total samples generated after a generation has stopped.
Attempted to Write Sample: 2496
Property: DAQmx_Write_RelativeTo
Corresponding Value: DAQmx_Val_CurrWritePos
Property: DAQmx_Write_Offset
Corresponding Value:

Task Name: _unnamedTask<2>
Status Code: -200288

 

int32 Configure_WriteDigPortExtClk(const char chan[], const char clockSource[], float64 rate, TaskHandle *taskHandle, uInt32 *numChannels, uInt32 sampsPerChan)
{
    int32 error=0;
  
    /*********************************************************************
    *    1. Create a task.
    *    2. Create a Digital Output Channel.
    *    3. Call the DAQmxCfgSampClkTiming function which sets the sample
    *       clock rate. Additionally, set the sample mode to Finite.
    *********************************************************************/
    DAQmxErrChk (DAQmxCreateTask("",taskHandle));
    DAQmxErrChk (DAQmxCreateDOChan(*taskHandle,chan,"",DAQmx_Val_ChanForAllLines));
    DAQmxErrChk (DAQmxCfgSampClkTiming(*taskHandle,clockSource,rate,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,sampsPerChan));
    DAQmxErrChk (DAQmxCfgDigEdgeStartTrig(*taskHandle, "/Dev1/PFI6",DAQmx_Val_Falling));
    //DAQmxSetTrigAttribute (*taskHandle, DAQmx_StartTrig_Retriggerable, TRUE);
   
    if( numChannels )
        DAQmxErrChk (DAQmxGetTaskAttribute(*taskHandle,DAQmx_Task_NumChans,numChannels));
Error:
    return error;
}

int32 Configure_ReadDigPortExtClk(const char chan[], const char clockSource[], float64 rate, TaskHandle *taskHandle, uInt32 *numChannels, uInt32 sampsPerChan)
{
    int32 error=0;
    /*********************************************************************
    *    1. Create a task.
    *    2. Create a Digital Input Channel.
    *    3. Call the DAQmxCfgSampClkTiming function which sets the sample
    *       clock rate. Additionally, set the sample mode to Finite.
    *********************************************************************/
    DAQmxErrChk (DAQmxCreateTask("",taskHandle));
    DAQmxErrChk (DAQmxCreateDIChan(*taskHandle,chan,"",DAQmx_Val_ChanForAllLines));
    DAQmxErrChk (DAQmxCfgSampClkTiming(*taskHandle,clockSource,rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sampsPerChan));
    DAQmxErrChk (DAQmxCfgDigEdgeStartTrig(*taskHandle, "/Dev1/PFI7",DAQmx_Val_Falling));
   
    if( numChannels )
        DAQmxErrChk (DAQmxGetTaskAttribute(*taskHandle,DAQmx_Task_NumChans,numChannels));
Error:
    return error;
}

int32 Start_DigPortExtClk(TaskHandle taskHandle)
{
    /*********************************************************************
    *    3. Call the Start function to start the task.
    *********************************************************************/
    return DAQmxStartTask(taskHandle);
}

int32 Write_DigPortExtClk(TaskHandle taskHandle, uInt16 data[], uInt32 sampsPerChan)
{
    /*********************************************************************
    *    4. Write the waveform to the output buffer.
    *********************************************************************/
    return DAQmxWriteDigitalU16(taskHandle,sampsPerChan,0,5.0,DAQmx_Val_GroupByChannel,data,NULL,NULL);
}
int32 Read_Cont_DigPortExtClk(TaskHandle taskHandle, uInt16 *data, uInt32 bufferSize, int32 *read)
{
    /*********************************************************************
    *    4. Write the waveform to the output buffer.
    *********************************************************************/
    return DAQmxReadDigitalU16(taskHandle,bufferSize,10.0,DAQmx_Val_GroupByScanNumber,data,bufferSize,read,NULL);
}
int32 Wait_DigPortExtClk(TaskHandle taskHandle)
{
    return DAQmxWaitUntilTaskDone(taskHandle,10.0);
}
 
int32 Stop_DigPortExtClk(TaskHandle taskHandle)
{
    int32 error = 0;
    /*********************************************************************
    *    5. Call the Clear Task function to clear the Task.
    *********************************************************************/
   
    error = DAQmxStopTask(taskHandle);
    DAQmxClearTask(taskHandle);
    return error;
}
0 Kudos
Message 3 of 5
(4,414 Views)
Hi sunuk,

Error 200288 often results from analog output operations that have been set up for software re-triggering. In Traditional NI-DAQ, you only need to call the start command to re-enable the trigger. In NI-DAQmx, you must call DAQmx Stop Task after a read (analog input) or write (analog output) operation before re-enabling the triggers. As in Traditional NI-DAQ, the start (DAQmx Start Task) command re-enables the trigger.

The only other reference I found to error -200288 when writing to the PCI-6534 was the following discussion forum post:

PXI-6534 rewriting IO buffer with DAQmx causes error -200288

Hope this helps.
Jared T.
0 Kudos
Message 4 of 5
(4,388 Views)
Really good!. This is what I want to find out.
Thanks.
0 Kudos
Message 5 of 5
(4,375 Views)