Multifunction DAQ

Showing results for 
Search instead for 
Did you mean: 

Steps to make digital channel a sampling clock




I am new to NIDAQ. We have a requirement to synchronize a voltage ramping sequence with a camera/ frame grabber.


We plan to use Dev1/PFI0 as the digital channel to synchronize the the ramp sequence with the frame grabber.


The sampling rate of voltage ramp is 2500 Hz.   Can you confirm whether the following steps are correct to make the digital channel as the clock source?


1. Generate 5000 values per second - 1,0,1,0.......1,0

2. Write them to the digital channel at the sampling rate 5000.


Will the following code generate the clock as per my requirement?


DAQmxCreateTask("", &taskHandle);
DAQmxCreateDOChan(taskHandle, "/Dev1/PFI4", "", DAQmx_Val_ChanForAllLines);
DAQmxCfgBurstHandshakingTimingExportClock(taskHandle, DAQmx_Val_ContSamps, 5000, 5000, "/Dev1/PFI4", DAQmx_Val_ActiveHigh, DAQmx_Val_Low, DAQmx_Val_ActiveHigh);
uInt32      data[5000];
for (int i = 0; i < 5000; ++i)
	data[i] = (i + 1) % 2;
DAQmxWriteDigitalU32(taskHandle, 5000, 0, 10.0, DAQmx_Val_GroupByChannel, data, NULL, NULL);

DAQmxWaitUntilTaskDone(oTask, 10.0);


I plan to use the following code to write the ramp values based on PFI0 as the clock source


DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxCreateAOVoltageChan(taskHandle,"Dev1/ao0","",-10.0,10.0,DAQmx_Val_Volts,NULL));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"PFI0",2500,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,2500));

DAQmxErrChk (DAQmxRegisterDoneEvent(taskHandle,0,DoneCallback,NULL));

// DAQmx Write Code
DAQmxErrChk (DAQmxWriteAnalogF64(taskHandle,2500,0,10.0,DAQmx_Val_GroupByChannel,data,NULL,NULL));


Please help me on this.

0 Kudos
Message 1 of 8

What DAQ device(s) are you using?


I only program in LabVIEW and don't know details of the text API.  That said, I'm almost certain you have 2 better alternatives than rapidly toggling a digital line.   (Also, the function call you make related to Burst Handshaking doesn't *seem* right to me, but I honestly can't say as it isn't a timing method I've used.)


There should be API functions for exporting timing signals out to PFI pins.  Then you can configure the AO task to generate its own sample clock internally and then export that sample clock out to PFI0.   No need for a DO task at all!


The other approach would be to generate a 2500 Hz pulse train output with a counter task and route it out to PFI0.  Then your AO task would use the PFI0 signal as its sample clock.  It's just that a counter pulse train is a much simpler task than the corresponding method that toggls a DO line repeatedly.


A couple further small issues I suspect in your code, but can't say for sure since I don't use the text API:

- "/Dev1/PFI4" probably won't work as a DO channel.  You'd probably need to use something more like "Dev1/port1/line0" (or whatever DIO port/line combination corresponds to the PFI pin of interest).

- It's unclear why you seem to try to designate PFI4 for DO and PFI0 for the AO sample clock.  Shouldn't you specify the same pin for both?  Or is there some physical wiring to connect them that you haven't mentioned before?

- The shortened designation "PFI0" probably won't work in your AO config.  It'll probably need to be something more like "/Dev1/PFI0".



-Kevin P

0 Kudos
Message 2 of 8

Hi Kevin,


Thank you very much for the detailed answer. The device that we use is 

NIDAQ PCIE-6321 X-series.


Can you answer the following queries?


Option1:Exporting timing signals out to PFI pins

  •  Can I get some sample code for this? 
  •  Can I assume that "DAQmxExportSignal" is the API to export the timing signal out to PFI Pins? NIDAQ SDK setup does not come with a sample usage of this API.

Option2: Pulse Train

The below API is the one which creates a pulse channel.

DAQmxCreateCOPulseChanFreq(taskHandle, "Dev1/ctr0", "", DAQmx_Val_Hz, DAQmx_Val_Low, 0.0, 1000, .25)

The last parameter for this method is dutyCycle. The NIDAQ documentation for this is "The width of the pulse divided by the pulse period. NI-DAQmx uses this ratio, combined with frequency, to determine pulse width and the interval between pulses".


