LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Error 200288 - selecting analog waveform by loop index to be written by re-triggerable `DAQmx Write.vi`

First things first, I am using a PCIe-6363 and LabVIEW 2023 Q3.

 

I am attempting to write out waveforms on the rising edge of a counter channel, and read data back in on the falling edge of the same counter channel for the purpose of coherent averaging (i.e., the time between transmission and read-in must be hardware timed). However, the waveform I am writing out must be different on each rising edge, e.g. the first edge will write-out and read-in the results of a 1 Hz pulse, the second a 10 Hz pulse, etc.

 

So far, I have constructed what I believe to be the closest (albeit, non-functional) rendition of what I want:

AnalogOutEventIndexing2.png

 

This VI will work for the first waveform, but subsequent writes will throw error 200288. The only way I have been able to get this to work is by calling `DAQmx Start Task.vi` before the write operations without the event; however, this won't work with the event because the event requires a buffered operation. The event structure is there to count the number of samples written to the buffer, which will track the number of rising edges of the counter channel, wherein my intention is to output a waveform that corresponds to the rising edge count.

 

So, my question is, is it possible to output a waveform by index or edge count?

0 Kudos
Message 1 of 8
(644 Views)

I'm not 100% clear what you need to do overall.  Here's what I *think* I'm understanding:

 

You want to retrigger analog output using a counter output that's under your control as a triggering signal.  Not shown is that you also want this counter to help you do analog capture with a fixed time difference between output sample generation and input sample acquisition.

 

I'm wondering if perhaps you're mixing up the role of trigger and clock here.  I would normally look for this kind of AO / AI correlation to use a controlled pulse train as a *sample clock* rather than as a trigger.

 

Meanwhile, here's what I think the reason may be for the -200288 buffer overwrite error in the code you posted:

 

On the very first loop iteration, you immediately write an entire buffer full of samples to your task.  In parallel with this, your event case is waiting for the DAQmx event that those samples have been delivered from the task buffer down to the device.  Your task line continues and is started.  Once all the samples have been delivered DAQmx event will fire and the code advances to the next loop iteration.

    But here's a very key point: the DAQmx event is likely to fire *before* the task is actually done generating samples.  Even after the samples are delivered to the device, they still have to go through the device's onboard FIFO before they get generated.  And the default behavior of DAQmx is to keep that FIFO as full as possible to give the greatest safety against buffer underflow.  In other words, DAQmx is biased toward a maximum *latency* from the time when samples are delivered to the device until the samples become a real-world signal.

   

So now there are 2 possibilities, depending on whether DAQmx allows you to write new samples to the buffer before the first finite acquisition completes.  If not, you'll get the -200288 buffer overwrite error right away on the 2nd loop iteration.  If so, you'll iterate some number of times in this manner until you fill up the onboard FIFO, and then soon cascade into that same -200288 error.

 

So then, even though you've delivered your samples out of the task buffer, you're not allowed to write new ones until the original finite task finishes running to completion.  So your 2nd iteration starts up before the task is done, you immediately try to write more samples, and wind up getting the 200288 overwrite error.

 

There will probably be a good solution available for you -- the X-series devices are *very* flexible and capable.  But I need to be clear on your detailed requirements first.

- should AO and AI both use a counter pulse train as a sample clock?   With AO on the leading edge and AI on the trailing edge?

- is there some further need for triggering to sync with something else?

- are the AO waveforms pre-defined or will you need the program to be calculating them on the fly, in reaction to the measurements being taken?

- how many total samples do you intend for one complete run?

 

It can sometimes be a handy trick to drive an AO (or AI) task with a counter pulse train where the analog task is declared as Continuous and the counter is declared as Finite.  I guess we'll see if that comes into play for you.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 2 of 8
(575 Views)

Here is the "bigger picture" of what I am trying to do:

 

PulseTimedAoAi2.png

 

I basically have two antennas; one antenna transmits on the rising edge of PFI9, and the other antenna receives on the falling edge of PFI9. For averaging purposes, I need the timing to be constant between the transmit and receive portions of the experiment. The number of averages corresponds to the number of pulses output on PFI9 by the counter output channel. In the example above, the CO low time is 2s, the high time is 4s, and there are 5 averages. The DAQmx events count the number of samples transferred to and from the buffer to stop the re-triggerable task after the desired number of averages has been completed.

 

However, while the above example works, I also need to be able to output a different analog waveform with each rising edge of PFI9. My example above only outputs a 1s long 1Hz sine with each rising edge, but I would like to be able to output a different waveform from an array of waveforms with each retrigger. For example, with every rising edge of PFI9, I may want to output a sine with double the frequency of the previous sine waveform.

 

The AO waveforms will be predefined, and the number of total samples will be variable depending on the resolution I want for a particular run. I would guess, on average, that the experiments might consist of around 300,000 samples per CO pulse on AO, and receive around 300,000 samples on AI, with anywhere between 1-20 CO pulses.

0 Kudos
Message 3 of 8
(568 Views)

I like all-hardware timing as much as the next guy, and quite probably more than most.  But I find myself thinking that your solution might get a whole lot simpler if you put some key parts of it under software timing instead.

 

