Perfect--that fixed the issue. The AI and counter tasks working now after changing the clock source to "/Dev1/10MHzRefClock", as you suggested.
Very much appreciate you sharing your insight/tips/tricks/wisdom/knowledge. I had programmed LV a lot back in the day before DAQmx came around, but never to this point had I worked with syncing multiple boards before. A new adventure and learning experience for me...and many thanks for your help!
If I may, I have one last question, for my own edification w/ DAQmx and timing multiple tasks:
In addition to the AI and counter tasks that were the subject of this original post, I have an additional AO task running simultaneously. After I fixed the AI/counter issue, I ran my VIs thinking everything was kosher. However, I got the same error (-89137) as before because the AO RefClk.Src was not being set to "Dev1/10MhzRefClock", as it was with the AI and counter tasks. I was able to fix this using the same procedure--DAQmx Timing property Node with RefClk.Src and RefClk.Rate being set appropriately. Everything works just as it should, though I am worried that what's going on "under the hood" might not be what I think. Here's why:
The design of the system is that the finite pulse train (counter output) serves as the AO clock source. Basically, I have 3 AO values to write--say -2, 0, +2 V--and I want each sequential value in this list to be written when the AO clock source sees the counter pulse, which defines the timing I need. So, I have AO clock source set to "Dev1/Ctr1internalOutput" using the DAQmx timing.vi, which you can see in the screen shot (and/or code attached to this post.) However, I needed to insert the DAQmx Timing property node, setting RefClk.Src and Rate. Thus, I wonder whether the AO generation is actually being triggered the way I think it is using the counter output, or if it using the 10 MHz ref clock? If the former, then great. But I have an uneasy feeling this isn't actually what is happening, and that the timing is defined using the 10 MHz ref clock alone. In that case, I'm glad my system is up and running, but I really hate not knowing what's going on.
How can I tell which of these is actually the case? I guess I could route the AO channels clock source to a PFI and just measure it...but would be nice to have a fundamental grasp on how timing/clocking in DAQmx works in this case. DAQmx is great b/c it is overall easier to use, but, oh, the days when everything was more transparent (or maybe I'm just growing stupider...certainly wouldn't rule that one out 😃 )
Thanks again for all your help!!
And thanks, kevin price, for the initial optimism/inspiration that I could actually do simultaneous AI, counter, AI tasks.
ps The screenshot shows the relevant section for the AO generation task. Within the .zip archive is the file "AO Pulse Prep and Gen.vi", which is where the AO is actually being done.
Yes, DAQmx still requires your AO task's reference clock settings to be compatible with those of your other tasks when you are using an external AO sample clock. I'm not 100% certain whether any of the AO trigger/FIFO/DAC interface circuitry is necessarily synchronized to the output of the reference clock in all cases, but I do know that DAQmx will not allow you to change the reference clock source while an AO task is running.
You can certainly route ao/SampleClock to a PFI line and use a scope, logic analyzer, or counter/timer to verify that it has the expected signal characteristics. There's nothing wrong with double checking that your system does what you are programming it to do. But if you just want a simple sanity check that DAQmx is using the external sample clock, increase the value of SampClk.Rate and verify that the waveform is not affected. With an external sample clock, SampClk.Rate is interpreted as the maximum expected rate for the external clock, and does not directly affect the timing of the AO sample clock.
As for transparency in the DAQmx API, you can find out a lot of information about what DAQmx is doing by reading back properties after verifying the task. For example, when you are using an internal sample clock, M Series can only produce sample rates that are an exact divisor of the timebase frequency, so reading back SampClk.Rate will tell you the actual sample rate. Another example: with an AI task, you can ask DAQmx which input range was chosen by reading back AI.Rng.High and AI.Rng.Low; to get this same information in engineering units used by a sensor or custom scale, read back AI.Max and AI.Min. It's even easier with .NET, because all of the properties show up in the debugger.
If you have any suggestions for how to make DAQmx more transparent, by all means feel free to post them to the DAQ Idea Exchange.
For the sake of any future reader coming into this thread who manages to make it this far, I just wanted to rewind back near the beginning for a moment to make the following point:
Much of the detail and complexity involved here appears to be caused by the inherited AI code's explicit use of the Reference Clock. There may be good reasons to leave it that way in this app, but in many cases it would be much simpler to let DAQmx use its default timebase and not override it.
I've frequently run clocked AI and counter tasks simultaneously on an M-series board. My AI configuration specifies a sample rate but never makes any specific request about the timebase source for the sample clock. Consequently, the board uses the default 80 MHz internal timebase to derive a sample clock, and NONE of the discussed routing complications ever arise. Both AI and counter tasks happily share the 80 MHz internal timebase without routing conflicts or errors.
(To sync a 2nd board, as in this discussion, tasks on the 2nd board *would* need to explicitly request "Dev1/80MHzTimebase" or whatever the exact name is. In my experience, that can be handled by DAQmx under the hood via RTSI without conflicting with tasks on board 1.)
In short, it is normally very EASY to configure multiple simultaneous tasks on an M-series board by simply letting DAQmx select the default internal timebase.