Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Access Counter with ANSI C

Hi Folks,

 

I am trying to access counter  using ANSI C (python wrapper actually). Now I am able to read number of counts with sets of commands:

 

DAQmxCreateTask("", &task);

DAQmxCreateCICountEdges(task, "Dev1/ctr0", "", DAQmx_Val_Rising, 0, DAQmx_Val_CountUp);

DAQmxSetCICountEdgesTerm(task, "Dev/ctr0", "Dev1/PFI11");

DAQmxStartTask(task);

 

DAQmxReadCounterScalarU32(task, 10, &data, NULL) 

 

This example cumulates all counts since task was started, so I can get all counts from begining of task or from previous call (using internal software buffer).

But what I want to do is count non-periodical series of 'events'  represented with TTL/NIM pulses. So I want to set up measurement (integration) time for one single shot (let say 1000 ms) and then in loop read number of counts (=events) in this window (i.e. frequency in Hz). I probably need to trigger the 'counting function' in some way, probably something like DAQmxCfgSampClkTiming...

 

Can you please show me short, simple piece of code, how to do this?

Thanks a lot.

Radek 

 

 

0 Kudos
Message 1 of 5
(8,252 Views)

Hi Radek,

 

I'm not sure if understand what exactly do you need to do, but it really sounds like period (or frequency) measurement. There, you actually perform edge counting for exactly specified period of time.

 

 

Single Period Measurement.JPG

 

Notice here, that you need another signal of known frequency. To get this signal, you can use for example 2nd counter. If you need to measure edge count continuously, meening read edge count on each rising edge of the Gate (known) signal and then restart counting, then you might consider buffered operation.

 

I strongly recomend to read manual for your DAQ board. Assuming you are using M Series, use M Series User Manual, and check chapter 7 - Counters.

 

There are actualy couple of examples shipped with DAQ driver itself. Chceck NI-DAQ™mx C Reference Help (Windows Start -> Programs -> National Instruments -> NI DAQ -> Documentation -> Text based Support) for information on exact location of the examples. By default, they are in public Documents\National Instruments\NI-DAQ\Examples.

 

In my case, on Windows 7 they can by found in C:\Users\Public\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Counter

 

 

As I mentioned, the best would be to clarify with manual mentioned above what is the best counter mode for your application, and I'm sure you can find this implemented in shipped examples.

 

 

Hope it helped.

 

 

 

Stefo

Certified-LabVIEW-Developer_rgb.jpg

Message 2 of 5
(8,234 Views)

So I spent a lot of time reading manuals and examples, googling and experimenting with our devices, but I am still not able to get a simple piece of code, which is doing what I want.

 

Can you please anybody show me the code which do what is on that picture one post ago (fig. 7-8), also with description how/where to connect all signals? With preinstaled examples there is one problem, that I am not sure what are they doing, so I can not follow them.

 

Yes, and we have several 6601 and 6602 cards and one 6229, if it matters... 

 

Thanks a lot.

Radek 

 

 

0 Kudos
Message 3 of 5
(8,164 Views)

Hi Radek,

 

To measure period, it is pretty the same as when you configure let say pulse width (there is example on pulse width), just change the functions to measure Counter Input -> Period Measurement (DAQmxCreateCIPeriodChan). This should be pretty much everythink you have to do:

 

 

    1. Create a task. (DAQmxCreateTask)
    2. Create a Counter Input channel to measure Period (DAQmxCreateCIPeriodChan). 

    3. Call the Start function to arm the counter and begin measuring. (DAQmxStartTask)
    4. Call the Read function to return the next pulse width measurement. Set a timeout so an error is returned if a pulse is not returned in the specified time limit. (DAQmxReadCounterScalarF64)
    5. Call the Clear Task function to clear the task. (DAQmxStopTask; DAQmxClearTask)
    6. Display an error if any.

 

If you want to get information on what should be connected, you can see M Series User Manual, as I mentioned earlier. Connection and functionality of period measurement is described in chapter 7, Counters -> Counter Input applications -> Period Measurement. You need to connect your measured signal into Counter Source. Counters IOs are actualy PFI lines, and you can pick which one to be used. See page 7-30 to get Default Counter/Timer Pinouts. For example, for M Series devices CTR 0 Source is connected to PFI8 by default. Consult pinout of 6601 and 6602 with 660x User Manual.

 

If you need to know the pins where to connect the signal, see device pinout in particular manual (for example for 6229, see page 219, PCI/PXI-6229 Pinout of M Series User Manual manual).

 

 

Hope this will lead you to solution Smiley Wink

 

 

Regards / S pozdravom

Stefo

Certified-LabVIEW-Developer_rgb.jpg

0 Kudos
Message 4 of 5
(8,149 Views)

Hi Stefo,

 

Thanks for trying to help me.

I tried to use DAQmxCreateCIPeriodChan and it works fine, but it just not what I was looking for. In our application, we have to read counts from multiple counters (usually 3) in the same time window and the signal is NOT periodic (if it matters). Also it blocks one more counter for each one in the task, so if I need 3 Inputs, the 6601 cards with just 4 counters is not enough. Maybe if it is be possible to share that "gate" counter, I will need just 4 and also it will be maybe possible to count corresponding events in the same time window.

 

But I found a solution. This "code" (seems to) do exactly what I need:

(this is just important part of Python code, but I guess it is very easy to read, so...)

 