What value should I give to dutyCycle, If I set the frequency of the pulse train as 2500 Hz?


I can see from NI MAX application that the pulse Terminal corresponding to "Dev1/ctr0" is "/Dev1/PFI12". 


Can I assume that "/Dev1/PFI12" can be used as the source terminal of the sampling clock for analog write? 


Thank you very much for all the answers which helped me to solve the problems.

0 Kudos
Message 3 of 8

RE: exporting the AO sample clock

DAQmxExportSignal certainly sounds like the right function, but I can only show what I'd do in LabVIEW.  Inputs are a task reference, an enumerated value to specify the signal to export, and a destination terminal to route it.   (Note: legal routes for a device can be found in MAX.  Your device is quite flexible so you won't have many limitations.  Older devices were significantly more limited.)

   Here I'm passing in a task ref for the AO task, specifying that I want to export the task's "Sample Clock" and route it out to "/Dev1/PFI0".  (This needs to be done before starting the task.)




This seems like it'd be the simplest method for you to use, so you shouldn't immediately need to generate a clock with a counter.  But for the sake of future reference, you can think of duty cycle as the fraction of time that the pulse is in high state.  Duty cycle will always need to be a value >0 and <1.  It can't be exactly 0 or 1, that would imply no pulsing behavior.

   It's pretty typical to set duty cycle at 0.5 unless there's a reason not to.  Then it'll look more like a typical square wave clock signal that spends 1/2 its time in high state and 1/2 in low state.


Legal signal routes can be found in MAX.  Select the device and there'll be a tab at the bottom called "Device Routes."   There's a grid of possible signal sources and destinations.  Combos that result in a green cell will always work.  Yellow cells *can* work, but might also result in errors if you have other tasks running on your device.  It gets complicated, so try to use green cell combos when possible.



-Kevin P


0 Kudos
Message 4 of 8

Hi Kevin,


Thanks for answering my clarifications. I have one more doubt about your statement


"Then you can configure the AO task to generate its own sample clock internally and then export that sample clock out to PFI0"


Will the following API call make the AO task to create its own sample clock, if I pass NULL("") to the source parameter (The sourceterminalof the Sample Clock) -- 2nd parameter?


DAQmxCfgSampClkTiming(taskHandle, "", 2500, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, arraySize)




Should I use any other API calls?


Thank you very much for all your response.




0 Kudos
Message 5 of 8

Again, I really don't know the text API, but passing "" (NULL) as the sample clock source parameter seems pretty plausible.


In the LabVIEW API, choosing not to wire in any value to the source parameter input results in the task making its own clock internally.  NULL seems fairly equivalent to me, but I really can't say for sure whether it'll work.  You'll have to try it.  (If you're away from your DAQ hardware, you can make a simulated device in MAX and at least check that the syntax is legal.)



-Kevin P

0 Kudos
Message 6 of 8

Hi Kevin,


Thanks for answering my question. We tried both options with the device.  Both options seems to be working.  


Re: Exporting the AO sample clock


We have written the code as you specified and the value of "/Dev1/PFIO" changes to 1 when the the task was started.  "/Dev1/PFIO" is wired to "Dev1/port0/line6". When we read digital value from "Dev1/port0/line6", the value remains always 1. It does not toggle between 1 and 0. 


Is that the expected behavior? 

How can we check whether the value toggles at "/Dev1/PFIO"?


The code used is given below.


DAQmxCreateTask(TaskName, &taskHandle);
DAQmxCreateAOVoltageChan(taskHandle, "Dev1/AO1", "", -3.25, 3.25, DAQmx_Val_Volts, nullptr);
DAQmxCfgSampClkTiming(taskHandle, "", 2500, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, arraySize);
DAQmxExportSignal(taskHandle, DAQmx_Val_SampleClock, "/Dev1/PFI0");
DAQmxWriteAnalogF64(taskHandle, arraySize, 0, 600, DAQmx_Val_GroupByChannel, data, &sampleswritten, nullptr);
DAQmxWaitUntilTaskDone(taskHandle, 600);


Thanks for all the help.




0 Kudos
Message 7 of 8

After a quick look in the manual, I was reminded that the AI sample clock signal is a very brief pulse rather than a square wave.  If you simply poll the value, you'd often miss the very brief time it pulses.


Instead, configure a counter task to count edges at PFI0.  It'll be able to catch those brief pulses so you can confirm that they're happening.



-Kevin P

0 Kudos
Message 8 of 8