Discussion:
Analog Ouput Update
(too old to reply)
A Wooten
2008-04-01 23:10:06 UTC
Permalink
Is it possible to write to the Analog Output buffer while a continuous generation is being performed?
 
I need to be able to adjust a DC output signal on the PXI-6723, based upon a feedback measurement ( so there is no predefined update pattern ).
 
Currently I have to stop the AO task, write the new data, and restart the task. 
If I do not stop the task I receive the following error:

Error 0xfffcf19c - Some or all of the samples to write could not be written to the buffer yet. More space will free up as samples currently in the buffer are generated.
This process is taking too long, so I am  looking into ways to speed it up.
 
Any ideas?
 
Thanks,
Anson 
Matt A
2008-04-02 16:40:15 UTC
Permalink
Hello Anson,

I have written an example which I think demonstrates the operation you
discussed. I am assuming you are developing in LabVIEW, but if you are
using another development environment the same ideas will hold true. I
modified one of our example programs to use regeneration to update the
data that is generated by writing new data to the memory buffer that is
being generated. For a more detailed description of regeneration, you
can see the NI-DAQmx Help which you can find by going to your Start menu and selecting All Programs>>National Instruments>>NI-DAQ. Specifically, the help file has a section called Regeneration which states the following:

"Regeneration


Generating the same data more than once is called
regeneration. You can configure NI-DAQmx to allow or disallow
regeneration by setting the Regeneration Mode
attribute/property. By default, NI-DAQmx allows regeneration for sample clock
timing and disallows it for handshaking or burst handshaking timing. When
regeneration is disallowed, new data must be continuously written to the
device.

Allowing Regeneration and Using Onboard Memory


When the Use Only Onboard Memory
attribute/property is true, NI-DAQmx transfers data only once to the device and
that data is continually regenerated from there. Attempting to write new data to
the device after starting the task returns an error. In addition, the amount of
data written to the device before staring the task must fit in the onboard
memory of the device.


When the Use Only Onboard Memory
attribute/property is false, NI-DAQmx continuously transfers data from the host
memory buffer to the device even though this data is not changing. Thus, if you
write new data to the device after starting the task, that new data is generated
and regenerated until you write more new data. This type of regeneration is
sometimes called PC memory or user buffer regeneration.


When this attribute/property is false, you can also set the
Data Transfer Request Condition attribute/property to specify
when to transfer data from the host buffer to the device."

My example is attached and is called Cont Gen Voltage Wfm-Int
Clk-Regeneration_Modified.vi. There are more notes in the VI itself
regarding each function used, but basically this example takes an
update from the user through the Front Panel and writes the value on
the analog output. You could easily modify this example to calculate
the update based on a formula or equation that better suits your needs.
I hope this helps, let us know if you have any other questions.


