Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Best practise for arbitary signal generation with VB.NET?

Hi All,
 
This is my first post and I haven't been using Measurement Studio for long so go easy on me 🙂
 
Okay, basically my problem boils down to how to most efficiently generate a number of concurrent arbitary waveforms (i.e. non period). My hardware is a PXI unit equiped with a PXI-6733 for analog output and a PXI-6120 for analog input. I'm currently trying to use two tasks in Measurement Studio 7.5, one for input and one for ouput. The input task is working fine and aquires data from mutliple channels at a reasonable rate with no problems. However, I'm having difficulty getting my output waveforms to be generated correctly 😞
 
Currently, I'm utilising an AnalogMultiChannelWriter using the asynchronous method calls BeginWriteMultiSample and EndWrite. I've setup the output task to perform transfers using DMA and to not perform regeneration (as my waveform is not periodic and I want to avoid glitching - is this the right thing to do?) but I'm having major problems. I also have the output buffer size set to be as small as possible (i.e. a few data points)  the rational behind this was so that my output would be as responsive as possible. However, using this approach I can typically only generate 10-20 data points per second and there appears to be a lag of a few seconds after sending data to the buffer before it is outputted (I've checked this by simply wiring one of my outputs to an input and graphing the two waveforms). Obviously, I'm doing something wrong or I'm approaching the problem from the wrong angle. Has anyone got any example code of how to best generate in realtime a number arbitary waveforms each with ~100 data points per second.
 
Many thanks,
 
Mike
 
P.S. I think it may be possible to use some combination of the DataTransferRequestPosition and WriteRelativeTo to write new data into one half of the output buffer whilst the other half is being generated? Any suggestions on how to proceed would be greatly welcome 🙂
 
 
0 Kudos
Message 1 of 5
(4,239 Views)
HI,
  you're actually trying to do a double buffered analog output. This is where the balance part comes in.
If you run with no regeneration then you need top make sure that you keep up with the buffer your outputting, i.e.
you software can provide the next piece of data before the output runs out of buffer.
The regeneration flag says to loop over and use old data :
so this won't avoid glitching as such, but is there to allow no error when there's no new data.
 
I think your approach is correct (in the absence of any actual code I can sanity check it by), but I think the AI task is eating up a lot of processor time. If you do a DAQmx read in a loop, and the data itself isn't available (say 1000 points, at 1000 S/s = loop time of 1 second) then it can use a lot of processor time and effectively starve the other thread of the AO section. This could be why your AO rates seem so low.
 
Do you get any specific errors from your code?
What happens if you drop the AI section, and get the AO going on its own?
Can you post the project back here (as cut down as possible)?
 
Thanks
Sacha Emery
National Instruments (UK)
 
 
// it takes almost no time to rate an answer Smiley Wink
0 Kudos
Message 2 of 5
(4,223 Views)

Hi Sacha,

Here is some extra info :-

1) I'm not getting any specific error code - but the asynchronous output task write callback doesn't appear to be called as often as I'd be expeecting.

2) Running the input task on it's own adds only a few extra percent to the CPU usage - I'm nowhere near maxing out the CPU. 

2) Graphing both waveforms does make the CPU usage rise rapidly to nearly 100 percent - however, turning graphing off make's no difference to the apparent responsiveness off my generated output waveform.

3) I've recently started experimenting with turning regeneration on and setting UseOnlyOnBoardMemory = False - this enables me to update the output buffer from within my code.... previously with regeneration on once I'd started the output task nothing I wrote to the output stream had any effect on the output waveform (hence, I need regeneration turned off).

I'll post a cut down version of my code asap... I appreciate that it's hard to give a definitive answer without it.

BTW, do you have any documentation or links which outline the expected behavour of the write callback when using different modes e.g. regeneration on/off, dma vs. interrupt, onboard memory on/off ?

Many thanks,

Mike

0 Kudos
Message 3 of 5
(4,195 Views)
Hi Sacha,
 
Okay, here is a cut down version of my program... The general idea is to generate a arbitary output waveform and then read the waveform back into the program - both input and output waveforms are also graphed in the GUI. As stated previously the input task works fine but the output task doesn't work as I'd expect. Whilst writing the example program I think I've gained a better understanding of the problem. Basically, at the moment it seems that the output works but there is a large lag between the output being written to the buffer and the output actually being generated - basically I'm overfilling the output buffer. I didn't think this would be possible as I'd set the output buffer to be very small and hence expected any new samples that I wrote to the AnalogMultiChannelWriter to overwrite the existing values in the circular buffer.
 
To get this working I can see two approaches -
 
1) Fill the buffer using the AnalogMultiChannelWriter in a more controlled manor - I've tried using WaitUntilDone on the output task but then I get an exception along the lines of "The generation has stopped to prevent the regeneration of old samples" which I guess is expected if the call waits until all data points have been written. Is there a way to get WaitUnitDone to return when the buffer is half empty? I've tried DataTransferRequestCondition = AODataTransferRequestCondition.OnBoardMemoryHalfFullOrLess but this seems to have not effect (I guess this is because I've got UseOnlyOnBoardMemory = False so that I can update the buffer) 
 
2) Overwrite the buffer values directly using WriteRelativeTo and WriteRaw - I'm not sure how to go about this is there an example?
 
Many thanks,
 
Mike
 
P.S. Is there a way to clear the data in the AnalogMultiChannelWriter or underlying Stream ? As If I stop and restart the task I'd like to clear the buffer.
 
 
0 Kudos
Message 4 of 5
(4,192 Views)

Hi,

 sincere apologies for not replying sooner.

The principle of analog output does include a delay. Essentially the first lot of data written to the write buffer (system memory) is transfered to the card FIFO so it is filled. You then have say 10000 points in the system buffer (using round numbers here) and a FIFO 2000 elements deep filled with the first 2000 points. So with regeneration off, the system buffer continuously transfers data to the FIFO on the card (hopefully using DMAs). when you ask it to simply write new data, then the driver waits until there is enough space in the system buffer to write this data. A

As you say, if the buffer is large, you'll experience a large delay in the system. You also have to remember to include the onboard FIFO with this.

I've included below a section from a presentation I gave in Israel I think originally created by one of our engineers in the US for an internal presentation on advances in DAQ.

The screenshots showing the property nodes are from LabVIEW, however the properties (and indeed all functions) in DAQmx should be identical regardless of language used.

There's a lot of notes that go with the two slides so they should explain what's possible

When you clear the task, you need to reconfigure a new task to get it to be able to run again, so this creates a new buffer (de-allocating the old one).

Hope this helps

Sacha Emery
National Instruments (UK)

// it takes almost no time to rate an answer Smiley Wink
0 Kudos
Message 5 of 5
(4,063 Views)