LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

DAQmxWriteAnalogF64 - Repeat a buffer n times

Solved!
Go to solution

Hi All

I am writing a CVI 2015 app and I wish to use DaqMx (PCI 4661) to repeat the transmission of a buffer a number of times until completion.

I believe that I need to use a DAQmxRegisterEveryNSamplesEvent to call me back when the buffer is partially transmitted (half complete in my case) and top up the buffer with the next set of samples.


I can start the output, get the callback at the correct time and I can add the next set of sample data. The problem that I am seeing is that if I set the DAQmxCfgSampClkTiming parameter "sampleMode" to DAQmx_Val_ContSamps it replays the initial set of samples continually. If I set the sampleMode parameter to DAQmx_Val_FiniteSamps then it only plays the sample once and stops.

Would anybody please be able to guide me to the correct use of this function.

Thanks


My code look like the following (error checking removed for simplicity).

 

void DaqMxInit()
{
    DAQmxCreateTask("",&gTaskHandle);
    DAQmxCreateAOVoltageChan(gTaskHandle, "Dev1/ao0", "", -10.0, 10.0, DAQmx_Val_Volts, NULL);
    DAQmxCreateAOVoltageChan(gTaskHandle, "Dev1/ao1", "", -10.0, 10.0, DAQmx_Val_Volts, NULL);
}


void StartOutput(DataSampleSet_t* pSampleSet)
{
    DAQmxSetTimingAttribute(gTaskHandle, DAQmx_SampClk_Rate, pSampleSet->SampleClockRate);
    DAQmxGetTimingAttribute(gTaskHandle, DAQmx_SampClk_Rate, &resultingSampClkRate); 
    DAQmxCfgSampClkTiming(gTaskHandle,"", resultingSampClkRate, DAQmx_Val_Rising, /*DAQmx_Val_ContSamps*/DAQmx_Val_FiniteSamps, pSampleSet->SamplesPerChannel);

    DAQmxRegisterEveryNSamplesEvent(gTaskHandle, DAQmx_Val_Transferred_From_Buffer, (pSampleSet->SamplesPerChannel / 2), 0, DoneCallback, (void*)pSampleSet)

    DAQmxWriteAnalogF64(gTaskHandle, pSampleSet->SamplesPerChannel ,0, 10.0, DAQmx_Val_GroupByScanNumber, pSampleSet->pSamples, &written, NULL);

    DAQmxStartTask(gTaskHandle);  
}


int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
int32_t written;

    DataSampleSet_t* pSampleSet = (DataSampleSet_t*)callbackData;
    DAQmxWriteAnalogF64(gTaskHandle, pSampleSet->SamplesPerChannel / 2,0, 10.0, DAQmx_Val_GroupByScanNumber, pSampleSet->pSamples, &written, NULL);
    return 0;  
}

0 Kudos
Message 1 of 5
(3,648 Views)

Hi Stephen

 

The Done Callback should only get called when the task is complete- you should be using the  DAQmxRegisterEveryNSamplesEvent callback to continuously write to the buffer.

 

Essentially use the EveryNSamplesEvent to call WriteAnalogF64 and keep writing to the buffer every so many samples to achieve continuous.

 

I have include some links below which you may also find useful;

 

https://forums.ni.com/t5/LabWindows-CVI/DAQmx-DAQmxRegisterEveryNSamplesEvent-when-is-called/td-p/32...

https://forums.ni.com/t5/Measurement-Studio-for-VB6/DAQmxRegisterEveryNSamplesEvent-used-correctly/t...

 

I hope this helps!

 

Thanks

 

Sarah

Message 2 of 5
(3,591 Views)
Solution
Accepted by topic author StephenPinfold

Hi Sarah

Thanks for the answer. I will have a good look and hopefully it shall all become clear.

Steve

0 Kudos
Message 3 of 5
(3,584 Views)

Thanks, again.

I now understand how the functionality works. and can implement a solution that I think will provide seemless repeat of a waveform.

 

For those reading this post, I think that this is the solution

 

I needed to set the timing to continous samples and the NSamples event to the buffer size that I was passing to the write. The reload callback is called every time the buffer dries up. I am not sure on the time between the one buffer finishing and the new buffer starting.

 

void Setup()

{

DAQmxSetTimingAttribute(gTaskHandle, DAQmx_SampClk_Rate, SampleClockRate);
DAQmxGetTimingAttribute(gTaskHandle, DAQmx_SampClk_Rate, &resultingSampClkRate);
DAQmxCfgSampClkTiming(gTaskHandle, "", resultingSampClkRate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, SamplesPerChannel);
DAQmxRegisterEveryNSamplesEvent(gTaskHandle, DAQmx_Val_Transferred_From_Buffer, SamplesPerChannel, 0, ReloadCallback, (void*)pSampleSet);

// start the data write
DAQmxWriteAnalogF64(gTaskHandle, SamplesPerChannel, 0, 10.0, DAQmx_Val_GroupByScanNumber, pSamples, &written, NULL);
DAQmxStartTask(gTaskHandle);   
}


static int32 CVICALLBACK ReloadCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
int32_t result;
int32  written;

    if(count > 0)
    {
        DataSampleSet_t* pSamples = (DataSampleSet_t*)callbackData;
        DAQmxWriteAnalogF64(gTaskHandle, SamplesPerChannel, 0, 10.0, DAQmx_Val_GroupByScanNumber, pSamples, &written, NULL);
        count--;
    }
    else
    {
        DataGenNiDaqStop();
    }

0 Kudos
Message 4 of 5
(3,575 Views)

I would say initially start the task with a buffer size of 2000 and 2000 samples are configured

Then everynsamples write 1000 samples (this example assumes a sample rate of 1000S/s)

that way we are always 1 second ahead of the generation and ensure the buffer doesn't run out.

 

I hope that helps

 

Thanks

Sarah

0 Kudos
Message 5 of 5
(3,567 Views)