Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Retriggerable gated counter or analog pulse trains

Hi all,

 

I have a problem I could not resolve in the last days. It might be even a question of creativity of how to come up with a solution.

 

I have an external pulse train 1 at ca. 8 kHz (frequency not fully stable). With this pulse train, I want to trigger with each pulse an analog waveform. Using X-series boards, this works perfectly.

But now I want to gate this analog signal with another pulse train 2 that is much slower than the other one (pausetrig option). Theoretically, this works nicely, too. But in reality, the analog signal simply ends at the point where it is stopped by the pause trigger, whereas I want it to stop at the end point of the waveform.

 

Please have a look at the drawing attached

 

gated triggering.png

 

I would be really glad about any ideas on how to solve this problem.

 

Best regards,

Peter

0 Kudos
Message 1 of 11
(6,200 Views)

 

I don't think I've ever defined both a start trigger and a pause trigger defined for the same task.  Good to know it's allowed.

 

Given what you've already found, the solution is to control the timing of the end of the pause trigger pulse's active state (shown here as high). 

 

Here's one approach:

 

1. Create the pause trigger pulse with a retriggerable single pulse task.  Use a minimal "low time" and "initial delay".  Set the high (active) time to be approximately (N+1) periods of your AO sample clock.  Technically, N+1 periods is a bit more than necessary, but it's sure to be enough and doesn't require research into deep details of AO timing.

 

2. Configure the AO task to use the pulse as *both* its start trigger (rising edge) and its pause trigger (pause when low).

 

Comments: this makes for a different timing diagram than you've drawn.  Each external 8 kHz pulse causes a minimally-delayed pause trigger pulse which lasts long enough to generate the full AO waveform but ends before the next 8 kHz pulse.  The choice of when to start and stop this trigger pulse will be up to your own logic and will be governed by software timing. 

   Oh dang!  That still leaves you susceptible to a partial waveform since you can't sync the software timing to occur during the desired small fraction of the 8 kHz interval with no AO waveform.

 

 

Second approach:

1. Similar to #1 above, but set the high (active) time to cover multiple 8 kHz periods and *don't* make the task retriggerable.  To get the timing right in hardware, you'll need to generate a pulse that's *approximately* the requested length, but you'll reserve the right to tweak it so the edges fall in the right place.   You'll also define your pulse in terms of the external 8 kHz signal rather than in terms of internal board time.

     Specifically, configure to generate a pulse based on units of "Ticks" using the rising edges of the external 8 kHz signal as the "source of ticks."  Set a minimal value (probably 2) for both the "low ticks" and "initial delay" inputs.  The "high ticks" setting is where you do your tweaking.

    Suppose the desired pause trigger time is 10.3 msec.  Nominally, that's 82.4 intervals of the 8 kHz external signal.  Well, just round up or down as you see fit and wire this integer # into the "high ticks" input. 

2. AO task is configured to retrigger off the external 8 kHz signal and be pause triggered by #1's counter pulse.

 

Comments: When you start the pause trigger pulse task, it will remain in its low idle state for the first two 8 kHz pulses.  It will go high on the 3rd pulse and then revert low on the 82nd subsequent pulse.

   Because this pulse *also* acts as a pause trigger for the AO task, you're now synced such that the AO task is paused exactly as it is being retriggered, meaning that the previous waveform must have been allowed to complete.  (The deep details of timing will prevent the AO task from generating 1 sample at this instant.)

 

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 2 of 11
(6,182 Views)

Hi Kevin,

 

Thank you for your ideas! Having little experience, I didn't think of using a special clock for the pause train trigger ...

 

I think I will try out your first approach first. To do this without the uncertainty of software timing, I would simply make the pause pulse 2 retriggerable, and triggered by the 8 kHz pulse train. So the  software switches on the pulse train 2 task at an uncertain time (black arrow), but it starts only after receiving the pulse train 1 edge:

 

gated triggering2.png

 

