05-19-2021 03:16 PM
Hi friends!
I desire to count the number of pulses on a PFI line for a fixed time after a trigger is received. This process should be hardware timed (not software timed). The counter should be reset after the gated counts are recorded so that when the next trigger arrives, the counter starts from 0. The gate time is 25 ms every 1s or so.
I started from this example:
The code simply uses a counter input task (that is pausable) to count the pulses and a counter output task (used to pause the counter).
My additions to the code from the link above are:
1) a primary control TTL task that I will use to trigger the gate task that triggers the counting.
2) DAQmx Implicit timing vi such that the gate task only produces a single pulse per trigger.
When I run the code, I find that the primary control TTL task and the gate task appear on their respective PFI lines as programmed (Yay!).
The "gated counts" waveform chart however, updates even when the counter is paused (many zeros are displayed). This is in agreement with my while loop timer that shows that the while loop is running more than 10 times during a gate period. Furthermore, there are multiple none-zero counts plotted while the counter is active (gate is high).
I only desire to know the total number of counted pulses during a gate period. I thought that my "is task done" vi would mean that the while loop would wait to read the number of counts during a gate period until after the gate task had finished. Apparently not.
What do I need to change in order to read only the total number of pulses counted during a gate period? Or, said another way, what do I need to change such that my while loop only executes once the gate task has completed?
I have tried replacing the "is task done" vi with a "wait until done" vi but found that this vi simply timed out. This suggests to me that perhaps the gate task is never completing.
Thanks!
Software: LabVIEW 2019
Hardware: USB-6211, USB- 6218
Solved! Go to Solution.
05-19-2021 06:14 PM
The problem is that a retriggerable task never considers itself to be "done".
Let's get the important stuff all in hardware:
1. For your "Pulse counter task", add a call to DAQmx Timing configured to do continuous sampling with a sample clock. Use the falling edge of the gate counter as the sample clock source. Estimate a rate because DAQmx will use the sample rate value to auto-size the task buffer.
2. So now it's pause-triggered to count only while the gate counter output is high, and will buffer up a count value each time the gate counter output goes low.
3. A simple finite difference of these cumulative count totals will tell you the # pulses seen during each gate interval.
4. (Note: your gate counter doesn't need to call DAQmx Timing at all. You can simply remove it to get retriggerable single pulse behavior.)
5. Be careful when changing your primary control counter pulse params on the fly. For every pair (whether freq / duty cycle or high / low time), one of the properties is "active" and the other is "passive". If you write only to the "passive" property, it will not actually take effect until you subsequently write to the "active" property. Consequently, you should put the active property on the bottom of the property node.
I know frequency is active while duty cycle is passive. I *think* I recall determining that low time is active while high time is passive, but I don't really trust my memory on that. You'd better do some experiments yourself.
6. There's a next step available where your pulse counter task is changed to be a period measurement task. This requires some kinda "inside-out" thinking about the signals and their meaning, so let's get the simpler version in steps #1-3 working first. I tracked down one of the old threads I've been in that did some further explaining about the thinking.
-Kevin P
05-20-2021 10:39 AM
Thanks for your suggestions Kevin_Price.
Attached is my new vi (version b). Here are the changes I made:
1) remove DAQmx timing vi from gate task
2) add DAQmx timing vi to counter task
3) move counter task start task vi to before the while loop.
4) delete stop task vi (inside while loop)
4) subtract subsequent counter reads (inside while loop)
Upon starting the vi I see error -200145 at DAQmx start task vi. "Pause trigger is only valid for event counting fi sample clock is not used".
I am not sure what to do about this error. Thoughts?
Concerning the primary control counter, indeed that took much trial and error. I have confirmed it does function as desired, despite being rather goofy.
I agree with your final statement that I should focus on getting the simple version functioning first. Having the counter reset to zero is important because the counter will eventually roll over causing a measurement to be incorrect. On average I count about 100,000 pulses each 1 s cycle and need to be able to make accurate count measurements for weeks at a time.
Thanks again for your guidance!
05-20-2021 11:19 AM
Does my application require a buffered edge count if all I want to know is the final value of the counter once the counter is paused?
05-20-2021 03:46 PM
Drat! I've gotten used to the counters on X-series boards (63xx) that can support a pause trigger and sample clock simultaneously. I forgot some of limitations of M-series counters.
I've got a bias for doing stuff with hardware timing wherever possible, but I'm not sure it'll be possible with your hardware. After re-reading your first post where you expect only about 25 msec of counting time per second, I think software timing should be able to work for you.
So never mind the call to DAQmx Timing that sets a sample clock and creates a buffer. Instead, we'll use a different method (since the Task Done? query didn't work out) to decide when to take a count reading.
If I understand correctly, you'll need a way to detect whether or not a new 25 msec gate period has happened to let you know that you'll need to read the count and then reset the counter back to 0. I'd use the last of the 4 counters you have between your 2 boards for this. Set it up for edge counting on the falling edge of the gating pulse.
Then you'll monitor this count value in a reasonably fast polling loop. When you see the count increment, you know it's time to read the count value you care about.
Oh, and one more fun fact: if you do your count difference with the native U32 datatype, the count difference remains correct even when the count rolls over! (Try it and see.) So there's probably no need to go after the period measurement method for counting that does hardware-based count resets. (It also may turn out that on M-series boards like yours, pause triggering and period measurement may turn out to be incompatible. I just don't recall now.)
I had a few minutes at the end of the day to modify your code a little to show what I mean. Not 100% sure I got everything right b/c I did it quick, but it should at least be pretty close.
-Kevin P
06-15-2021 12:41 PM
Kevin,
Thanks for your swift reply. I apologize for my tardy reply. Today was the first opportunity I had try your solution. It appears to function as desired.
In order to hopefully save someone else the trouble shooting time in the future, I would like to pontificate on what I have learned. I was able to get the code found in the link of my original post to function by placing all of it in a while loop. I knew it was bad practice to re-define the counter tasks each time, but at least it functioned. Eventually I found that the code was effectively missing triggers intermittently. I found that I could cause the triggers to be missed by opening the block diagram of the vi and then "grabbing" the screen and quickly shaking the code back and forth. This suggested to me that the latency associated with redefining the counter tasks each loop cycle was sufficient to miss triggers if labview had too many other things to work on (like redrawing the code on my screen as I "shook" it back and forth). This is what lead me to my post on this forum.
Kevin's solution does not appear to miss triggers when I shake the block diagram back and forth even though it is software timed.
Thanks Kevin!