07-20-2018 03:49 AM
Dear Kevin,
thanks for your tipps - and you are right, I just overlooked some basics.
I tried to implement your tips, but failed again;
"Your AI task is set to be retriggerable. It appears you want to retrigger at certain points within the AO such as positive zero-crossings"
Yes - this would be very much what I want to do.
I can't lower the sampling rate for the AO channel, since it is used to actually do something. It writes with changing frequency, but without allowing regeneration/phase hopping.
Parallel to driving the AO output I need the actual written data for an internal LockIn Algorythm. This is were I fail.
Am I missing the difference between ticks and frequency?
Also, when I am reading back my measurement signal with the AI; I need this block of samples in a fixed phase relationship to the AO(because of the LockIn) e.g. the zerocrossing.
thanks
Christian
07-20-2018 12:06 PM
The code's getting better. I can see you've addressed the things I mentioned before.
I still don't clearly understand the exact details of what you need from the CO and AI tasks. I need a more complete description of what you meant by:
@ChristianKi Parallel to driving the AO output I need the actual written data for an internal LockIn Algorythm. This is were I fail.Am I missing the difference between ticks and frequency?
I *suspect* you may want to continue to retrigger your AI from the Ctr0 output (as you've set it up already), BUT use a normal internally-derived sample clock for AI and quite possibly run AI sampling at a higher rate than AO sampling.
The re-triggering will sync you to the right phase of the AO waveform *PROVIDED* you set up the right relationship between your pulse specs and the # of samples per cycle of the AO waveform. The polarity of that pulse will be important as well so you need to know the distinction of where the rising and falling edges will be relative to the AO waveform so you know what to trigger from..
To help move toward mutual understanding, I'll describe what I see now from the code and default control values. Maybe that'll help identify where "what I see" is different from "what you want."
1. AO runs off a precise internal timebase. You do a very good thing where you query the actual sample clock rate and use it for your signal generation (instead of using the nominal requested rate).
2. AO is set to run at 20 kHz nominal (and it will be able to do this frequency exactly). You've explicitly set your buffer to be 5000 samples long which is equivalent to 0.25 seconds worth of AO signal.
3. Each iteration of the AO loop, you attempt to write a full 5000 samples to the buffer. I'm not sure this is a good plan. My general preferenece is to write no more than about 1/3 to 1/2 a buffer length at a time. In the old days, attempting to write full-buffer blocks of data would often lead to underflow errors. I *think* DAQmx has gotten more sophisticated at handling this situation, but I still prefer to limit my writes to 1/3 to 1/2 buffer size. It's tried and true, and I'm a bit of a geezer that doesn't always like relying on shiny newfangled features.
4. At least at a quick overview, the rest of AO seems fine.
5. The CO task will derive its timing from the AO sample clock signal. It's now properly sequenced to start *before* the AO task starts generating that sample clock signal. Good so far.
6. Your pulse specs are going to be crucial in making sure that the output pulse edges occur exactly where you want them with respect to the AO waveform signal you're generating. However, you set the the pulse specs manually with front panel controls
and nothing makes them correlate to the characteristics of the AO waveform.
7. Further, your AO loop allows the waveform frequency to be changed on the fly. As that changes, the pulse specs would also need to change to make sure the edges occur right at the 0 crossings. (This is probably why the not-quite-functional DAQmx Write for the CO task was in the loop in the original code. I suggested getting rid of it and you did, but now I see that it may be necessary to put it back.)
8. In strict terms, if you allow arbitrary changes to the AO waveform frequency, you can't really keep the counter edges in sync with the zero crossings. There are two factors why:
- there's a variable time between when you write AO data to the task buffer until it turns into a real-world signal at the output terminal. You're pushing blocks of data into the buffer while the driver pulls it out and delivers it to the board. There will be some ebb and flow to the latency.
- the exact timing of *when* counter pulse specs are changed would be largely governed by a software call to DAQmx Write. The exact timing of when the AO data is written to the task buffer is also governed by a software call to DAQmx Write. This software timing will also not maintain perfect sync.
9. You may need external circuitry that can generate a pulse on every zero-crossing. Then use *that* pulse as the AI trigger.
10. AI is configured oddly. Sample timing is driven by Ctr0 pulses which are generated by dividing down the AO sample clock. Presently you have Ctr0 set up with 1000 tick period so you'd get 1 AI sample per 1000 AO samples.
11. You probably want to sample AI *at least* as fast as the AO rate, and maybe faster. If you don't wire the 'source' input to DAQmx Timing, DAQmx will derive a sample clock from an internal timebase. As presently wired, you're asking for the same sample rate as AO. It should be ok to start there.
12. AI is doing Finite Sampling which makes sense when you're retriggering. But the # of samples is presently set independently. It probably should be related to some characteristics of the AO waveform you generate.
However, if it *is* calculated based on AO waveform characteristics, it's once again problematic to change the AO waveform on the fly.
13. Overall, it seems that the desire to make arbitrary, on-the-fly changes to your AO waveform is in conflict with your desire to set precise timing of your CO pulse and your (likely) desire to capture an appropriate duration of AI (which is aligned to the CO pulse).
You may need to consider constructing a more controlled and pre-defined changing AO waveform. Your device also supports generation of a pre-defined variable rate pulse train. You can then do what you need with AI either via retriggering or careful post-processing based on your knowledge of how you've predefined the AO.
-Kevin P
07-24-2018 03:59 AM
thanks a lot for your help&time!
I checked my application and I think I will let go of the "changing the frequency" feature.
Therfore I can just reinitialize both tasks when I do want to change the frequency of the analog out.
"The re-triggering will sync you to the right phase of the AO waveform *PROVIDED* you set up the right relationship between your pulse specs and the # of samples per cycle of the AO waveform. The polarity of that pulse will be important as well so you need to know the distinction of where the rising and falling edges will be relative to the AO waveform so you know what to trigger from."
this helped a lot, going to implement it.
07-25-2018 05:55 AM
sorry to bother again.
I still can't get Analoge output and my Tick Counter synchronized. I assume I fail at getting the ticks time correlated to my output frequency.
Do you, does anybody see the mistake, why Counter and Analogue output are not synchronised?
my final goal is to read the Input triggered with the zerocrossing (plus delay) of the analogue output to maintain a fixed phase relationship.
Therefore I hard wired my Anlogue input to my analoge output. Therefore I read the oringal AO back with an AI channel and the phase of the resulting reada waveform should be always the same (Only sines, I wrote phase should be zero by mistake in the .vi _it should be constant!)
best regards
Christian
07-25-2018 06:38 AM
Your calcs for the high time and low time of the CO task don't look right.
The sum should equal the # samples in one cycle of your waveform. You drive the CO task with the AO sample clock and you want one full period of the counter pulse train to span one full period of the AO waveform. Ticks per period of CO should equal Samples per period of AO. You don't need to query SampClk.Timebase.Rate, and the calcs you do with it aren't needed.
Note: to maintain correct phasing over time, you'll need to constrain your AO task such that an integer # of samples represents exactly 1 period. (Or possibly an integer # of periods, but that's a more difficult topic to get into).
Don't forget that you should also use the Initial Delay input on your CO task to place the pulse right at the zero-crossing point of the AO waveform.
-Kevin P