Cont Gen Voltage Wfm-Int Clk-Regeneration_Modified2.vi:
http://forums.ni.com/attachments/ni/250/38760/1/Cont Gen Voltage Wfm-Int Clk-Regeneration_Modified2.vi
A Wooten
2008-04-02 18:10:13 UTC
Permalink
Matt,
Thanks for your reply.
I am not using Labview ( I'm using C++ in Visual Studio 6.0 ), so unfortunately I am not able to view your sample.
If I understand the regeneration documentation properly, I should be able to:

- Set "Regeneration" =  true

- Set "Use Only Onboard Memory" = false

This will result in the device getting constantly updated with the contents of my data buffer, which I can update while the Task is running using the standard write() functions.
Is this correct?
I have some questions about the "UseOnlyOnBrdMem" configuration function ( see declaration below )

DAQmxSetAOUseOnlyOnBrdMem(TaskHandle taskHandle, const char channel[], bool32 data)
The channel[] parameter surprises me!

- Do I need to supply the name of the output channel in the task that will be using "user buffered" generation?

- What if the task contains multiple channels, do I need to call this function for each channel in the task?

- Is it possible to have one channel in the task using "User Buffered" data while the other use "Device Buffered" data?

Thanks,
Anson
 
 
Matt A
2008-04-02 22:40:06 UTC
Permalink
Hello Anson,First, let me address your questions:A) Yes, by enabling regeneration and disabling onboard memory only, you are creating a data buffer in memory which you can update with new data to generate with your device.B) Regarding the channel parameter questions:    1. No, you do not need to supply a channel name in the task to be used with this function. I passed NULL as a parameter and my program ran without error.    2. The AOUseOnlyOnBrdMem property is set for all channels within a task. All the channels in the TaskHandle you pass will be set to the value you select.    3. No, it is not possible to set one channel in a task to use only onboard memory and then set another channel to another setting.Though you are not using LabVIEW, the fundamental steps to perform the operation in the above VI will remain the same (this is the beauty of the architecture of the NI-DAQmx driver). Here are the notes from the attached VI with the corresponding C function calls:Steps:1. Create an Analog Output Voltage channel.    - int32 DAQmxCreateTask (const char taskName[], TaskHandle *taskHandle);    - int32 DAQmxCreateAOVoltageChan (TaskHandle taskHandle, const char
physicalChannel[], const char nameToAssignToChannel[], float64 minVal, float64    
maxVal, int32 units, const char customScaleName[]);2. Configure the task to automatically regenerate data.    - int32 __CFUNC DAQmxSetWriteRegenMode(TaskHandle taskHandle, int32 data);3. Call the DAQmx (Sample Clock) VI Use C function call to set the sample clock rate. Additionally, set the sample mode to Continuous and set the size of the sample buffer. The buffer must contain at least 2 samples to perform continuous generation; however, a larger buffer will prevent data being overwritten when updating the buffer with new samples.    - int32 DAQmxCfgSampClkTiming (TaskHandle taskHandle, const char source[], float64
rate, int32 activeEdge, int32 sampleMode, uInt64     sampsPerChanToAcquire);4. Read the actual sample clock rate (eventually coerced depending on the hardware used).    - int32 __CFUNC DAQmxGetSampClkRate(TaskHandle taskHandle, float64 *data);5. Compute the desired waveform, using the buffer size and DC value.    - not a DAQmx function, any sort of array instantiation should work6. Write the waveform to the output buffer.     - int32 DAQmxWriteAnalogF64 (TaskHandle taskHandle, int32 numSampsPerChan, bool32
autoStart, float64 timeout, bool32 dataLayout, float64     writeArray[], int32
*sampsPerChanWritten, bool32 *reserved);        or    - int32 DAQmxWriteBinaryI16 (TaskHandle taskHandle, int32 numSampsPerChan, bool32
autoStart, float64 timeout, bool32 dataLayout, int16 writeArray[],     int32
*sampsPerChanWritten, bool32 *reserved);    or    - int32 DAQmxWriteBinaryU16 (TaskHandle taskHandle, int32 numSampsPerChan, bool32
autoStart, float64 timeout, bool32 dataLayout, uInt16 writeArray[],     int32
*sampsPerChanWritten, bool32 *reserved);    - depends on whether you are writing scaled or unscaled data and what format you are using for your array7a. Call the Start VI. This is only needed when the loop is executed for the first time.    - int32 DAQmxStartTask (TaskHandle taskHandle);7b. Do nothing.    - unnecessary in this case8. Loop continuously until user presses the Stop button. Every iteration computes and writes a new waveform to the buffer.    - see note on 6 above about which version of the write function to use.9. Call the Clear Task VI to clear the Task.    - int32 DAQmxClearTask
A Wooten
2008-04-04 17:40:16 UTC
Permalink
Matt,
I seem to be unable to configure regeneration and onboard memory usage for my PXI-6723.
Here is the configuration seqence I am performing

- DAQmxCreateTask()

- DAQmxCreateAOVoltageChan()

- DAQmxSetWriteRegenMode()

- DAQmxSetDOUseOnlyOnBrdMem()

Steps 3 and 4 are generating the following errors:
3) DAQmxSetWriteRegenMode( DAQmxTaskHandle, 1 );

Error 0xfffcf273 - Requested value is not a supported value for this property.
4) DAQmxSetDOUseOnlyOnBrdMem(DAQmxTaskHandle,  NULL,   0);

Error 0xfffcf0fc - Specified property is not supported by the device or is not applicable to the task.
Any ideas why I am receiving these errors?
Thanks,
Anson
 
Matt A
2008-04-07 14:10:11 UTC
Permalink
Hello Anson,1. As noted above, the definition for the function to set regeneration mode is as follows:&nbsp;&nbsp;&nbsp; int32 __CFUNC DAQmxSetWriteRegenMode(TaskHandle taskHandle, int32 data);However, when you examine the documentation, you will find that the data values are not simple booleans, but numerical values which represent different options. The NI-DAQmx C Reference Help contains a section called "Regeneration Mode" which describes these values. I have copied this description below for your reference:<img src="Loading Image..."> So, if you would like to enable this mode you would actually pass the DAQmx_Val_AllowRegen value (10097) to the function rather than a 1 for true. For your information, you can find the NI-DAQmx C Reference Help by navigating to Start&gt;&gt;All Programs&gt;&gt;National Instruments&gt;&gt;NI-DAQ. 2. The reason you are receiving this error is because you are attempting to set a digital task property for an analog task. You posted that you are using the DAQmxSetDOUseOnlyOnBrdMem(), which is the property to set for a digital operation. You would actually use the DAQmxSetAOUseOnlyOnBrdMem() function to set the property for an analog output operation. Should be a quick change and you should be good to go.Message Edited by Matt A on 04-07-2008 08:43 AM