If I understand correctly, the AO signal will only be active during the CO high time and maybe only part of it.  It will be idle during the CO low time.  And in the code you posted, you have *seconds* worth of time when the AO task will be idle.

    If your minimum idle time is anywhere in the 1 second order of magnitude or more, you should be fine using software timing between triggers.  Especially if you can *also* put the CO pulses under software timing control.  You'd still have the same hardware-controlled time diff from rising to falling edge, but you could then make sure you don't issue another pulse until AO & AI are known to be ready for it.

The scheme I'm proposing is more of a state machine where you:

1. Configure AO as a finite sampling task, triggered by a rising edge from CO.  Write the first set of data to the task.

2. Configure AI as a finite sampling task, triggered by a falling edge from CO.

3. Configure CO for a single pulse with the desired high time (the time diff from rising to falling).  Be sure to set idle state low in case this isn't the device's default.  Note however that the pulse will go into idle state for 'initial delay' time *before* pulsing for high time.  This *might* produce a falling edge, which is why we didn't start AI yet.

4. Start AO

5. Start CO

6. Start AI

7. Wait for the AO task to complete.  Then call DAQmx Stop (if necessary.  The task may be in its stopped state on its own).  Write the next set of data to the AO task.

8. Wait for the CO task to complete.  Then call DAQmx Stop (if necessary).

9. Read all samples from AI.  Then call DAQmx Stop (if necessary).

10. If you haven't done all the desired CO pulses yet, return back to step 4.  (Or back to step 3 if the CO pulse timing needs to be changed).   If desired, you can add a software timing delay here first to give you more idle time.

 

No re-triggering, no chance of buffer overwrites, no DAQmx events to handle & coordinate.   As long as you only really need tight hardware timing on the delay from AO trigger to AI trigger.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 4 of 8
(558 Views)

I do like the idea of a state machine - I originally thought about something similar, but I had instead convinced myself that using a counter as a “pseudo-master clock” was more appropriate for my application. However, while what I’ve described is a simpler, more general application for this experimental setup, there are more advanced experiments that I’d like to perform that I believe may require hardware timing not just between the AO and AI, but also between pulses. The solution you’ve provided sounds like a great solution for average a set of single-pulse and acquire experiments, though. I’ll detail a bit where hardware timing between the pulses is important:

 

These are NMR-type experiments, and there may be more advanced experiments/sequences where I want to send out a pulse train where I induce varying flip angles. For instance, the first pulse might be a 90 degree pulse, then I might pulse out a train of small flip angles at constant, precise intervals to achieve a steady state. This is ultimately what I am trying to achieve with the pulsed counter output, and why I am trying to output a waveform indexed from a pre-computed array of waveform on each rising edge of the counter.

 

I appreciate your insights on this, greatly.

0 Kudos
Message 5 of 8
(548 Views)

I'm more confused now than I thought I was when I made my last reply.  Your code shows you using a counter output as a trigger signal while relying on internal timebases for the AO and AI sample clocks.   But your latest text description seems to want to use the counter output as a sample clock, with one sample generated and acquired per output pulse.

 

I also don't know what you mean by terms like "NMR-type experiments" and phrases like "pulse out a train of small flip angles at constant, precise intervals".   For example, what is a "flip angle"?  And what kind of pulses relate to these angles?  Are you talking about counter pulse train output?   Or analog waveforms that generate analog pulse shapes?

 

Can you show a representative timing diagram of your signals, along with some detailed description?   Even a pic of a hand sketch would probably help.  Be sure to identify triggering signals, sample clock rates (and sources if not the built-in timebases), active vs idle periods, other relevant signal and timing details.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 6 of 8
(527 Views)

Here is a crude timing diagram of a possible experiment:

 

timing_diagram.png

 

This should illustrate how I am using the counter to time the analog output from the first antenna, and the acquisition on the second antenna. I believe a hardware timed "pulse time" is also necessary because a characteristic decay curve should become apparent if a line is drawn between the maximum of the FID acquired on each pulse. I worry that too much jitter in this "pulse time" would change the characteristic decay curve and yield an incorrect decay time.

 


@Kevin_Price wrote:

Be sure to identify triggering signals, sample clock rates (and sources if not the built-in timebases), active vs idle periods, other relevant signal and timing details.

 


I think this diagram should cover everything regarding triggering signals, active vs. idle periods, etc., and the VI block diagram I posted in my previous comment should give sample clock rates and sources - I copied the subVI contents directly from my project, minus the output waveforms, which have yet to be calibrated. They will probably be sampled on the order of 1 MHz sampling rate for a duration in the hundreds of milliseconds.

0 Kudos
Message 7 of 8
(518 Views)

That timing diagram is hugely helpful - thanks!

 

I had a few idle minutes over lunch to tinker on the snippet you posted.  I removed all the event and retriggering stuff to try to illustrate a simple version of the steps I listed previously.  I don't love everything about this code I'm posting, but I was trying to minimize how much of the overall structure I changed.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 8 of 8
(489 Views)