Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Can DAQmxRegisterEveryNSamplesEvent function be used for the Counter Input Channels

Solved!
Go to solution

Hi, All,

 

I have an application to count the digitial pulse number. I want to know the time of the coming pulses which start from 1 and increased 4 later, like 1, 5, 9, 13..... The time interval between each pulse is not a fixed value. So I tried to use  DAQmxRegisterEveryNSamplesEvent and DAQmxCreateCICountEdgesChan functions. But afterI called the DAQmxStartTask function, it always failed.  The board I used is the NI-PCIe-6320. Here is part of my code.


DAQmxErrChk (DAQmxCreateTask("",&m_taskhandle));
DAQmxErrChk (DAQmxCreateCICountEdgesChan(m_taskhandle,"Dev1/ctr0","",DAQmx_Val_Rising, 0, DAQmx_Val_CountUp));
DAQmxErrChk(DAQmxRegisterEveryNSamplesEvent(m_taskhandle, DAQmx_Val_Acquired_Into_Buffer, 4, 0, EveryNSamplesCallback, this) );
DAQmxErrChk (DAQmxStartTask(m_taskhandle));

 

I don't know the reason. Can Anyone give me some help. Thanks.

 

Yang

0 Kudos
Message 1 of 13
(8,093 Views)

There are several shipping examples you might find useful. 

 In the examples file go to Counters>>Count Digital Events>>Count Digital Events

also go to

Digital I/O>>Digial Measurements>>Change Detection or Change Detection Event

Applications/Systems/Test
National Instruments | AWR Group
0 Kudos
Message 2 of 13
(8,074 Views)
Solution
Accepted by slowsheep

DAQmxRegisterEveryNSamplesEvent only works with buffered tasks.  This is what you should be doing anyway (whether you want to use the callback or not):

 

1.  Make your external signal the sample clock (DAQmxCfgSampClkTiming).

 

2.  Use one of the internal timebases as the source (DAQmxSetCICountEdgesTerm).

 

 

Every sample you read will give the count in timebase ticks.  Multiply the count by the period of your timebase and you now have a timestamp.  Keep in mind the counter rolls over at 2^32 so account for this in your program.  

 

The callback isn't necessary, but it's useful in that you can ensure you don't block your main thread while waiting for samples to be available.

 

 

Best Regards,

John Passiak
0 Kudos
Message 3 of 13
(8,063 Views)

Thanks John. I will try your suggestion.

 

Regards,

 

Yang

0 Kudos
Message 4 of 13
(8,056 Views)

John,

 

When I called the DAQmxCfgSampClkTiming function, it shows an error  message:

 

External sample clock source must be specified for this application.
Unspecified Property: DAQmx_SampClk_Src
Channel Name: Dev1/ctr0

Task Name: _unnamedTask<0>

Status Code: -200303

 

Here is the code I used:

DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk(DAQmxCreateCICountEdgesChan(taskHandle,"Dev1/ctr0","",DAQmx_Val_Rising, 0, DAQmx_Val_CountUp));

DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"OnboardClock",20000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,4));
DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle,DAQmx_Val_Acquired_Into_Buffer,4,0,EveryNSamplesCallback,NULL));

 

I saw the C reference help, it says to  use the internal clock of the device, use NULL or use OnboardClock for the second parameter of DAQmxCfgSampClkTiming. Can I use the internal clock as an external clock? Can you give me some simple code to use the internal clock as an external clock. Thanks.

 

Regards,

 

Yang

0 Kudos
Message 5 of 13
(8,054 Views)

There isn't an internal sample clock for the counters, you'd have to generate a clock yourself (could use one of the other counters if you wanted to do this, there are 4 on the device).

 

However... I was under the impression that you were trying to timestamp your external signal.  If this is the case, you'll want to use your external signal as the sample clock.

 

 

Best Regards,

John Passiak
0 Kudos
Message 6 of 13
(8,051 Views)

Hi, John,

 

What's I what to do is that I have an external digital signal, when the signal goes from low to high, I need do some operations. So I just want to know the time when the digital signal goes from low to high.  The frequency of the digital signal is from 0 - 20000Hz. My first plan is to use a counter to count the pulse rising edges. When the number of edge increases one, I do the designed operations. In this method, I can't guarantee I can catch each pulse rising point. Because sometimes the counter will increase more than one in the on-demand mode. For example, the previous content of the counter is xxxx4, but the next reading the content may become xxxx6.

 

After I learned some ANSI C  codes, I found that the ChangeDetectionEvent can help me found time when the signal goes from low to high. So I wrote the following code: (I set the digital signal to P0.0)

 

DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxCreateDIChan(taskHandle,"Dev1/port0/line0","",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgChangeDetectionTiming(taskHandle,"Dev1/port0/line0","",DAQmx_Val_ContSamps, 1));

DAQmxErrChk (DAQmxRegisterSignalEvent (taskHandle, DAQmx_Val_ChangeDetectionEvent, 0, Callback , dialog));

DAQmxErrChk (DAQmxStartTask(taskHandle));

 

int32 CVICALLBACK Callback (TaskHandle taskHandle, int32 signalID, void *callbackData){

 

CNIPCIE6320Dlg* dialog = static_cast<CNIPCIE6320Dlg*>(callbackData);

dialog->m_event_num++;  // Here is to calculate how many events has been triggered

return 0;

 

}

 

Yesterday I used this method to get the pulse rising time. I found the m_event_num is close to the ground truth (In the simulation, I know how may rising pulse I generated).  In one two hours test, the offset is almost 400 pulses. But today I did the same tests again. I found the m_event_num got a big difference from the ground truth. The voltage of the whole system today maybe smaller than yesterday, because today the power is from an invertor while yesterday the power is from the electricity supply. So will the lower voltage supply will causing some event missing. Or if PC system became busy will ignore some callings of the event callback function? That's two possible reason will affact the final result. I am not sure. Do you have any experience about this problem.  Or do you have some better suggestion to get the pulse rising time. Thanks again.

 

Regards,

 

Yang 

0 Kudos
Message 7 of 13
(8,048 Views)

If you're just looking to count the number of edges or get a timestamp associated with each rising edge you should use hardware timing for this (see my suggestion here).  Buffer the data rather than relying on your software loop to keep up.

 

If you actually need to run a software operation on each edge then this is a completely different question.  DAQmx events would be the right way to handle this but I'm not so sure the software would be able to keep up at 20 kHz.  What call are you planning to execute in your callback?  The example you gave just increments a count (presumably this example is just testing the reliability of using callbacks).

 

 

Best Regards,

John Passiak
0 Kudos
Message 8 of 13
(8,027 Views)

Thanks John. 

The call I am planning to execute in my callback function is to sync the pulse information from the digital IO channel to another signal information which is from a RS485 port. The sync procedure is to tag the pulse id from the digital IO channel to the id of the signal from the RS485 port. So it is not a complicated operation. My concerned is that if the callback function can be executed on time on each rising edge of pulse, especially when the system is busy. So I wrote the incremental operation in the  example code  to verify the reliability of using callbacks. Right now the result is not stable.

 

 I will try your suggestion. But right now I don't know how to use this DAQmxSetCICountEdgesTerm function. Do you have some sample code for me to figure out how to use it.  

 

By the way, today I met a new problem. Here is my code.

 

DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxCreateDIChan(taskHandle,"Dev1/port0/line0", "", DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgChangeDetectionTiming(taskHandle,"Dev1/port0/line0", "", DAQmx_Val_ContSamps, 1));
DAQmxErrChk (DAQmxRegisterSignalEvent (taskHandle, DAQmx_Val_ChangeDetectionEvent, 0, Callback , dialog));

 

DAQmxErrChk (DAQmxCreateTask("",&taskHandle2));
DAQmxErrChk (DAQmxCreateDIChan(taskHandle2,"Dev1/port0/line1", "", DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgChangeDetectionTiming(taskHandle2,"Dev1/port0/line1", "", DAQmx_Val_ContSamps, 1));
DAQmxErrChk (DAQmxRegisterSignalEvent (taskHandle2, DAQmx_Val_ChangeDetectionEvent, 0, Callback2 , dialog));

 

After I created a digital channel on P0.0 in one task, I want to create another task on P0.1. Because I have two external signals to be detected by the NI card.  

When I want to start the second task, it shows the P0.1 was reserved.

Here is the detail information:

NI Platform Services: The specified resource is reserved. The operation could not be completed as specified.
Task Name: _unnamedTask<2>

Status Code: -50103

 

I didn't open or use dev1 port0 except the above code. I don't know the reason. Are all lines in dev1 port0 can only be opened in one task? Do you have any idea about this error.

 

I really appreciate your help. Thanks.

 

Regards,

 

Yang

 

 

0 Kudos
Message 9 of 13
(8,021 Views)

If you want to use change detection then all of your inputs have to be in the same task.  You can reference both lines when you create your channel (e.g. "Dev1/port0/line0:1").

 

The CI Count Edges Terminal can only be set for a Counter input (edge count) task.  The call itself might look something like this:

DAQmxSetCICountEdgesTerm(taskHandle, "", "/Dev1/PFI0");

 

 

Best Regards,

John Passiak
0 Kudos
Message 10 of 13
(8,012 Views)