Re: software vs. hardware timing
Hani's method should be a much more CPU-efficient method for getting your data as the loop execution timing will be driven by the hardware. When he directly calls DAQmx Read while wiring in the desired # samples, DAQmx Read won't return until detecting that the desired # of samples becomes available (or there's a timeout). While waiting, it will yield the CPU and there are even some DAQmx property nodes that let you fine tune this waiting. (This kind of behavior is one key benefit of the DAQmx driver compared to the legacy driver. Note that the Windows task manager may still report 100% CPU, but you'll be able to multitask because DAQmx will yield as necessary.)
Your method would gobble up CPU as it polls for # samples available as fast as the loop can run. In this sense, your method depends on application-level software timing to gather the data. You're right though that you should eventually get the same data either way. In a troubleshooting situation involving a kind of un-responsiveness though, it'd be good to avoid hogging CPU or memory resources wherever possible.
If I remember your app right, one further enhancement of Hani's method might be to request (triggers per step)*(samples per trigger) from DAQmx Read and get rid of the loop. After reading the complete chunk of data all at once, you can then break it down into chunks of ~1000 samples per trigger or whatever is the exact # of finite pulses you generate per trigger.
I find your "weird observation" intriguing. Often when a behavior tracks to some magic # like a power of 2, there really *is* some underlying and consistent explanation. I was about to speculate about the board's hardware FIFO, but just looked it up and saw that it's in the Mega-sample range. Still, I'd keep prodding about to explore whether the magic # behavior happens around the specific value of 1024, or whether it happens for other multiples of 16, or powers of 2, or whatever.
Thanks for the clear explanation Kevin. I made a little test program to try using from 1 to 1024 samples per trigger. For each value I would run the loop 1,000 times (i.e. 1 trigger per step, 1,000 steps). I set the timeout value in the DAQmx read so when the pulse train stops triggering I would get an error. I recorded how many loops were acquired before an error for each number of samples per trigger as well as the amount of time taken to acquire the data vs. the expected time. See the attached pictures and the vis I used. It looks like I generally get no errors (at least for 1,000 steps) for values up to around 384 steps per trigger. After this point every multiple of 16 works. Other values usually fail. I have noticed that putting a slight delay after the DAQmx read seems to help. For example putting a conditional probe on the error from DAQmx read greatly improved the number of times I successfully acquired 1,000 steps. After I saw this I fooled around with putting a dummy loop in to cause a delay and that also seemed to help. I don't think I want to put an actual sleep call there since my trigger rate is 100 Hz and in my previous experience with Windows it seemed like the minimum sleep time is usually 10 ms. So that's the first problem.
The other thing I noticed was that for values of samples per trigger that were not multiples of 16 it took about twice as long as it should have to get the data. I had noticed earlier that if I didn't specify the number of samples to read in the DAQmx read it returned data in multiples of 16. If I had 2 samples per trigger, the DAQmx read (with no sample number specified) returned only after 8 triggers (giving me 16 data points). The disconcerting thing now is that I if actually specify 2 samples to the DAQmx read it still takes 8 triggers to return but only gives me 2 data points, apparently discarding the other 14! From my timing measurements specifying 2 samples per trigger took 8 times as long, 3 samples took 6 times as long, 4 samples took 4 times as long, etc. Above 16 samples per trigger, only multiples of 16 took the expected amount of time, everything else took twice as long. It seems the DAQmx read only returns when has the number of data points specified, then rounded up to the next multiple of 16. I've watched the pulse train on a scope and confirmed that it's not that its missing triggers. That's the 2nd problem.
To me the 2nd problem, while undocumented and annoying, isn't a big deal; I prefer powers of 2 since I later perform an FFT on it. The first problem with the pulse trains stopping triggering is a problem that I would like to fix. Also, I can't really use your suggestion of reading in multiple triggers in one block. I'm trying to fit the data from each trigger in real time and the time it takes to fit is only slightly less than my trigger rate. NI people, is there someone that is an expert in the pulse train generation that can comment? Can I talk to someone (I don't have a service contract) since this really seems to me to be a bug in a board and/or software that I've just purchased?
After this point every multiple of 16 works. Other values usually fail. I have noticed that putting a slight delay after the DAQmx read seems to help.
I don't have LV near my network PC and can't examine the code now. The fact that a slight delay after the read helps should prove to be a very helpful clue though.
The second problem sounds to me like a board-specific behavior. I've read other threads where certain boards would not return single 16-bit samples. They waited to pack two of them into a 32-bit wide data chunk before transferring to system memory. I don't know your board in detail, but your description sounds like your board only wants to transfer data in 16-sample multiples. When you want 2 samples per trigger, it waits for 8 triggers to accumulate the 16 samples -- thus 8x factor. When you ask for 3 it waits for 6 triggers to accumulate >= 16 samples, ask for 4 or 5 each and wait for 4 triggers, etc.
There's a chance that there are DAQmx properties allowing you to change this behavior, but I don't know for sure. I'm also only speculating in my diagnosis above. Can anyone from NI comment?
The problem of the counters only retriggering properly for a while, then failing to respond, then "coming back to life" is not one I recall reading about previously on the forums. I don't really know if that'll be good news or bad news to you, but it seems to be a fairly unique problem rather than a general, commonly-experienced bug.
I will be looking into why multiples of sixteen for your samples per trigger produces the appropriate number of steps.
I have also been looking through your initial posts and I see that you had originally modified the example Multi-Function-Ctr Retrigg Pulse Train Generation for AI Sample Clock.vi. I noticed that you will be changing external parameters after a predetermined number of triggers occur. I assume that these changes will be made after the tasks are stopped and before they are restarted. Will this functionality be added to the code at a later date? I ask because it is not necessary to stop and restart the DAQmx tasks if there is no change to any of the properties of the counter or AI task.
In order to correct the counter glitch you are seeing, it is necessary to reproduce the issue. I see that you mentioned a scope in a previous post and if it is possible, could you scope the pulse train and trigger signal and trigger the scope off of the trigger signal? Screenshots of this would be most helpful. Along this line, please make sure that the trigger signal you are using matches TTL specifications and is properly terminated on the DAQ card.
Also, could you read the trigger signal and the pulse train in using the analog input channels of your card? This is possible by performing a continuous analog input task independent of the pulse train generation task. You can continue to stop and restart the counter task, but the AI task should be continuous so that no triggers are missed. Please include the code you use to perform this test as well as screenshots so I can also verify it on my end.
I've attached the files requested. Had problems finding a scope I could save a capture on so I ended up doing it the old-fashioned way. One picture is zoomed in showing the trigger and a few of the sample clock pulses. The other shows the length of the whole pulse train. Note these are taken when the pulse train actually triggers. When it doesn't I see the trigger and nothing on the pulse train channel (usually zero volts, occasionally 5 volts). This is how I've been able to tell that only the counter train stops working. For these pictures I had a sample clock rate of 2.5 MHz, 511 samples. The trigger is 1 us wide at 100 Hz. My connections to the board are made through a BNC-2110 box.