Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Please help with C code to synchronize counter output to analog input

Hi All,

 

I am using NI DAQ USB-6353 with text-based C code to control it. I would like to send a continuous pulse train from the DAQ to pulse a power supply, which then activates an electron beam producing current to be read by the analog input port of the same DAQ. I would like to keep only the analog samples during the pulse peak and samples of a couple pulse widths right after. I am successfully to generate a pulse train using the sampled clock from a counter output channel, but fail to use the same clock to synchronize the pulse train with the analog input. DAQmxReadAnalogF64 is not called by the static function EveryNCallback set for the analog input task. Am I doing something wrong with the following codes? It would be great if it turns out only I am using the wrong sampled clock name of the counter ("dev1/PFI8") for the analog input. Or is something more fundamental that a counter cannot be sync. with an analog input?

 

Would someone be able to send me a link to an example in C or C++ or visual basic showing how to synchronize a buffered sample clocked digital pulse train from a counter output channel to an analog input? To simplify the post, the below codes do not include the static functions EveryNCallback and DoneCallBack, but I can send them if needed.

 

Many thanks in advance for your help,

Thuc Bui

 

//setting operation parameters

double initDelay = 0.0, freq = 10;

double dutyCycle = 0.0001;           //thus pulse width is 10 microsec

unsigned highTicks = 4;   //per period

unsigned numSamplesPerPeriod = highTicks / dutyCycle;   //40000 samples/period

unsigned lowTicks = numSamplesPerPeriod - highTicks;      //per period

unsigned sampleRate = 2*numSamplesPerPeriod*freq;       //800000 samples/s

//create counter

TaskHandle counterTask;

int errCode = DAQmxCreateTask("", & counterTask);

errCode = DAQmxCreateCOPulseChanFreq(counterTask, "dev1/ctr0", "",

                                 DAQmx_Val_Hz, DAQmx_Val_Low,

                                 initDelay, freq, dutyCycle);

errCode = DAQmxCfgSampClkTiming(counterTask, "dev1/PFI8", sampleRate, DAQmx_Val_Rising,

                           DAQmx_Val_ContSamp, numSamplesPerPeriod);

//create analog input

TaskHandle aiTask;

double minVolt = 0.0, maxVolt = 1.0;

errCode = DAQmxCreateAIVoltageChan(aiTask, "dev1/ai0", "", DAQmx_Val_Diff,

                                 minVolt, maxVolt, DAQmx_Val_Volts, "");

unsigned bufferSize = 10* numSamplesPerPeriod;

errCode = DAQmxSetBufInputBufSize(aiTask, bufferSize);

errCode = DAQmxCfgSampClkTiming(aiTask, "dev1/PFI8", sampleRate, DAQmx_Val_Rising, DAQmx_Val_ContSamp, numSamplesPerPeriod);

 

errCode = DAQmxRegisterEveryNSamplesEvent(aiTask, DAQmx_Val_Acquired_Into_Buffer,

                                        numSamplesPerPeriod, 0, EveryNCallback, 0);

errCode = DAQmxRegisterDoneEvent(aiTask, 0, DoneCallBack, 0)

 

//start aiTask first

errCode = DAQmxStartTask(aiTask);

//then counterTask

errCode = DAQmxStartTask(counterTask);

 

0 Kudos
Message 1 of 4
(6,183 Views)

Hi Thuc,

 

