07-31-2007 10:35 AM
How do you simultaneously latch values in multiple counters, at arbitrary times, for later reading?
A physical system generates several kinds of events to be counted by different counters, none of which events are strictly periodic or mutually synchronized (most of them are radioactive decay events, on the order 10^-3 to 10^5 per second average). It is critically important to count them all. At somewhat irregular intervals a few dozen milliseconds apart, I have the opportunity to read the counts, and it is also critical that whenever I read them, the counts are all captured at the same time, though it is not important exactly when this time is or how close in time I read them. Note: it is defining the end of one count period and start of the next that is time critical - not returning the count value to the calling program, which can happen whenever convenient.
I've used other counters that have a strobe-and-latch feature in past versions of this system, including Advanced Micro Devices' Am9513 and the good old 8254. When a read opportunity happens, I programatically strobe the counters then read each one's latched values at leasure, while the counters themselves continue counting. But I haven't found strobe-and-latch in either of my two NI hardware systems or in any of the LabVIEW vi's, properties, or examples. Is it there someplace, maybe by a different name?
I haven't found an example vi that simultaneously buffers counts in different counters. But it looks like some combination of the "Count Digital Events-Buffered-Continuous-Ext Clk.vi" example vi and the "Duplicate Count Prevention" method described in my DAQPad-6259 docs might get me what I want, but I'm not sure. I've attached one of my attempts to make this work, "SimultaneousCountBuffering01.vi". I have a single benchtop signal generator sending a 1 kHz signal to my DAQPad, where it's wired to both counter source terminals. This vi reads both counters at slightly different times on an irregular schedule repeating at about a half second. But it also first drives a digital output line high and low. This output is physically wired to both counter gate terminals. The DAQPad docs say that when counting in this mode, the counter is always counting regardless of the state of the gate, but at every positive edge on the gate, the count is buffered for subsequent reading. It's not important whether the readings are cumulative or get rezeroed because it's easy to use a shift register to change this anyway.
But I haven't gotten this vi or others like it to do anything useful. In this particular version, the counter reads time out. Maybe this means there's nothing sitting in the counter buffer? The examples don't seem to show anything making the counter buffer counts, so I guess that's done by the property node selecting Duplicate Count Prevention counting mode. I've checked various combinations of the digital out line state in this vi, by the way, but still the timeout happens. In my other attempts the counts are always zero, or occasionally jump by thousands, or only one counter will occasionally see only one count. Simpler vi's (that don't attempt the Duplicate Count Prevention and don't get synchronized count values) do work, and the counters both count at the expected rate.
Am I on the right track, using Duplicate Count Prevention?
If not, what approach should I be taking?
Even if this is the wrong approach, I still wish the vi did something, and am curious what I'm leaving out. Anybody know?
Thanks!
08-01-2007 05:17 PM
08-07-2007 03:01 PM
OK, now I have a VI that works and is close to what I want to do, and I have a VI that does not work but is what I think I want to do. I don't understand why they don't both work.
Based on your suggestion, David S., and thanks for that, I created TwoLoops01.vi. It is a modification of "Figure 5. Continuous Buffered Event Counting" in the reference you cite. I have two counters that are both being read in the same loop, and with shift registers I subtract the previous readings from the current ones to get the latest contributions to the cumulative counts, and then I subtract these two deltas to see if the result is zero, because I hope both counters get the same delta. And they do! Like in my previous attempt, there's a digital output going high and low which is physically wired into the sample clock source. But unlike my previous attempt, it is a separate loop that is driving the output high and low. Oddly, the loop counters for these two loops track each other - I guess because the reading can't complete until the line has gone high.
However - and here's the problem - I can't drive the line high and low within the same loop that's doing the reading. OneLoop01.vi tries to do this. As it is written, it will cycle several times, getting 0 differences which is good, but then the loop will stall and there'll be a timeout error on one or the other counter. Why???
I've tried several things to prevent these timeouts:
1) Increasing the timeout input to the read vi does not seem to make timeout less likely.
2) Because I think it's necessary that the sample clock source line cycle high before I try reading the counters, I tried wiring the error out of the last digital line out write vi to the error input of one of the counter reads. This should force the upper sequence to finish before the lower one starts. But every run of this VI times out on the first cycle.
3) Likewise if I continue running the error line out of the first counter and into the second, so neither can start till the upper sequence is finished. Still the same.
4) I even added another, later frame to the upper sequence and gave it another digital line deassert write vi and threaded the error through that, to make sure the variable time delay part of the sequence had finished before any counter reads, but still, timeout every time.
Since in my physical test I will want to trigger the buffering and then read the result, I don't think the two-loops vi (the one which works) imitates the way I need to use the counters.
Any ideas?
Thanks!
08-07-2007 03:02 PM
08-08-2007 10:11 AM
I don't have LV handy here, but I took a quick look at your OneLoop and TwoLoop attachments. If I remember correctly (I may be mixing those up with a couple other things I looked at), you face the following significant issues:
A. Need dataflow sequencing to help enforce execution sequence. With multiple data acq tasks, it's very typical to use the wind the error cluster from one task to another as a means to enforce execution sequence.
B. Need an overall scheme that doesn't keep configuring, running, and clearing each task in a software loop.
Let me roughly describe an approach I'd suggest:
1. Create a "dummy" AO task solely for the purpose of using its sample clock as a strobe for buffering your edge counts. Configure it for Continuous Samples using DAQmx Timing.vi The sample rate you choose will determine how often count values are captured ("strobed"). You may also need to set the property to "Allow Regeneration", found under one of the DAQmx Property Nodes (probably either the Channel or Write node). Write an array full of 0 values to the output buffer using DAQmx Write. (The actual value doesn't matter to the program, but 0 volts should be a safe value if you've got anything wired to your analog output terminals.)
2. Create 2 similar edge counting tasks with your counters. Both should be configured to use a digital "Arm Start" trigger using a DAQmx Trigger property node. That will guarantee that they are sync'ed at time=0. When you call DAQmx Timing.vi, wire in the input that lets you specify sampling using the AOSampleClock.
3. My personal choice for getting them all started in the right order would go like this. The counters would use the falling edge of the AOSampleClock as an "Arm Start" trigger and the rising edge of the AOSampleClock as their sample clock. The counter tasks are started before starting the AO task. After starting the AO task, the falling edge of the 1st AOSampleClock will "arm" the counters to start counting their edges simultaneously. The rising edge of the 2nd AOSampleClock will "strobe" the count values into the counter tasks' data acq buffers. Each subsequent rising edge will buffer the next counts.
4. Duplicate Count Prevention may need to be specified if there's a chance you might not see any edges to count between 2 consecutive sample clock strobes.
5. When you read from the counter tasks, be sure to read the same # of samples from each task. Then you can subtract the arrays to get your count differences, knowing that the counts correspond to the exact same interval of time.
-Kevin P.
08-08-2007 11:54 AM
Thanks, Kevin.
I posted a new thread (the title was something like "Buffered Event Counts: Why can't I sequence things?") at about the same time you were posting your reply, because I'd found enough new about the situation I'm really asking new questions now. But your reply is still relevant. Here are some points you address:
a) I have tried wiring the error flow to control sequencing as well as using Flat Sequences. Another LV programmer and I thought earlier today we were seeing that the two methods don't work exactly the same (?!), so I also tried wiring numerical results from vi to vi, while doing tricks to make the numbers themselves unimportant. For instance, I'd make the wait happen before the read by taking the ms output of the wait, divide it by 1,000,000, add 10 to the result, and pass that in as the timeout value (which would be 10.000000000000001 or something now instead of the 10 I used before).
b) I know about not configuring the task inside the loop, and don't think you saw that in my vi's.
Using a dummy AO task to tie its sample clock to my counter? I didn't think of this, I used a physical wire from a digital out port. I'll have to give it a try. But, is there a reason you'd expect it to work better, or is it just different or to save the physical wiring I already did?
Syncing the arming isn't important; in my physical experiment, counts early on get ignored, and they're all asynchronous radioactive decays. Only relative counts matter. I didn't gather whether you meant to rearm the counters every loop cycle, or just once, but I absolutely have to catch all the counts once the experiment officially begins and throughout a few thousand loops, so there's no rearming allowed.
Duplicate count prevention? Yeah, that's a worry if I need it. Someone else thought I didn't, and I don't know after reading the help docs about it. I haven't gotten things to work without it, yet, and in the mockup I'm developing on I can guarantee I'll always have nonzero counts for as long as I want to defer the question.
>When you read from the counter tasks, be sure to read the same # of samples from each task. ----- How do I do that? If I wire the data output from the read vi to something else using data, and they appear once in the loop, have I accomplished that? This is a very interesting point, because I think occasionally taking too many values would cause the problem I'm having - how might I have accidentally done that? How do I cause a wire that appears in a loop to take a value exactly once? Note, if I cause two pulses in my loop, which I tried, I never have timeout issues (though of course in doing so I am erroneously putting extra values into the buffer and therefore wouldn't be reading what I should be).
08-08-2007 01:53 PM
08-09-2007 09:19 AM
- Re: "dummy" AO task. Right, if you want to choose your strobe times in software based on, well, whatever, then the AO task may be the wrong way to go. I guessed wrong -- most folks' apps favor the regular constant sample rate you get with an AO task.
- Re: syncing the arming via triggering. Yeah, I see your point now. Since you control the sample clock "strobe", you can make sure that both counter tasks are armed and counting before you generate a strobing pulse. The only benefit of an arm start trigger would be to guarantee that the very first count values buffered were collected over an identical time interval. Without triggering you'll be starting the tasks in sequence, so one of them will collect counts for a little longer than the other. After the very first value, all the rest will represent the same time intervals.
I quickly modified one of the vi's you posted and added a few comments. There's no triggering or duplicate count prevention, but the code should demonstrate proof-of-concept.
-Kevin P.
08-17-2007 11:36 AM