Regeneration Mode Property.jpg:
http://forums.ni.com/attachments/ni/250/38907/1/Regeneration Mode Property.jpg
A Wooten
2008-04-10 19:40:09 UTC
Permalink
Matt,
Thanks for your patience.&nbsp; I should have caught those last errors, just overlooked them in my haste to get this resolved.
I have fixed the driver errors I was receiving ( per you directions ), however I am still unable to get this approach to work.
Below is the current Sequence of commands I am executing:

- DAQmxCreateTask()
- DAQmxCreateAOVoltageChan()
- DAQmxSetWriteRegenMode( DAQmxTaskHandle,&nbsp;10097 );
- DAQmxSetA OUseOnlyOnBrdMem(DAQmxTaskHandle,&nbsp;&nbsp;NULL,&nbsp;&nbsp; 0);

- DAQmxCfgSampClkTiming()

- DAQmxCfgOutputBuffer() -- I may not need this one anymore

- DAQmxWriteAnalogF64()

- DAQmxStartTask()

This sequence is working fine, and the first value I write to the task&nbsp;is being generated at the expected output.
After the task is started I am unable to update the output.

- I've tried updating the data buffer I passed to the task in step 7


- But the output is not updated.

- I've tried resending the DAQmxWriteAnalogF64() command


- I receive the same errors described above when performing the write command on a running task.

Am I missing something?
I thought that configuring the card in this manner would allow me to update the output task ( without stopping the task ) by changing the contents of the buffer supplied in step 7.&nbsp; Is this not correct?
Thanks for all your help,
Anson
&nbsp;
A Wooten
2008-04-11 15:40:11 UTC
Permalink
- UPDATE -
Matt,
I increased my buffer size which resolved the failure I was receiving when executing the Write() function.&nbsp; So now there are no driver failures, but there is still a problem.
When I execute the Write() command, I receive no errors and the function indicates that the correct number of samples&nbsp;where written.&nbsp; I do not however see any change at the output pin.&nbsp; Also, after a few minutes the output drops to zero.
Here is the sequence:

- Create and configure the Task as we have discussed above

- Write a single sample of 2 (2 VDC)

- Start the task

- Attempt to write&nbsp;a new sample to the buffer (3 VDC)


- No failures generated but the output stays at 2 VDC.

- The output eventually drops to 0 VDC ( with no input from me)

Any ideas why I would see this?
Thanks again,
Anson
Matt A
2008-04-14 22:40:09 UTC
Permalink
Hello Anson, That behavior does seem strange. My LabVIEW code worked well and did not report any errors. I passed the following values to my sample clock function::rate (Sample Clock Rate): 20000sampsPerChanToAcquire (Buffer Size): 250I specifically chose this combination of sample rate and buffer size so that I would eliminate errors with old data being mixed with new, but also so that updates to my voltage would take no longer than one cycle through the buffer (1/20000 sec/Sample * 250 Samples= 0.0125 sec) to update the output. What values are you using in your task? What happens if you try this combination of sample rate and buffer size? Rather than writing a single sample of 2 and then 3 to the buffer, you could try writing an array of 250 elements (all 2s) to the buffer and then another 250 element array of all 3s to the buffer. I'm not sure that that would address your question specifically, but that is the method I am using and it seems to work for me. Let me know how things go.
Vectrix
2008-05-28 21:40:09 UTC
Permalink
Hello Matt, I downloaded your vi and an memory underflow error occured. I am using NI DAQPad-6015 with DAQmx on Windows Xp.I have been searching everywhere for a solution to my current problem with continuous AO update, and this thread is the closest thing I can find. Allow me to explain what I am trying to achieve.I have a 21 kHz digital signal.I want to use that as a trigger for an anolog output of an step function.The tricky thing (and the dilemma I am having) is on each tick, the output should step up once, and then after a couple ticks, the output returns to 0. So the pattern is like 0, 3, 6, 9, 0, 3, 6, 9 and so on. I have attached my vi here. The problem, as you will see, is that the "write" is inside a while loop and therefore not sync up with the clock. Furthremore, the outputing frequency is much slower than 21kHz and is unpredictable. Could you take a look and provide me with some pointers?Thanks,Vectrix


Bmode trig V1.2.vi:
http://forums.ni.com/attachments/ni/250/40358/1/Bmode trig V1.2.vi
Nathan_R
2008-05-29 21:10:08 UTC
Permalink
Hi Vectrix,


So it sounds like you need to output a
repeating sequence of values timed to an external 21 kHz clock. To do this I
would recommend taking advantage of analog output regeneration. This will let
you write the output sequence to the buffer once and then the card will output
the sequence over and over. You can time this to be synced with an external
clock. An example of this can be found in the NI Example Finder. In LabVIEW go
to Help &gt;&gt; Find Examples? &gt;&gt; Hardware Input and Output &gt;&gt;
DAQmx &gt;&gt; Analog Generation &gt;&gt; Voltage &gt;&gt; Cont Gen VoltageWfm ?
Ext Clk.vi. The external clock will be your 21kHz signal and you can replace
the examples waveform with your repeating sequence.