It is definitely possible to use a counter pulse generation output as an analog input sample clock. You will either need to use the counter output (for example, PFI12) and wire it onto another PFI line to use as a sample clock (you can't output on a PFI line and use that same line as a sample clock). Alternatively, you can use the internal counter output for the AI sample clock (for me it would be "/Dev1/Ctr0InternalOutput") which will internally route the correct pulse generation to your sample clock.

 

If this does not work, it would be helpful to see what type of errors you are getting using your current code. As far as examples, you have various types of built-in examples installed on the following directory: C:\Users\Public\Documents\National Instruments

 

Hope it helps!

Xavier
0 Kudos
Message 2 of 4
(6,158 Views)

Hi Xavier,

 

Thank you very much for getting back to me. I really appreciate it. I followed your advice with the option 2 and simplified my code by using one of the NI C example templates to generate the below codes (also attached). I was able to see the pulses generated with an oscilloscope, and on the same oscilloscope I could see the ouput pulses of the electron beam probe. Unfortunately, the below code via DAQmxReadAnalogF64 reports of no data read from the probe and finally times out. Below is the error message given by this function. I did check the connection of the analog input wires to make sure they were connected to pin 1 (A0+) and 2 (A0-) because I was using the terminal configuration DAQmx_Val_Diff. Do you see any obvious errors I have made in my codes?

 

Thanks a lot for your help,

Thuc Bui

 

**************************************************************************

Task started, waiting for trigger...

 

Acquired 0 analog samples DAQmx Error: Some or all of the samples requested have not yet been acquired.

 

To wait for the samples to become available use a longer read timeout or read later in your program. To make the samples available sooner, increase the sample rate. If your task uses a start trigger,  make sure that your start trigger is configured correctly. It is also possible that you configured the task for external timing, and no clock was supplied. If this is the case, supply an external clock.

 

Property: DAQmx_Read_RelativeTo

Corresponding Value: DAQmx_Val_CurrReadPos

Property: DAQmx_Read_Offset

Corresponding Value: 0

Task Name: _unnamedTask<1>

Status Code: -200284

End of program, press Enter key to quit

***********************************************************************************

 

********************** C Code **************************************************

#include <stdio.h>

#include "NIDAQmx.h"

#include <math.h>

#define DAQmxErrChk(functionCall) { if( DAQmxFailed(error=(functionCall)) ) { goto Error; } }

 

int main(void) {  

int32 error = 0;  

char errBuff[2048]={'\0'};

TaskHandle  taskHandleDig=0;  

TaskHandle taskHandleAna=0;    

double  timeout=10;  

double minVol = -1.0, maxVol = 1.0;

double initDelay = 0.0;  

double freq = 10.0;  

double pulseWidth = 1.0e-5; //10us  

double dutyCycle = pulseWidth * freq;

unsigned hiTicks = 4;  

double sampleRate = hiTicks/pulseWidth; //samples/s  

unsigned lowTicks = ceil(sampleRate/freq) - hiTicks;  

unsigned nSpPeriod = hiTicks + lowTicks;

unsigned numPulses = 1;  

unsigned nSpCh = numPulses*nSpPeriod;    

double sampleRate2 = ceil(2.0*sampleRate);  

unsigned sampleMode = DAQmx_Val_FiniteSamps;

 

 /*********************************************/  /*/ DAQmx Configure Code  /*********************************************/  

DAQmxErrChk(DAQmxCreateTask("", &taskHandleDig));  DAQmxErrChk(DAQmxCreateTask("", &taskHandleAna));    

 

DAQmxErrChk(DAQmxCreateAIVoltageChan(taskHandleAna, "Dev2/ai0", "", DAQmx_Val_Diff, minVol, maxVol, DAQmx_Val_Volts, ""));  

DAQmxErrChk(DAQmxCfgSampClkTiming(taskHandleAna, "/Dev2/Ctr0InternalOutput", sampleRate2, DAQmx_Val_Rising, sampleMode, nSpCh));

 

DAQmxErrChk(DAQmxCreateCOPulseChanFreq(taskHandleDig, "Dev2/ctr0", "", DAQmx_Val_Hz, DAQmx_Val_Low, initDelay, freq, dutyCycle));  

DAQmxErrChk(DAQmxCfgSampClkTiming(taskHandleDig, "/Dev2/PFI12", sampleRate2, DAQmx_Val_Rising, sampleMode, nSpCh));    

 

unsigned bufferSize = nSpCh;  

DAQmxErrChk(DAQmxSetBufInputBufSize(taskHandleAna, bufferSize));  

DAQmxErrChk(DAQmxSetBufOutputBufSize(taskHandleDig, bufferSize));

 

/*********************************************/  /*/ DAQmx Write Code  /*********************************************/  

DAQmxErrChk(DAQmxWriteCtrTicksScalar(taskHandleDig, 0, timeout, hiTicks, lowTicks, NULL));

 

/*********************************************/  /*/ DAQmx Start Code  /*********************************************/  

DAQmxErrChk(DAQmxStartTask(taskHandleAna));  DAQmxErrChk(DAQmxStartTask(taskHandleDig));

 

printf("Task started, waiting for trigger...\n");

 

/*********************************************/  /*/ DAQmx Read Code  /*********************************************/  

double* dataAna = new double[nSpCh];  

int32 numReadAna = 0;  

int errCode = DAQmxReadAnalogF64(taskHandleAna, -1, timeout, DAQmx_Val_GroupByChannel, dataAna, nSpCh, &numReadAna, NULL);  

printf("Acquired %d analog samples\n",numReadAna);  

if (numReadAna) {   

    unsigned nPts = (numReadAna < hiTicks)? numReadAna : hiTicks;  

    for (unsigned n = 0; n < nPts; ++n) {    

         printf("%6.3f ", dataAna[n]);   

    }   

    printf("\n");  

}  

 

delete [] dataAna;

DAQmxErrChk(errCode);

 

Error:  

if( DAQmxFailed(error) )   DAQmxGetExtendedErrorInfo(errBuff,2048);  

if( taskHandleDig!=0 && taskHandleAna!=0 ) {   

/*********************************************/   /*/ DAQmx Stop Code   /*********************************************/   

    DAQmxStopTask(taskHandleDig);   

    DAQmxClearTask(taskHandleDig);   

    DAQmxStopTask(taskHandleAna);   

    DAQmxClearTask(taskHandleAna);  

}  

if( DAQmxFailed(error) )   printf("DAQmx Error: %s\n",errBuff);  

printf("End of program, press Enter key to quit\n");  

getchar();  

return 0;

}

 

0 Kudos
Message 3 of 4
(6,153 Views)

Hi Thuc,

 

I couldn't find anything obvious in your code, except perhaps that you should start the Dig task before the AI task (since AI relies on the Dig counter output as a timing sample clock). Does that fix the error?

 

Would you be able to change the AI task's sample clock to the default AI Sample Clock, and see if you are able to run? If you are, then the timing will not be accurate but we will be able to pinpoint the source of the error to the sample clock.

 

Are you able to successfully run the built-in examples using known input signals, without interacting with a counter? This will check your hardware connection and make sure your AI is working properly.

Xavier
0 Kudos
Message 4 of 4
(6,130 Views)