My only concern is that the retriggering of pulse train 2 by pulse train 1 might lead to delay. (If it's smaller than 1-3 us, then it would be ok.)

 

It will take some time until I get it working, because I'm not using LabView, but a Matlab wrapper for the C library, but I will come back if I have solved the problem.

 

Peter

0 Kudos
Message 3 of 11
(6,178 Views)

 

The delay can be as small as 2 timebase edges.  With approach 1, the timebase can be the internal 20 MHz or 80 MHz clock so the delay is much less than a microsec.  With approach 2, the timebase would be the 8 kHz signal itself so the delay would be exactly 2 full cycles of that external clock.  Either way, the rising edge of the pause trigger pulse would occur less than a microsec after one of the external clock edges.  Exactly *which* edge is determined in both cases by software timing.

 

To clarify my concern about approach 1: by defining a retriggerable pulse, it will keep recurring until you decide to stop the task in software.  When you *do* stop it in software, the falling edge will occur at a more-or-less random phase of the 8 kHz external clock and very likely result in a truncated final AO waveform.

 

With approach 2, the beginning of the pulse is delayed by 2-3 cycles of the external clock (250-375 usec) after the software-timed task start.  But both edges of the pause trigger will coincide with rising edges of the external clock so you won't get any truncated AO waveforms.

   Note that approach 2 depends on knowing ahead of time how long the pause trigger pulse should last.  If that needs to be decided after the pulse is started, a 3rd approach may be needed.

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
0 Kudos
Message 4 of 11
(6,174 Views)

Thanks for your reply.

 

I wonder how I could do this:

 

>> Set the high (active) time to be approximately (N+1) periods of your AO sample clock.

 

With the LabView interface, it might be quite obvious, but when you don't know the commands, it's not so easy. I simply do not know how to let a counter be governed by a clock. Can you give me a pointer?

 

And I'm also wondering: Will this AO sample clock only count ticks when there is (triggered) output, or will it run freely?

 

Best regards,

Peter

0 Kudos
Message 5 of 11
(6,159 Views)

--- deleted message ----

0 Kudos
Message 6 of 11
(6,145 Views)

It seems to be not possible to assign the sample clock of the analog output channel to the counter. When I type

 

obj.frameClock2.apiCall('DAQmxSetCOCtrTimebaseSrc',obj.PRgalvo.taskID,'Dev1/ao1','');  % which is a API call for the function of interest, where frameClock2 is the counter,

 

I get the following error:

 

NI DAQmx error (-200452) in call to API function 'DAQmxSetCOCtrTimebaseSrc':
Specified property is not supported by the device or is not applicable to the task.

0 Kudos
Message 7 of 11
(6,138 Views)

 

The string for designating DAQmx properties looks like the same format as the LabVIEW API.  Your string 'Dev1/ao1' refers to the actual analog output D/A channel.  Instead, try using the string '/Dev1/ao/SampleClock'.   (Note the leading '/' char)

 

I suppose that your PRgalvo.taskID is the task corresponding to channel ao1?   I'd just note that in the LabVIEW syntax, I'd be feeding in the task ID for the counter's task while then referring directly to the '/Dev1/ao/SampleClock' timing signal.  I wouldn't need to reference the AO task ID.   Just bringing it up as another possible speed bump.

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 8 of 11
(6,126 Views)

 

If I try using the string '/Dev1/ao/SampleClock', then I get the error: 

 

"NI DAQmx error (-200486) in call to API function 'DAQmxSetCOCtrTimebaseSrc':
Specified channel is not in the task."

 

Maybe I should briefly switch to LabView and check out how it works. Otherwise it's rather tapping in the blind.

 

Peter

0 Kudos
Message 9 of 11
(6,101 Views)

It looks like you have some sort of wrapper calling the DAQmx ANSI C API.  DAQmxSetCOCtrTimebaseSrc takes a task handle, the channel string, and the terminal to be set.  Assuming the .apiCall method just makes the specified C call and takes the inputs in order, I would expect it to look something like this:

 

obj.frameClock2.apiCall('DAQmxSetCOCtrTimebaseSrc',<ctr_task_handle>,<ctr_channel_name>,"/Dev1/ao/SampleClock");

 

<ctr_task_handle> is the TaskHandle that was created by DAQmxCreateTask (for the counter output task).

<ctr_channel_name> is the name that you defined for your counter output channel when you called DAQmxCreateCOPulseChanTicks*.  

 

 

*If you do not specify a name, NI-DAQmx uses the physical channel name as the virtual channel name. If you specify your own names for nameToAssignToChannel, you must use the names when you refer to these channels in other NI-DAQmx functions.

 

 

Best Regards,

John Passiak
Message 10 of 11
(6,076 Views)