One thing I noticed in your VI is that
you have 300 wired to the rate terminal in the timing vi. When you are
providing an external clock the rate terminal should be set to the highest frequency
you expect that external clock to run at, in your case 21000. Also you will
want to set the sample mode to ?Continuous Samples?. Please let me know if you
have any questions and take care.


Thanks,
Vectrix
2008-05-29 21:40:08 UTC
Permalink
Hi Nathan, Thanks for the speedy reply. However, the example doesn't quite suit my application. There are two complications. Firstly, I would like to take out the "Desired Frequency" input parameter and have the output to depend solely on the external clock. Secondly, from my understanding of signal regeneration is that the waveform is fixed. (One write to the buffer and the output will continuously generate whatever is in the buffer.) Due to the fluctuation and the packet like behaviour of the external signal, a fixed waveform is not desired. Instead, the output should ONLY increase/decrease by a predefined amount when the device sees the rising edge of the external clock. This is quite different from outputtig a fixed waveform (say 3 steps) on every rising edge.I hope that clears things up a little. Any suggestions?Your help is greatly appreciated,Vectrix
Nathan_R
2008-05-30 20:40:07 UTC
Permalink
Hey Vectrix,


The way the example I showed you and hardware
timed analog output works is that on each edge of the external clock 1 sample
from the buffer is output. It does not output the entire buffer on each edge. &nbsp;When the end of the buffer is reached it
starts over from the beginning. So if you write 0,3,6,9 to the buffer on the
first clock edge 0 will be output. On the second edge 3. Next edge 6. Then 9.
On the fifth edge 0 will be output again and so on. This sounds like the behavior
you were looking for. When using an external sample clock the output will be
timed to that clock and only output a sample on the active edge of that clock.
You still however need to set the rate terminal of the timing VI with the
highest frequency that you expect that external clock to run at. This is so the
drivers know how large of a buffer to allocate for the task. This value is used
to setup the timing of the acquisition only when using the internal sample
clock. If you provide an external sample clock the output timing will depend
solely on that clock. I hope this helps and let me know if you have any
questions.


Thanks,
Vectrix
2008-06-07 00:10:20 UTC
Permalink
Hi Nathan, I have finished writing the program with desired funcitonalities. Couldn't have done it faster or better without your help or the forum.Thank you very much,Vectrix
jeroen.clarysse
2008-07-02 11:10:08 UTC
Permalink
Hi Vectrix, would you mind posting your code here ?I'm sort-of stuck with the same problem : I have an output signal that I want to manipulate programmatically, but as with your problem, the changes in the waveform are not reflected when I measure the output-pin. Only after aboutr 3 to 5 iterations of the waveform will the new data be outputtedI noticed that turning OFF regeneration will solve that problem, but then I'm stuck with a SINGLE waveform rather than a continuous outputgot any hints for me ?thanks !Jeroen
Vectrix
2008-07-03 21:40:05 UTC
Permalink
Hi Jeroen, I have posted my code below. Hope that helps.Is your output signal an arbitrary waveform? My outputs are single voltage outputs, so the codes itself is very simple as you will see. I would imagine modifying the codes to output an arbitrary waveform upon receiving an external wouldn't be too difficult (however I don't think it's entirely trivial neither).How are you controlling the generation? External trigger or internal clock? Could you perhaps explain your setup in more details, and I will try to help out however I can.Best,VectrixMessage Edited by Vectrix on 07-03-2008 05:39 PM


sample4.vi:
http://forums.ni.com/attachments/ni/250/41332/1/sample4.vi
jeroen.clarysse
2008-07-03 22:10:06 UTC
Permalink
Hi Vectrix ! thanks for your reply. I've detailed my problem in another thread on the forum :http://forums.ni.com/ni/board/message?board.id=231&thread.id=5819I do get the code working, but the changes in the data buffer are only reflected in the output signal after quite a few regenerationsI'd be very grateful if you could help me out there.my signal is fairly simple : a sine wave or a block wave, but the amplitude should be switchable on-the-fly (triggered by a TTL signal that comes from a special device)
Vectrix
2008-07-18 16:10:11 UTC
Permalink
Hi Jeroen,
I have attached a vi that does exactly what you have described in the other forum. I have not seen any delays in the response while running the code on my system.
The vi is a modified version of the example library.
Hope this helps,
Vectrix


ampUpdate.vi:
http://forums.ni.com/attachments/ni/250/41657/1/ampUpdate.vi

Loading...