counting pulses with NI DAQ tools
AKuerten
I am using IGOR 6.21 together with NI DAQ tools. The NI DAQ hardware I am using is a PCMCIA 6036E board.
I would like to do the following: counting pulses with counter 0 on the board over a specified period - e.g. 1 second.
For testing my code I am using the channel "/Dev1/20MHzTimebase" of the NI board as a source. First, I tried the following function:
function count_pulses_simple()
Variable/D a
DAQmx_CTR_CountEdges/DEV="Dev1" /EDGE=1 /INIT=0 /DIR=1 /SRC="/Dev1/20MHzTimebase" 0
sleep 00:00:01
a = fDAQmx_CTR_ReadCounter("Dev1", 0)
fDAQmx_CTR_Finished("Dev1", 0)
print a
end
Variable/D a
DAQmx_CTR_CountEdges/DEV="Dev1" /EDGE=1 /INIT=0 /DIR=1 /SRC="/Dev1/20MHzTimebase" 0
sleep 00:00:01
a = fDAQmx_CTR_ReadCounter("Dev1", 0)
fDAQmx_CTR_Finished("Dev1", 0)
print a
end
It returns e.g. 4.53663e+06, however, this value varies, most likely because the sleep function is not very accurate. What bothers me is, why does the function not return a number which is close to 2e+7 and therefore corresponding to the 20MHz timebase? Is this due to a numeric overflow or due to aliasing?
In order to have a more precise timing for the counting I also tried another procedure instead of using the sleep function. For this, I tried to use counter 1 on the same NI board to provide a trigger (on "/Dev1/Ctr1InternalOutput") for counter 0. The trigger (/TRIG) command should be used to start the counting and the pause (/PAUS) command should terminate it. With the following function it should count for 0.1s:
function count_pulses()
Variable/D a
DAQmx_CTR_CountEdges/DEV="Dev1" /EDGE=1 /INIT=0 /DIR=1 /TRIG={"/Dev1/Ctr1InternalOutput", 1, 1} /PAUS={"/Dev1/Ctr1InternalOutput", 0, 0, 0, 2} /SRC="/Dev1/20MHzTimebase" 0
DAQmx_CTR_OutputPulse/DEV="Dev1" /SEC={0.1, 0.9} /NPLS=1 /OUT="/Dev1/Ctr1InternalOutput" 1
a = fDAQmx_CTR_ReadCounter("Dev1", 0)
fDAQmx_CTR_Finished("Dev1", 0)
fDAQmx_CTR_Finished("Dev1", 1)
print a
end
Variable/D a
DAQmx_CTR_CountEdges/DEV="Dev1" /EDGE=1 /INIT=0 /DIR=1 /TRIG={"/Dev1/Ctr1InternalOutput", 1, 1} /PAUS={"/Dev1/Ctr1InternalOutput", 0, 0, 0, 2} /SRC="/Dev1/20MHzTimebase" 0
DAQmx_CTR_OutputPulse/DEV="Dev1" /SEC={0.1, 0.9} /NPLS=1 /OUT="/Dev1/Ctr1InternalOutput" 1
a = fDAQmx_CTR_ReadCounter("Dev1", 0)
fDAQmx_CTR_Finished("Dev1", 0)
fDAQmx_CTR_Finished("Dev1", 1)
print a
end
However, when running this function an error message appears which is related to the use of the /TRIG command. If the /TRIG command is removed no error message appears but the timing doesn't seem to have any effect - the result is completely independent on the /SEC settings.
Any help would be greatly appreciated!
Andreas
You are correct that count_pulses_simple() fails to give the expected result due to overflow. The E-series devices have 24-bit counters; 2^24=16777216. Given that, you would expect that an exact 1-second counting time would result in 20e6-16777216 = 3.22278e+06; I think the result you got is not unreasonable as the sleep time and execution time of the statements would be pretty variable.
If you change 20MHzTimebase to 100kHzTimebase the numbers you get will be quite variable but right around 100,000. Note that 20 MHz is the maximum counting rate specified for that device.
I added some error checking and corrected the commands in your count_pulses() function:
Variable/D a
try
// DAQmx_CTR_CountEdges/DEV="pci6014" /EDGE=1 /INIT=0 /DIR=1 /TRIG={"/pci6014/Ctr1InternalOutput", 1, 1} /PAUS={"/pci6014/Ctr1InternalOutput", 0, 0, 0, 2} /SRC="/pci6014/20MHzTimebase" 0; AbortOnRTE
DAQmx_CTR_CountEdges/DEV="pci6014" /EDGE=1 /INIT=0 /DIR=1 /PAUS={"/pci6014/Ctr1InternalOutput", 1, 0} /SRC="/pci6014/20MHzTimebase" 0; AbortOnRTE
// DAQmx_CTR_OutputPulse/DEV="pci6014" /SEC={0.1, 0.9} /NPLS=1 /OUT="/pci6014/Ctr1InternalOutput" 1; AbortOnRTE
DAQmx_CTR_OutputPulse/DEV="pci6014" /SEC={.1,1} /NPLS=1 1; AbortOnRTE
sleep/S 2
a = fDAQmx_CTR_ReadCounter("pci6014", 0); AbortOnRTE
fDAQmx_CTR_Finished("pci6014", 0); AbortOnRTE
fDAQmx_CTR_Finished("pci6014", 1); AbortOnRTE
catch
if (V_abortCode == -4)
print "Error trying to count edges:"
print fDAQmx_ErrorString()
endif
endtry
print a
end
Adding the error checking resulted in an error message telling me that /TRIG is not supported on that device for counting pulses. The /PAUS trigger is supported, however, but an error in my documentation has led you astray. The documentation has these arguments for /PAUS:
/PAUS={source, pretrigSamples [, type, edgeslopewhen, level1, level2]}
But in fact, the pretrigSamples argument is not present in the PAUS keyword; it is used only for a reference or stop trigger for pre-triggered analog input. My apologies.
Also, the type for /PAUS must be 1; a type of 0 disables the trigger. Finally, the sense of the /PAUS trigger is perhaps unexpected- when asserted, it *stops* the counter. So for a pulse that is high, you need to use 0 for the level argument in order to have counting occur during the high-going part of the pulse.
Finally, I added the Sleep command because otherwise execution gets to fDAQmx_CTR_ReadCounter() and the rest too soon, before the pulse time is elapsed. Then you get a truncated count.
I removed "/OUT="/pci6014/Ctr1InternalOutput"" because it is unnecessary- that happens regardless of any other settings.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
September 15, 2011 at 03:33 pm - Permalink
September 15, 2011 at 11:06 pm - Permalink