def cOut0(self, chan, up = 1, down = 0.1, samps = 1e3, num = -1):
    err1 = self.device.DAQmxCreateCOPulseChanTime(self.task, char(chan), char(""), int32(DAQmx_Val_Seconds), int32(DAQmx_Val_Low), float64(0), float64(down), float64(up))
    if num > 0:
        err2 = self.device.DAQmxCfgImplicitTiming(self.task, int32(DAQmx_Val_FiniteSamps), uInt64(num))
    else:
        err2 = self.device.DAQmxCfgImplicitTiming(self.task, int32(DAQmx_Val_ContSamps), uInt64(samps))

def cOut1(self, chan, freq = 1e3, duty = 0.1, samps = 1e3, num = -1):
    err1 = self.device.DAQmxCreateCOPulseChanFreq(self.task, char(chan), char(""), int32(DAQmx_Val_Hz), int32(DAQmx_Val_Low), float64(0), float64(freq), float64(duty))
    if num > 0:
        err2 = self.device.DAQmxCfgImplicitTiming(self.task, int32(DAQmx_Val_FiniteSamps), uInt64(num))
    else:
        err2 = self.device.DAQmxCfgImplicitTiming(self.task, int32(DAQmx_Val_ContSamps), uInt64(samps))

def cIn5(self, chan, trig, rate = 1e9, samps = 1e3):
    err1 = self.device.DAQmxCreateCICountEdgesChan(self.task, char(chan), char(""), int32(DAQmx_Val_Rising), uInt32(0), int32(DAQmx_Val_CountUp))
    err2 = self.device.DAQmxSetPauseTrigType(self.task, int32(DAQmx_Val_DigLvl))
    err3 = self.device.DAQmxSetDigLvlPauseTrigSrc(self.task, char(trig))
    err4 = self.device.DAQmxSetDigLvlPauseTrigWhen(self.task, int32(DAQmx_Val_Low))
def wait(self, tOut = -1):
    tOut = float(tOut)
    err = self.device.DAQmxWaitUntilTaskDone(self.task, float64(tOut))

def gCts(self, tout = 1.0, buff = False):
    tout = float(tout)
    ret = numpy.zeros(1, dtype=numpy.uint32)
    err = self.device.DAQmxReadCounterScalarU32(self.task, float64(tout), ret.ctypes.data, bool32(0))
    return ret[0]
And here is terminal output (important part):
>>> devOS.createTask(taskName = "OS")
>>> devOS.cOut1(chan = "/Dev1/ctr0", freq = 1e5)
>>> devOS.startTask()
>>>
>>> devOG = pydaq.nidaq()
>>> devOG.createTask(taskName = "OG")
>>> devOG.cOut0(chan = "/Dev1/ctr1", up = 1, down = 0.1, num = 1)
>>>
>>> devIA = pydaq.nidaq()
>>> devIA.createTask(taskName = "IA")
>>> devIA.cIn5(chan = "/Dev1/ctr2", trig = "/Dev1/PFI32")
>>>
>>> devIB = pydaq.nidaq()
>>> devIB.createTask(taskName = "IB")
>>> devIB.cIn5(chan = "/Dev1/ctr3", trig = "/Dev1/PFI32")
>>>
>>> devIC = pydaq.nidaq()
>>> devIC.createTask(taskName = "IC")
>>> devIC.cIn5(chan = "/Dev1/ctr4", trig = "/Dev1/PFI32")
>>>
>>> import time
>>> def fce(n):
    T1 = time.time()
    r = []
    for i in xrange(n):
        t1 = time.time()
        devIA.startTask(); devIB.startTask(); devIC.startTask();
        devOG.startTask()
        devOG.wait()
        devOG.stopTask()
        c = [devIA.gCts(), devIB.gCts(), devIC.gCts()]
        devIA.stopTask(); devIB.stopTask(); devIC.stopTask();
        t = time.time() - t1
        r.append(c)
        print "%d: %d %d %d (%d s)" % (i + 1, c[0], c[1], c[2], t)
    T = (time.time() - T1) / float(n)
    print "Total Average Time: %d s" % (T)
    return r

>>> a = fce(10)
1: 100000 100000 100000 (1 s)
2: 100000 100000 100000 (1 s)
3: 100000 100000 100000 (1 s)
4: 100000 100000 100000 (1 s)
5: 100000 100000 100000 (1 s)
6: 100000 100000 100000 (1 s)
7: 100000 100000 100000 (1 s)
8: 100000 100000 100000 (1 s)
9: 100000 100000 100000 (1 s)
10: 100000 100000 100000 (1 s)
Total Average Time: 1 s
So conclusion:
1) I know I can put all Input Tasks together to only one task, but when I try to read the counts with DAQmxReadCounterU32 function, I get error -200523. So what Read function is for task with multiple counters?
2) All those Trigger functions I used I found somewhere on the internet. Where is documentation? I can not find it in NI-DAQmx C Reference Help. Also in the header file, there are a lot of functions prototypes of which are not mentioned in the documentation.
3) When I change the lowTime parameter in function DAQmxCreateCOPulseChanTime, the time of measurement does not change, so it seems that this part of pulse is not part of 'task' and/or the DAQmxWaitUntilTaskDone function waits just when the trigger pulse is high. This decreases our death time, because it seems not be possible to set duty cycle to 100 %, but still it is little confusing for me.
Diky moc
Radek

P.S.: Ten "editor" na vlkadani dotazu je udesnej... 🙂

 

Message 5 of 5
(8,054 Views)