LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Writing Data Dynamically to an A/D converter

Solved!
Go to solution

Dear community,

 

I am trying to build a VI (Labview 8.5 professional) which allows to use an NI A/D-converter (e.g. PCIe6321) as a function generator for a potentiostate.

 

One of the major problems I encountered is related to the input of the data. In principle, it would be possible to define a certain ramp or function which is then sent to the A/D converter and written. The disadvantage of this method is that the potential function has to be known in advance and that no changes can be made during the writing process of the A/D converter. As this is of utmost importance for me, I planned on sending small parts (i.e. each part is 0.1 s long) of the function which I want to execute (i.e. 1. Write a piece of an analog wave 2. Write Analog wave to A/D converter, repeat 1-2). In that way I could be able to make adjustments to the function with a short delay. This works so far.

 

The problem with this structure cleary is: After the first piece of the analog wave is written to the A/D converter, the writing operation stops until the new part of the analog wave arrives. Thus, there should be a (short) delay between each package of the analog wave. Is there an option to circumvent this? I am thinking of a continous writing process of the DAQWrite function which reads data from an array. However, I am unsure how to fill this array dynamically. If I do this in a Producer/Consumer manner (where the production of the analog wave would be the producer), the array will soon be filled. What I would maybe need is an array, which is filled up with two parts of the analog wave and then the wave "production" should stop until an element of this array is used by the DAQWrite function. How can this be done? Is there any better way to create a buffer which tells the producer to wait until data has been read out?

 

I hope I expressed myself in an appropiate way. Thank you for your help!

 

Kind regards,

Mr_Kse

 

PS: I attached a version of the function generator I did so far.

 

 

 

So the

0 Kudos
Message 1 of 16
(3,276 Views)

Have a look at this doc:

http://www.ni.com/example/25370/en/

 

Edit:

The above doc only explains how to do non-regenerative AO, but also for me still an open question how to handle the memory, as you described?...

Lets wait for a real DAQmx expert to jump in, I feel I will learn some interesting stuff soon 🙂

Hmm, I am just reading this doc now, to understand further how the onboard FIFO memory works in different modes: http://digital.ni.com/public.nsf/allkb/45A7AC6B59E026B386256F90006DAA49

0 Kudos
Message 2 of 16
(3,245 Views)

Those two citations from Blokk seem to cover non-regenerative AO, which is what you want to do (incidentally, you are using a D/A converter, not an A/D converter).  You should also see if there's a suitable example right "inside" LabVIEW 8.5 (I found a suitable example in LabVIEW 2016 called "Voltage (non-regeneration) - Continuous Output").

 

Bob Schor

0 Kudos
Message 3 of 16
(3,229 Views)

Hi Phage,

 

I also think, you should have a look at the non-regeneration Option, but I'm not quite sure if this is what you need.

 

As far as I understand, your current problem is more of a LabVIEW-nature, than DAQmx. So you are writing an array of a few samples every 10ms (e.g. a ramp). If your DAQmx-Write-VI is inside a loop with no timing and has a sample rate defined, it should automatically wait, and let you pass only one array all 10ms.

Example: Samplerate=1kHz, Samples to Write = 100 -> 100 Values each 10ms.

In this case you only need to create the 100 samples of signal within 10ms, wich is a long time to generate a signal. If you run a producer-consumer architecture with this, your producer loop can generate way more samples than needet, your queue will fill up, and you won't pass the currently produced part to the Device, but the last package thats in the queue. Consider generating the signal within the same while-loop as your DAQmx Write.vi. In this case you only run the "production" once every 10ms, and then pass the data to the Device.

 

Is that the problem you are facing?

 

Best,
Jan Göbel

Staff Applications Engineer

0 Kudos
Message 4 of 16
(3,207 Views)

Thank you for your answers. I already had a look at the first document prior to opening this thread, which cleary is necessary to execute the task I am interested in.The second document appears to be promising, especially the onboard memory configuration!

 

@bob_shore: Thank you for pointing that out, you are totally right, it is actually a D/A conversion which I want to perform. I could not find the example with the exact name but another one which might be helpful (Cont Gen Voltage Wfm-Int Clk-On Board Regeneration).

 

@Jan Göbel: This is exactly the problem.I need the Daqmx Write to run continously while changes in the input waveform can be made on-line or rather without a long delay (like in the producer/consumer example you described).

 

0 Kudos
Message 5 of 16
(3,202 Views)

Hi Phage,

 

in this case, you should just place the generation an the DAQmx Write.vi in the same loop.

 

In case you want to change the waveform in its Frequency (e.g. output a constant sine, but change the frequency during runtime) you could change the Sample-Rate of the Output dynamically. But you were talking about ramps, so I guess this does not apply to your problem.

 

