Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

PCI 6602 InitialDelay on a counter with finite number of pulses VB 2005

Finally, after much toil and confusion, I think I have a decent grasp of how to program this card with DAQmx. Now that I got most of the basics down I decided to start writing the actual program that I set out to write several months ago.

One of the functionalities I want to implement is to repeat some trigger pattern at a regular interval. The way I have chosen to do this after much discussion is as follows:

On counter 7, I create a task of continuous (or finite) pulse train at the specified repetition frequency with duty cycle .5. The only purpose of this counter is to serve as the "master" cycle; it is not available to the user. I will not paste my code here but for those out there searching it's something like this:

Dim RefSig As New Task
RefSig.COChannels.CreatePulseChannelFrequency("/Dev1/Ctr7", "RefSig", COPulseFrequencyUnits.Hertz, COPulseIdleState.Low, 0, 15, 0.5)
RefSig.Timing.ConfigureImplicit(SampleQuantityMode.ContinuousSamples)

This prepares counter 7 for output at 15 Hz, but does not start it (since I should set up my other counters first).

Then I have 7 counters left for the user to do as he pleases. One very simple use would be to create one pulse of specified width that goes off a specified delay after this reference signal's rising edge. (NOTE: I spent weeks and weeks toiling with "Gating", "Pause triggers", "Signal Routing", etc, but it turns out if you just don't think about it much DAQmx does the dirty work for you. The shame is the documentation does not have enough examples, and the combination of this with the fact that there are several ways to do the same thing can make it very confusing.) The code for this would look like this:

Dim Counter0 As New Task
Counter0.COChannels.CreatePulseChannelTime("/Dev1/Ctr0", "Counter0", COPulseTimeUnits.Seconds, COPulseIdleState.Low, 0.001, 2/80000000, 0.001)
Counter0.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/Dev1/Ctr7InternalOutput", DigitalEdgeStartTriggerEdge.Rising)
Counter0.Triggers.StartTrigger.Retriggerable = True
Counter0.Timing.ConfigureImplicit(SampleQuantityMode.FiniteSamples, 1)


This the particular chunk of code that took me a long time to figure out between the docs and the forums. It's all clear now, even though the learning process is a big haze to me. But this works - and at least for the output of counter 7 - will work for counters 0 through 6 (i don't know if all the outputs of every counter are usable as start triggers for every other counter).

This code creates a pulse on counter 0 which is 0.001 seconds wide and whose leading edge is 0.001 seconds after that of RefSig (counter 7). The first "0.001" is "The initial delay",  the "2/80,000,000" is the "Low time" (minimum of 2 clock cycles of the 80MHz clock), and the second "0.001" is the "High time" (according to the definition of CreatePulseChannelTime).

Because there is both an "Initial delay" and a "low time", I figured I could then implement the next feature easily: Allow the user to set a counter to be a burst of N triggers separated by a certain time, with certain width, and where the burst starts a set time after the reference signal's rising edge.

