03-04-2009 06:51 PM
I have an externally-generated sampling signal and I need to count how many pulses occur between each edge of the sampling signal, where this count will very often be zero. This is similar to photon-counting applications that have been posted on this board, but I need to accomplish it using the C API (not Labview). I'm using an NI-6251 card and NI-DAQ 7.4.
From everything I've read I want to use Buffered Period Measurement (with Duplicate Count Prevention enabled), but I cannot get code to work for this.
For testing I have a 16 kHz pulse train wired to CTR0 GATE (PFI9) for my sampling signal and a 100 Hz pulse wired to CTR0 SRC (PFI8) to simulate my input that I need to count.
My code looks like this:
const int SamplesPerSecond = 16130;
float64 TimeoutSeconds = 20.0;
float64 Pulses[SamplesPerSecond] = {0};
TaskHandle CounterTaskHandle = 0;
DAQmxErrChk(DAQmxCreateTask("PulseCount_C", &CounterTaskHandle));
DAQmxErrChk(DAQmxCreateCIPeriodChan(CounterTaskHandle, // Task Handle
"Dev1/ctr0", // Counter
"", // Name to assign channel
0.00001, // Minimum expected value
100, // Maximum expected value
DAQmx_Val_Ticks, // Units
DAQmx_Val_Rising, // Edge to trigger on
DAQmx_Val_LowFreq1Ctr, // Measurement method
1, // Measurement time
4, // Divisor
"") // Custom scale name
);
DAQmxErrChk(DAQmxCfgImplicitTiming(CounterTaskHandle,
DAQmx_Val_ContSamps, // Acquire or generate samples until you stop the task.
SamplesPerSecond) // Samples per channel to aquire
);
DAQmxErrChk(DAQmxSetCIDupCountPrevent(CounterTaskHandle, "Dev1/ctr0", 1));
DAQmxErrChk(DAQmxStartTask(CounterTaskHandle));
// Loop over the next statement
DAQmxErrChk(DAQmxReadCounterF64(CounterTaskHandle, // Task handle to read data from
SamplesPerSecond, // The number of samples, per channel, to read
TimeoutSeconds, // timeout, in seconds
Pulses, // The array to read samples into
SamplesPerSecond, // Array size, in samples
&readD, // The actual number of samples read from each channel
0 // reserved
));
The ReadCounter call is blocking for 1 second as if everything is working, but the Pulses array contains all zeros.
(Oddly, if I remove the call to DAQmxSetCIDupCountPrevent() aquisition still takes 1 second but the values I get back are all 4960, plus or minus one. I have no idea where this number comes from, and it doesn't change if I increase the frequency of my data signal.)
I can pretty much get things working with edge counting mode, but I don't really want a cumulative count; period measurement should give me exactly what I want without any post-processing (or so the docs say).
Can anyone explain what I'm doing wrong?
03-05-2009 03:22 PM
Your gate is moving way to quickly at 16 kHz to be able to count anything on your 100 Hz Source. Check out the following Dev Zone Article.
http://zone.ni.com/devzone/cda/tut/p/id/2868
03-05-2009 03:54 PM
Thanks for your reply Doug.
I understand that for a "typical" period-measurement application I would have the faster signal as the source and the slower as the gate (as pictured in the Dev Zone article you referenced) so that I get the period of the gate as a multiple of the period of the source.
My intention, however, is to hook up the signals in reverse. So for the majority of the 16000 samples I will have zero counts, but 100 times a second I'll capture an edge and get a single count.
This post seems to imply that this should work:
http://forums.ni.com/ni/board/message?board.id=40&thread.id=1974&view=by_date_ascending&page=1#M205
In fact that thread describes pretty much exactly what I want to do, except all the discussed code is in LabView and I need to do it from C.
03-05-2009 04:57 PM - edited 03-05-2009 05:00 PM
Upon playing with this some more, I've discovered that the default sampling signal is not PFI8, but the 80MHz timebase. Once I explicitly set the source to my 100 Hz signal with
DAQmxErrChk(DAQmxSetCICtrTimebaseSrc(CounterTaskHandle, "/Dev1/ctr0", "/Dev1/PFI8"));
Things are working as I expected.