Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Arm Start Trigger for buffered events counting PCI 6602

Solved!
Go to solution

Hello,

 

I am using a NI-6602 card and I am using 2 counters input channels to perform buffered event counting on each counter. The signals are TTL pulses arising from photon detectors.


Everything works fine except that the two counters do not start at the same time. And it is essential for my application that they do.

 

I tried to use the Arm Start Trigger property but it does not work. In a bit more details, here is what I did (in C#) :

 

// Sample Clock
myTaskSampleClock = new Task();
myTaskSampleClock.COChannels.CreatePulseChannelFrequency("Dev1/ctr3", "", COPulseFrequencyUnits.Hertz, idleState, 0.0, sampleClockFrequency, sampleClockDutyCycle);
myTaskSampleClock.Timing.ConfigureImplicit(SampleQuantityMode.ContinuousSamples, 1000);
myTaskSampleClock.Start();


// Counter 1
counterReadTask1 = new Task();
counterReadTask1.CIChannels.CreateCountEdgesChannel("Dev1/ctr1","", edgeType, initialCountValue, countDirection);
counterReadTask1.Timing.ConfigureSampleClock("/Dev1/PFI24", sampleClockFrequency, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, sampleClockFrequency);

counterReadTask1.Triggers.ArmStartTrigger.ConfigureDigitalEdgeTrigger("/Dev1/PFI0", DigitalEdgeArmStartTriggerEdge.Rising);

myCounterReader1 = new CounterReader(counterReadTask1.Stream)
myCounterReader1.BeginReadMultiSampleInt32(sampleClockFrequency, myCallBack1, counterReadTask1);

 

// Counter 2
counterReadTask2 = new Task();
counterReadTask2.CIChannels.CreateCountEdgesChannel("Dev1/ctr0", "", edgeType, initialCountValue, countDirection);
counterReadTask2.Timing.ConfigureSampleClock("/Dev1/PFI24", sampleClockFrequency, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, sampleClockFrequency);

counterReadTask2.Triggers.ArmStartTrigger.ConfigureDigitalEdgeTrigger("/Dev1/PFI0", DigitalEdgeArmStartTriggerEdge.Falling);

myCounterReader2 = new CounterReader(counterReadTask2.Stream);
myCounterReader2.BeginReadMultiSampleInt32(sampleClockFrequency, myCallBack2, counterReadTask2);


// Trigger task
Task triggerTask = new Task();
triggerTask.DOChannels.CreateChannel("/Dev1/port0/line0", "", ChannelLineGrouping.OneChannelForEachLine);

DigitalSingleChannelWriter StartTriggerWriter = new DigitalSingleChannelWriter(triggerTask.Stream);
triggerTask.Control(TaskAction.Verify);

 

// Write the digital edge
StartTriggerWriter.WriteSingleSampleSingleLine(true, false);
StartTriggerWriter.WriteSingleSampleSingleLine(true, true);
StartTriggerWriter.WriteSingleSampleSingleLine(true, false);

 

In words :
I define and set up my sample clock (used by the 2 counters)
Then I create my 2 readers and set up their ArmStartTrigger properties.
Finally, I define my arm trigger as a DOChannel and write an edge that should start both readers.

 

But this is not working. I get a timeout error saying that samples haven't been acquiered (er -200284), so it looks like the trigger is never activated. I looked at many forums but didn't find a solution in C#. Do you have any idea why it's not working ?

 

Any help would be very appreciated !

 

Thanks,

0 Kudos
Message 1 of 8
(233 Views)

I only know the LabVIEW API and can't really help with *details* of C# (or any other text language) programming.

 

That being said, I don't see anything that raises any alarms.  FWIW, the error you mention -200284 could also arise from not "seeing" the sample clock signal at PFI24 (the apparent default output pin for CTR3).

 

I'd start troubleshooting by breaking down to much simpler tests.  Here are things you could consider trying:

- use your code solely to generate a continuous pulse train on CTR3.  Then go into MAX test panels and try to count edges from PFI24.

- once you confirm pulses on PFI24, add a single edge-counting task to your code.  Have it count edges on PFI24.  Don't configure Timing or Triggering, just let it be a simple software-timed on-demand edge counting task.

- once you see those counts, add in an Arm Start Trigger.  Start by triggering off an always-present signal such as the 100kHz internal timebase.  When *that* works, switch over to your original scheme with PFI0 / a.k.a. digital port 0 line 0.

 

Basically, work through the different elements step by step to isolate the part that isn't working right.

 

 

-Kevin P

0 Kudos
Message 2 of 8
(193 Views)

Hello Kevin,

 

Thanks a lot for your quick answer. I have started the tests you suggested and I am still on it! 

I will come back to you later on to let you know how it worked.
Thanks again

0 Kudos
Message 3 of 8
(176 Views)

Hi again,

 

So I did everything you mentioned, it helped me having a deeper understanding of the concepts, thanks.

 

I now start the sampleclock after the readers and it’s better. However, my problem is still the same. Maybe there is something I’m not correctly understanding. Please tell me if something is wrong in the following reasoning :

 

  • BeginReadMultiSamplesInt 1 starts reading values from counter 1. Waits for sampleclock edges to transfer data to the buffer.
  • BeginReadMultiSamplesInt 2 starts reading values from counter 2. Waits for sampleclock edges to transfer data to the buffer.
  • Start sample clock start transferring data to the buffer


To do the tests I send an identical signal (periodic burts of TTL) to both counters.

 

If my assumption is true, then when starting the sampleclock AFTER the readers, the values of each counter should be the same physical event with maybe a slight amplitude gap due to the initial value of the first measure, as explained on this figure :

 

image NI.jpg

 

 

 

And if you call data1 the results of reading 1 and data2 the result of reading 2 I should have something like this :

 

data1[n] = data2[n] + (data1[0] – data2[0])

 


But for some reason I don’t understand, when doing so, there still is a slight time difference. I have something like this :

 

data1[n] = data2[n-delta_t*f]

 

where delata_t is the initial time difference between the beginning of reader 1 and 2 and f the sampleclock frequency (note that I don’t have any amplitude gap because I’m measuring a lot of zeros).


So to sum up, using only one sampleclock (or triggering 2 sample clocks) and starting it afterwards will assure that I’m measuring data at the same time.

 

However, it seems like it’s not enough because of the time difference between data, so I guess I also have to start both readers at the same time. But I can’t find a way to start both readers at the same time, do you know if there is a way to do this ? Arm-triggering doesn’t looks like doing the trick (first post).

 

I’m beginning to wonder if it’s even possible to do such a thing. I recently read this, but I’m not sure I understand it right : https://zone.ni.com/reference/en-XX/help/370466Y-01/mxcncpts/synccounters/

 

Thank you again for your time.

 

 

0 Kudos
Message 4 of 8
(145 Views)

There's a lot of things, so I'm gonna try to answer inline in red.  (Wish the forum framework would support quoting and threading as least as well as, say, USENET back in 1995.  Maybe it'll catch up in some future decade...)

 


I now start the sampleclock after the readers and it’s better. However, my problem is still the same.
Yes, that was a good fix to start the sample clock *after* you start the counting tasks.

Maybe there is something I’m not correctly understanding. Please tell me if something is wrong in the following reasoning :

 

  • BeginReadMultiSamplesInt 1 starts reading values from counter 1. Waits for sampleclock edges to transfer data to the buffer.
  • BeginReadMultiSamplesInt 2 starts reading values from counter 2. Waits for sampleclock edges to transfer data to the buffer.
  • Start sample clock start transferring data to the buffer

Sounds like you've got it right.


To do the tests I send an identical signal (periodic burts of TTL) to both counters.

 

If my assumption is true, then when starting the sampleclock AFTER the readers, the values of each counter should be the same physical event with maybe a slight amplitude gap due to the initial value of the first measure, as explained on this figure :

 

image NI.jpg

 

 

 

And if you call data1 the results of reading 1 and data2 the result of reading 2 I should have something like this :

 

data1[n] = data2[n] + (data1[0] – data2[0])

 

Agreed.  Makes sense.


But for some reason I don’t understand, when doing so, there still is a slight time difference. I have something like this :

 

data1[n] = data2[n-delta_t*f]

 

where delata_t is the initial time difference between the beginning of reader 1 and 2 and f the sampleclock frequency (note that I don’t have any amplitude gap because I’m measuring a lot of zeros).

 

But in the test you're running with both counters seeing the same edges to count and the same sample clock, doesn't the formula above mean pretty much the same thing as the previous one?   The first formula emphasizes that counts at a given index differ by a constant amount, defined by the difference in counts at index 0.   The second formula emphasizes that the counts at a particular index for one counter can be found by offsetting the index for the other counter by a constant amount.

    Both are saying that if you plotted your 2 tasks' count values vs time, they would be parallel lines.  They'd have the same slope, but there'd be an offset.  The first version simply happens to measure the offset vertically while the second measures it horizontally.  That said, the first version is probably a more useful approach because you'll always have an integer value for the vertical offset.  The second is liable to give you a non-integer horizontal offset which doesn't map cleanly to your discreet integer indices.

 
So to sum up, using only one sampleclock (or triggering 2 sample clocks) and starting it afterwards will assure that I’m measuring data at the same time.

 

However, it seems like it’s not enough because of the time difference between data, so I guess I also have to start both readers at the same time. But I can’t find a way to start both readers at the same time, do you know if there is a way to do this ? Arm-triggering doesn’t looks like doing the trick (first post).

 

I can vouch for the Arm Start trigger as something the hardware and driver support.  There must be something wrong or incomplete in the syntax, which I don't know for any text API's, but what I *do* see generally appears correct and complete.

 

I’m beginning to wonder if it’s even possible to do such a thing. I recently read this, but I’m not sure I understand it right : https://zone.ni.com/reference/en-XX/help/370466Y-01/mxcncpts/synccounters/

 

That article isn't relevant here.  It refers to tasks that use "Implicit" timing such as period or frequency measurement.  You're using normal sample clock based timing with two tasks sharing the same clock signal.

 

But what you're trying to do IS possible.

I tried to do a little searching.  Here's one thing I found that might help, at least partly.   While the syntax has some general differences compared to the C# you posted, one thing I found worthy of note is that it seems to require pair of related calls to fully configure the Arm Start Trigger as seen below.   See if you can find a function in your API that's analogous to the first one below where one sets ArmStartTrigType=DigEdge.

 

DAQmxSetArmStartTrigType(taskHandleCtr0, DAQmx_Val_DigEdge);

DAQmxSetDigEdgeArmStartTrigSrc(taskHandleCtr0, "/Dev1/ai/StartTrigger");

 

 

-Kevin P

0 Kudos
Message 5 of 8
(123 Views)

Hi Kevin,

 

Thanks a lot for your answer and the information therein.

 

First of all: you were right to vouch for the Arm Start Trigger as I finally managed to have it working out. Thanks for the confidence you gave me in the procedure, I was close to giving up!

 

Starting the sample clock after the counters helped reducing the gap between data, but didn’t set it 0.

 

So the point was to be able to also trigger the counters. However, when doing so:

  •  without explicitly starting them (ie no CounterReadTask.Start(), just the BeginRead method), nothing was counted;
  •  with explicitly starting them (ie CounterReadTask.Start(), then BeginRead method) a “error -200278 : attempted to read a sample beyond the final sample acquiered” appeared.

 

... which led me to think it was not working. However,  after a bit of observation, I noticed that triggering the counters with the CounterReadTask.Start() did in fact work but only for one read. Then the error occurred.

 

I therefore introduced a stop() and start() on the different tasks (CounterReadTask and Sampleclock) for each counting loop (in the callback method) and created a timer to periodically write an edge on the ArmTrigger Terminal. And it worked perfectly !!

 

Thank you again and a lot for your help!

0 Kudos
Message 6 of 8
(92 Views)
Solution
Accepted by topic author Edouard_Wagner

I don't know enough about your system, its behavior, and the overall needs of your app well enough to say anthing definitive here.  Let me just add a little food for thought.

 

Some situations *require* an approach that stops and restarts a task repeatedly.  Others don't require it but are also not harmed by that approach.  Some others are slightly harmed by it, and still others are harmed quite a bit.   In these latter cases, it can be important to determine whether the stops / restarts are truly *necessary* or whether they were merely a *convenient* way to get a solution that was "good enough".

 

So that's all background to say this:  I suspect there might be a way to accomplish your original goal without needing to stop & restart.  Whether that's valuable enough to pursue harder is something I don't know enough to offer an opinion about.

 

 

-Kevin P

0 Kudos
Message 7 of 8
(62 Views)

It might indeed not be the simplest/easiest/more pertinent way to do it. For the moment, the counters count and are synchronized so it is enough to move forwards.By I keep in mind your "little food" and might come back to it.

Thanks again for all your advices and experience.

 

0 Kudos
Message 8 of 8
(41 Views)