However, it seems to me that this behavior is broken. As written above, if I change the number of pulses from 1 to 2 (on the last line) I get a pulse that is twice as wide - that is, two pulses with a delay of 25/80e6 between them. If I switch the first "0.001" and the 25/80e6 above (making the initial delay "zero" and the low time 1 ms) then (if I'm still creating one pulse) the single pulse is correctly delayed by 1 ms off the reference signal. If I then try to generate two pulses in this configuration (which I would assume would have a pulse delayed by 1 ms followed by a second pulse 1ms later) then what I get is a first pulse right on the reference signal's leading edge with a second pulse whose leading edge is 1 ms after the falling edge of the first trigger. In other words, the delay between triggers is correct based on a low time of 1ms, but there is no longer a delay in front of the first pulse. You would think then that the initial delay should also be set to 1 ms but this does not work either.

In short:
The InitialDelay parameter does not work under any circumstance in this retrigerable configuration, and
The LowTime parameter is ignored [for the first pulse] if generating more than one pulse.

This is broken, right? Or is there yet another concept I missed?

0 Kudos
Message 1 of 10
(5,430 Views)
In addition:

LowTime is the time the pulse spends in the low state whether or not idle sate is high or low, which means that LowTime can act as a delay if your idle state is low, but it just increases the width of the "inverted" pulse if the idlestate is high.
0 Kudos
Message 2 of 10
(5,427 Views)

Hi pelesl-

The behavior you are seeing is expected and is discussed briefly in this KB.  The idea is that you can configure different pulse specs from your first pulse than subsequent pulses if you would like.  If you want consistent operation with every retriggered pulse generation, simply configure your initial delay and LowTime/HighTime (whichever one corresponds to your idle state) to the same duration.  This will make all triggered pulses predictable and identical with respect to delay, duration, etc. 

Hopefully this helps-

Tom W
National Instruments
0 Kudos
Message 3 of 10
(5,422 Views)
Hi Tom,

Thanks for the reply (very quick!). The way I originally discovered this problem (or disappointment) is by setting the low time and initial delay identically.

To reiterate: I have a reference signal which is a continuous pulse train at set frequency. If I then generate a single pulse (idle low) with both initial delay and low time identical that is retriggerable off this reference signal, my scope shows this for the first and second reference signal pulses (case 1):

             ----                               ----
            |    |                             |    |
ref     ----      -----------------------------      ---------------
               ----                               ----
              |    |                             |    |
pulse   ------      -----------------------------      -------------
 

Now if I take the same exact code, except that I tell "pulse" to be two pulses instead of 1 (case 2), this is what I get:

             ----                               ----
            |    |                             |    |
ref     ----      -----------------------------      ---------------
               ----     ----                    ----     ----
              |    |   |    |                  |    |   |    |
pulse   ------      ----     ------------------      ----     -----_


In other words, the first set of "pulse" is correctly delayed off the reference signal, but every subsequent set of "pulse" is not.

One could interpret this as saying, as it states in the document you linked, that initial delay only happens on the first pulse even on a "retrigerable" pulse train (which as I'm NI had their reasons for doing this, I don't see how this could be useful) and the low time comes after the high time in a pulse defined in this way.

However this would be inconsistent with the behavior in case 1, where the pulses indicate that either:
A. the low time comes before the hight time and the initial delay is ignored, or
B. the low time comes after the high time and the initial delay is effective at every trigger from the reference signal (which is inconsistent with the KB that you linked).

Am I missing something?
Message 4 of 10
(5,417 Views)

Hi pelesl-

I misread your earlier post- you're correct in saying that it's not possible to create a uniform initial delay for a retriggerable finite pulse train generation.  The best method to accomplish this behavior is to manually program the two counters required for a finite pulse train generation.  This method allows you to exploit the behavior of a uniform initial delay that's available with a single pulse generation.  Here's how you might accomplish it:

  1. Program one counter for continuous, pause triggered pulse train generation as shown in the attached "GenDigPulseTrainContinuous_PauseTrigger"  Configure the pause trigger as the other counter's internal output.
  2. Program a second counter for retriggerable single pulse generation with uniform initial delay.  This pulse will "gate" the first counter and give the effect of bursts of retriggerable pulses with uniform external delays.  The duration of this pulse should be [number of pulses]/[frequency] for the pulse train you are generating.  The trigger for this pulse will be the external signal that you want to delay the burst of generation from.

The end result should give the effect you're looking for.  Please let me know if you need any additional information.  Thanks-

Message Edited by Tom W [DE] on 04-17-2006 04:42 PM

Tom W
National Instruments
Message 5 of 10
(5,408 Views)
Hi Tom,

Am I correct in saying that your suggested method requires three counters? (I looked at the sample you attached a while ago.)

Then in that case I could simply take my "pulse" task and leave it as a single pulse then create a new task on a third counter that would be retrigerrable off pulse and would have 0 initial delay with whatever number of pulses I want to generate, thus this "burst" would be delayed off the reference by the delay in "pulse".

But again, am I not correct in saying something is broken? If indeed you can only have a re-ocurring delay for single-pulse signals, then there should be three timing modes: "continuous", "singlepulse", and "Npulses". I don't know the detail of your hardware obviously, and I don't claim to, and I understand that the point of a library such as DAQmx is to make the card a "black box" but as a user it is frustrating to run into these ambiguous situations.

As it stands, I still don't know whether the low time comes before the high time, where this is in the documentation, and whether any of this is "broken" or not.

Thanks for the pointers,
Emilio
0 Kudos
Message 6 of 10
(5,402 Views)
Hi Emilio-
 
The method I suggested actually only requires two counters.  A single pulse generation, finite pulse train generation, and continuous pulse train generation requires one, two, and one counters, respectively.  So, whether you choose to create a finite retriggerable pulse train OR a retriggerable single pulse and continuous pulse train (as in my suggestion) you will only require two counters for the entire operation.
 
The behavior of triggered pulses varies with the type of operations you are performing.  For a single pulse, the behavior is the same as is discussed in the KB I linked previously.  For a finite pulse train the first pulse sequence waits for  initial delay before beginning on the "non-idle" state and generating pulses from there.  For subsequent triggered bursts the initial delay is not used and the output enters the non-idle state directly after the trigger.  In this way, the idle state is always the last level generated before each generation ends and the idle time before the next trigger begins. 
 
A lot of users requested the ability to create a first pulse delay pattern that differed from subsequent sequences and this situation arose from that need.  For applications where uniform operation is desired the workaround I suggested is a great option.
 
Hopefully this helps-
Tom W
National Instruments
0 Kudos
Message 7 of 10
(5,399 Views)
Hi Tom,

I don't think I understand. Let me try to decipher what you said:

  1. Program one counter for continuous, pause triggered pulse train generation as shown in the attached "GenDigPulseTrainContinuous_PauseTrigger"  Configure the pause trigger as the other counter's internal output.
  2. Program a second counter for retriggerable single pulse generation with uniform initial delay.  This pulse will "gate" the first counter and give the effect of bursts of retriggerable pulses with uniform external delays.  The duration of this pulse should be [number of pulses]/[frequency] for the pulse train you are generating.  The trigger for this pulse will be the external signal that you want to delay the burst of generation from.
The counter you describe in (1) is part of my multiple-pulse burst, what I called "pulse" in the second timing diagram of reply four---that is, it is the same frequency and duty cycle as the pulses in the burst I want to generate.

The counter in (2) is the second half of my burst---it would inhibit the continuous output of the counter in (1) such that, in my case, I only get two pulses in "pulse". This counter is a retrigerable pulse with initial delay, which I should trigger by my reference signal.

But my reference signal is internally generated on a counter, thus the total is 3 counters.

What I just realized is that my method is internally using 2 counters for "pulse" if I try to generate two pulses or more. I had no idea, and now the fact that it behaves completely differently from a single-pulse signal makes sense.

But this is all the more reason that these should be differentiated more clearly in the library. It is confusing to have a change in one parameter completely alter the internal behavior of the machine like this. Do you not agree?

And again I must reiterate my complaint from other threads where I insist that the documentation is not adequate, nor are the examples. We must agree that if I gave you a Spanish-English dictionary and told you to learn Spanish you'd be in a jam. None of the information I have learned in this forum over several months is anywhere in the documentation---at least not where I could find it. In fact, without this forum, it would be impossible to write anything but the simplest program. I'm glad that at least you all do a great job of responding relatively quickly, or we would all be royally screwed.

It is easy to write a program to churn out one signal out of an 8-counter board, but I'm trying to push the board to its limits here, and all this ambiguous behind-the-scenes magic makes it very hard to do so.

I admit, I'm an amateur, not an experienced programmer, and I've never programmed one of your products to this extent. But I am in charge of some heavy documentation in my group and I do know what I'm talking about there.

Thanks Tom, for your helping clear up what's really going on with these multiple-pulse signals.

Emilio
Message 8 of 10
(5,390 Views)
Hi Emilio-
 
Your understanding of my explanation is correct.  I didn't realize that you were also generating your trigger pulses on the board- in that case you will indeed need three counters for the entire operation.
 
I also understand your frustration with the documentation- for a new user it is definitely somewhat fragmented, and we are actively trying to consolidate and clarify all of the available information.  If you have any specific suggestions or requests for improvement please let me know.  The easiest way to offer your suggestions is to file a product suggestion here.  Otherwise, if we can help out in any other way please let us know here on the forum or by contacting our applications engineers at www.ni.com/support .
 
If you need any more information for this application I'll be glad to help out.  Otherwise, good luck with the rest of your development.Smiley Happy
 
Thanks a lot-
Tom W
National Instruments
Message 9 of 10
(5,386 Views)

...am I not correct in saying something is broken? If indeed you can only have a re-ocurring delay for single-pulse signals, then there should be three timing modes: "continuous", "singlepulse", and "Npulses"...    I still don't know whether the low time comes before the high time, where this is in the documentation, and whether any of this is "broken" or not.

FWIW, I'd put in a vote for "broken."   Fortunately there's a pretty reasonable workaround as TomW posted.

I understand why NI wanted to offer a behavior where the first pulse has a different idle time than subsequent pulses, but it was added in a way that was NOT transparent to existing users.  For years, most of NI's DAQ vi's were designed so that if you left optional items unwired, a pretty normal & expected default behavior would happen.  I personally think that the "initial delay" parameter for pulse generation broke this trend. 

My opinion: if "initial delay" is unwired, the programmer is NOT INTERESTED in a special initial delay and the input should be IGNORED.  Pay attention ONLY to the regular pulse specs.  This defaults back to the traditional behavior before the initial delay parameter was introduced.  I find it kinda annoying that over and over again, I MUST wire a value to initial delay even though I don't want any special initial behavior.

I also got thrown off on the question of "low time before high time?".   I think I recall some docs stating that the low time happens first.  But in reality, that's true only for the default output polarity.  If you change it, then the high time happens first and the docs are wrong.  What IS always true is that the "idle state" comes first.  I suspect that part of the docs were written by someone who'd only dabbled with the counters and didn't even realize that "low time" is not necessarily always the same as "time spent in idle state."

All these things were more explicitly clear in the traditional NI-DAQ programming model for counters.  DAQmx has expanded some capabilities and has tried to abstract away some of the hw implementation.  I think it has brought fairly simple counter operations within the reach of a LOT more beginning users who may have been scared off by all the counter-specific jargon needed to talk about traditional NI-DAQ.  It has also brought in several new capabilities for more advanced users.  However, I think a bit of new confusion was introduced for those advanced users as well.

I've written docs before though, and I've been frequently surprised that stuff I thought was clear and thorough turns out to cause confusion.  It's really hard to get it right.  Hopefully NI will keep working to improve it.  Meanwhile, there's quite a bit of info here on ni.com, though you sometimes have to be persistent in your search queries.  Somehow, searching "entire site" leaves out the DevZone and forums.  And depending where you are on the site, the list of available categories to search keeps changing.   Then again, I'm glad I'm not responsible for organizing that quantity of information...

-Kevin P.

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 10 of 10
(5,371 Views)