Just try having it all in one loop, or do you see a problem with that?

 

Best,
Jan

0 Kudos
Message 6 of 16
(3,197 Views)

Hey Jan,

 

maybe I am mistaken, but I still see a problem here, when I highlight the execution in one of the Labview examples without regeneration:

 

Upon execution the generation of the waveform starts and DAQmxWrite waits for the waveform before it executes. It then  executes and starts to write samples to the onboard fifo (I am not really sure about this as I could only find the Data Flow for data aqcusition. I assume that the data generation is maybe just the other way around?). After it has completed is task (I am unsure why the execution waits for DAQmx Write to finish as I normally have to poll DaqmxIsTaskDone?), the cycle starts again. To my mind, this means that the writing task is not really continuous as it has to wait for the new data generated during the next cycle.

0 Kudos
Message 7 of 16
(3,193 Views)

Hi Phage,

 

you are right, I guessed calculating a ramp won't take that much time, so it should'nt affect your Output. If your "production" takes longer than 1ms or so, just do the production parallel to the DAQmx Write.vi.

Don't use 2 loops, but just have them in the same loop, but no dataflow between them. Then just wire the Result of the production (e.g. 100 samples of signal) to a shift register, and pass it to the DAQmx Write.vi in the next iteration. This way the DAQmx Write will always get its data immediately, and while the data is outputted (takes 10ms) you can generate the Signal for the next Iteration.

 

Make sure to initialize the shift register before you go into the loop to provide the 100 Samples for the first iteration.

 

Do you see any problems with this approach?

 

Best,
Jan

Message 8 of 16
(3,190 Views)

Hey Jan,

I am sorry for answering so late, but unfortunately building this new VI is not my main task. However, I already tried your suggestion and it works so far (especially using the shift register appears to be a good idea for a simple buffer, which does exactly what I want).

 

Still there remains one problem, which I do not understand in general. The DaqMxWrite function writes the samples to the RAM Buffer which then transfers the samples to the onboard buffer of the D/A converter, correct? These samples are then used for conversion and a voltage function is produced by the converter.However, the DAQmxWrite really takes a long time (e.g. if I send a buffer of 5s, the DAQmx write is also active for roughly 5 s), which leads me to the conclusion that the DAQmxWrite function works parallel to the actual voltage output of the D/A converter. Is that correct? If DAQmxWrite just wrote a bunch of data to the buffer and did not wait for the execution of the D/A converter, I would expect that the function rapidly finishes.

 

As a result, this would still mean: DAQmxWrite is called, samples are wirten, DaqmxWrite stops (and thus the D/A conversion), the next loop starts and DAQmxWrite is called again. Thus, there should be a still a very short delay between the last voltage of the first buffer and the first voltage point of the second buffer. Is this true? Is there any option to have a truly continuos output?

 

I know this might sound picky, but we want to simulate an analog potential ramp as realistically as possible.

 

 

Best,

Phage

 

0 Kudos
Message 9 of 16
(3,169 Views)
Solution
Accepted by topic author Phage

Hey Phage,

 

I think now I got what you're stuck with. Your explaination is nearly correct, with a little difference.

 

All values in the explaination refer to a SampleRate of 1kHz and 1000 Samples beeing written each iteration:

 

The DAQmx Write VI does not take 1s, because you passed 1000 Samples which represents 1s of signal, but because of your buffer is full, and you need to wait for another 1000 samples to fit in there. So what you can do to prevent a delay between two packages is, to configure a bigger buffer. Lets say you use the "configure output buffer.vi" to set the output buffer to 10000 Samples (=10s of signal). Now your DAQmx Write.vi would run 10 times really fast and fills the buffer. After that it always waits until the Number of Samples in the buffer has dropped from 10000 to 9000, so it can write the next 1000 samples.

So if you set the buffer bigger than your package size, you can already write the next package, while the current one is beeing outputted. If doing so, you might get problems with Buffer Over-/Underflows after a while. Thats why you should poll the DAQmx Write Property "Space Available in Buffer" to check when to deliver the next Samples. If you're taking good care of the buffer level, you won't need the "Do Not Allow Regeneration"-Property mentioned in some previous posts. Anyway you can turn it on to get notice of an underflow. With Regernation Allowed, you could empty you buffer, and DAQmx would just repeat the last bit of the signal. Thats not what you want, so set it to "Do Not Allow Regeneration" to catch an error when that happens.

 

About setting the Buffer:

Alway use the DAQmx Buffer Property "Output->Buffer size" to check, how big your buffer really is. Some devices change the buffersize, even if you use the Set Output Buffer.vi.

 

Please let me know if you understand all from this post, and if you have any further questions about it.

 

Best,
Jan Göbel

Staff Applications Engineer

Message 10 of 16
(3,161 Views)