Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Counter output, on demand

Solved!
Go to solution

I'd like to have a counter output a single pulse whenever a condition occurs within a loop. My current solution (in pseudocode; I use LabWindows CVI on a RT target) looks like this:

 

DAQmxCreateTask(...);
DAQmxCreateCOPulseChanTime(...);
while (true)
{
  if (condition)
  {
    t1 = Timer();
    DAQmxStartTask(...);
    t2 = Timer() ;
    DAQmxErrChk (DAQmxWaitUntilTaskDone(*th,2));
    DAQmxErrChk (DAQmxStopTask(*th));
  }
}
DAQmxClearTask(...);

Unfortunately, the delay between t1 and t2 is at least 0.142ms, and sometimes 2ms. Is there an elegant way to decrease this and not having to call StartTask again and again?

 

Thanks,

Jonas 

Jonas Zimmermann, PhD
Neuroscience Department
Brown University
0 Kudos
Message 1 of 5
(7,036 Views)
Solution
Accepted by topic author jonasz

You should get some improvement by committing the task before your loop:

 

...
DAQmxCreateCOPulseChanTime(...);
DAQmxTaskControl(taskHandle, DAQmx_Val_Task_Commit);
while (true)
...

 

If this still isn't good enough, you might instead try using a digital output task (start the task before the loop, write twice inside the loop--high then low--whenever you need to output a pulse).  If the pulse width needs any sort of accuracy at all you'll want to use the digital output task to trigger a counter output (start the counter task before the loop, configure it to be "retriggerable" so you don't have to restart it repeatedly in software).  I don't know if this will actually be faster or not without benchmarking it.

 

 

Best Regards,

John Passiak
Message 2 of 5
(7,018 Views)

That's very helpful, thanks!

Your first solution reduces the time to start the counter task to 30µs. The second solution seems to be slower (looking at where the pulse comes in on the scope), and writing the digital samples also takes ~140µs.

My code for the second solution is below, maybe there is room for improvement, too.

DAQmxCreateTask("",&triggerTask);
DAQmxCreateDOChan (triggerTask, "SpikeDAQCard/port0/line7", "", DAQmx_Val_ChanPerLine);

DAQmxCreateTask("pulse",&stimOutTask);
DAQmxCreateCOPulseChanTime(stimOutTask, "SpikeDAQCard/ctr0", "", DAQmx_Val_Seconds, DAQmx_Val_Low, 0.0, 0.001,0.001));
DAQmxCfgImplicitTiming(stimOutTask, DAQmx_Val_FiniteSamps, 1));
DAQmxCfgDigEdgeStartTrig(stimOutTask, "/SpikeDAQCard/PFI8", DAQmx_Val_Rising));
DAQmxSetTrigAttribute (stimOutTask, DAQmx_StartTrig_Retriggerable, 1));
DAQmxStartTask(stimOutTask));
unsigned char dat[2]={1,0};

while (true)
{
    if (condition)
    {
        t1 = Timer();
        DAQmxWriteDigitalLines (triggerTask, 2, TRUE, 1, DAQmx_Val_GroupByChannel, dat, &dwr, NULL);
        t2 = Timer();
    }
}

 

Jonas Zimmermann, PhD
Neuroscience Department
Brown University
0 Kudos
Message 3 of 5
(7,011 Views)

Try explicitly starting the triggerTask before the loop and set auto start on the write call to FALSE (it's the 3rd input).  This should make a big difference.

 

Situational:  You might want to split up the write call--set the line high when you need to send the trigger (assuming this is the time-critical portion of the code) and re-arm the trigger by setting the line low whenever you have time to spare later on.  Overall you'll probably end up taking up more time with 2 calls vs 1 but I'd expect each individual call should take less time so it might be advantageous to split this up and make the calls on your own terms.

 

EDIT:  You might also try enabling memory mapping on the digital output task (call DAQmxSetDOMemMapEnable before starting your task).  It might not be supported on your device though (you didn't mention which device you are using).

 

 

I'm still not sure how this will compare to just outputting the counter directly--I thought it would have been faster but then again this probably varies quite a bit across different product lines and different busses.

 

 

Best Regards,

John Passiak
0 Kudos
Message 4 of 5
(7,005 Views)

OK, I tried your first suggestion. It improves things (and writing the DO pulse takes only 20µs.

EDIT: and splitting up the writes in two consecutive statements reduces write time for the first to 10µs.

DAQmxSetDOMemMapEnable is not supported by my device (PXI-6251 and PXI-8101 in a PXI-1002 chassis). Also, it's not documented in my LAbWindows help ...

It is still about 1ms slower than counter only, so I'll go with that.

 

Thanks for your help!

Jonas

Jonas Zimmermann, PhD
Neuroscience Department
Brown University
0 Kudos
Message 5 of 5
(6,993 Views)