07-07-2012 10:11 PM
I'm working on an application (L/V 2011) that must sample hours of data out an AO port at 120 s/sec. The I/O device is a USB-6218, which will not do 'hardware timed on demand' AO.
The problem: the output stream must pause on demand, and sometimes the output level changed during that pause period, then restarted where it stopped in the data stream. The output buffer size is set to 120 so it shouldn't take more than a second to empty out, but I'm seeing things in the buffering that puzzle me.
As you'd expect, if the data is 'chunked' (120 sample array) out too slowly it causes an underflow error (no data in the buffer). However, if the data is written too rapidly, there's no overflow; something seems to store it, up to at least 10 K samples. If a Pause occurs, all that data is lost!?
Help says the DAQmx Write property SpaceAvail shows “the amount of available space in the buffer.” Since the system acts as if there is an unlimited buffer, I’m not sure what SpaceAvail is showing. And tests using it to set the 'chunk' size show a distorted waveform, indicating data is lost.
So my questions:
1. Why is there no overflow error; where is that data going?
2. What does the SpaceAvail property show?
3. Anyone have suggestions for a better design?
Jim
Solved! Go to Solution.
07-09-2012 05:38 PM
Jim,
What sort of method are you implementing for pausing your output task? The method you are using may dictate the AO behavior, as well as how the buffering works. If you could provide a screenshot of what you have tried thus far that could be helpful in suggesting possible solutions for achieving your desired behavior.
Regards,
07-09-2012 06:38 PM
Chris,
The 'method' for pausing is simple: the DAQmx Stop VI stops the task then the DAQmx Start VI restarts. Although this works, the ambiguity of what's in the buffer makes operation iffy: too little leads to underflow; too much causes data loss.
Can you point me toward information that explains the first two questions above? Why doesn't the DAQmx Configure Output Buffer VI set the buffer size?
Jim
07-11-2012 10:12 AM
Jim,
From the NI-DAQmx Help (NI-DAQmx Key Concepts>>Reading and Writing Data>>Buffering>>How Is Buffer Size Determined?):
-------------------------------------------------------------------
For generations, the amount of data you write before starting a generation determines the size of the buffer. The first call to a Multiple Samples version of the Write function/VI creates a buffer and determines its size.
You also can use the Output Buffer Config function/VI to create an output buffer. If you use this function/VI, you must use it before writing any data.
The samples per channel attribute/property on the Timing function/VI does not determine the buffer size for output. Instead it is the total number of samples to generate. If n is your buffer size, setting samples per channel to 3×n generates the data in the buffer exactly three times. To generate the data exactly once, set samples per channel to n.
NI-DAQmx does not create a buffer when the sample mode on the Timing function/VI is set to Hardware Timed Single Point.
-------------------------------------------------------------------
Space available is a calculated value that is also described in the NI-DAQmx Help (...>>Read Status Attributes/Properties and Buffers):
-------------------------------------------------------------------
The three Read Status attributes/properties are useful for observing the progress of your acquisition. The Current Read Position is the place in the buffer where the next read begins if the Relative To attribute/property is Current Read Position and the Offset is 0. In any case, the Current Read Position is always where the last read left it. Total Samples per Channel Acquired is the total number of samples per channel acquired by the device and transferred into the buffer. Available Samples per Channel is computed by first calculating the Current Read Position based on the settings of the Relative To and Offset attributes/properties and then subtracting this number from Total Samples per Channel Acquired.
-------------------------------------------------------------------
There is additional information in that section of the Help file that describes how the buffering is performed that could be worth checking out as well.
Regards,
07-11-2012 11:20 AM
Chris,
I’m well aware of what Help says; if you reread my first post you’ll see that’s not what DAQmx does. Buffer size is clearly set to 120 samples using DAQmx Configure Output Buffer.vi yet the system happily takes 10 K samples as fast as LabVIEW can write them.
The same behavior shows up in using the SpaceAvail property to ‘meter’ data into the bufer: a 60-second block of samples (7200) goes ‘somewhere’ in 4 second but take a minute to be output. System action implies there’s a 10 K buffer somewhere; why else would CurrWritePos increment above 120?
The Write Status Attributes (equivalent to the Read Status Attributes you quote) mentions Relative To and Offset properties, as does the section ‘Controlling Where in the Buffer to Write Samples’. It would really be helpful to read more in-depth information on these properties and how using them affects what gets transferred to the hardware buffer (FIFO?).
Jim
07-11-2012 03:29 PM
Jim,
There is indeed multiple layers of buffering that occur when doing analog output. For a USB device this includes:
1) DAQmx Buffer. You can/have set the size of this buffer.
2) USB Transfer Buffers. You can get/set information about these buffers via the USB Transfer Request Size and USB Transfer Request Count properties. These properties are buried deep in the DAQmx channel property node.
3) Each device has some amount of memory dedicated for buffering USB transfers as they arrive. There is no way to configure this.
4) Analog Output FIFO. You should be able to query this via the 'Onboard Buffer Size' property in the DAQmx Buffer property node.
In order for data to get from your program to the device's output, it must travel through all of these layers of buffers. Since DAQmx attempts to be proactive in preventing the FIFO on the device from becoming empty and causing error, the data written is pushed as far through this buffering process as is possible. As such, as soon as data is written, it will get transferred to the USB transfer buffers and eventually on to the device. As such, there becomes space available in the buffer for more of the data you've written and DAQmx will move that data along as well. CurrWritePos is always relative to the first sample you write, and will increment for each sample written. Buffer size has no bearing on how it is calculated.
When you stop/start a DAQmx task, it does discard all of the data in these buffers. This is by design.
To me, it sounds like you should take the following approach:
1) Use a pause trigger to pause your output. This way you will avoid stopping and starting the task, and you will not lose all of the buffered up data.
- There is no software pause trigger, so the source will need to be an actual signal. You can make this happen by using DIO on your device to write a digital line high or low depending on whether you would like to pause or not. Wire this digital line to a PFI line, and use the PFI line as your pause trigger source.
2) Write less data at a time. If DAQmx fills up all the layers of buffering, you end up with a long delay between writing data with DAQmx write, and actually seeing the data on the output channel. To do this, you'll need to tell DAQmx not to regenerate data from the buffer (Regeneration Mode property in the DAQmx write property node), then implement a loop which periodically writes data to the buffer. By limiting the amount of data written to the device, you should be able to limit how much data gets buffered up in all of the intermediate buffers.
Hopefully that provides some insight into what you're seeing. Please let me know if I've been unclear. If I have time I may write up an example of my two step approach above.
I hope that helps,
Dan
07-11-2012 06:50 PM
Thanks Dan,
That does indeed help! I’m essentially doing what you recommend in 2); 1) is not good as the output must be varied during the pause period. In theory the first output could run back in an AI then out another AO, and that second AO varied during the pause; but guess what: that other AO is in use!
You've done what I needed: confirm this is 'as good as it gets' with this hardware. And yet another reminder that these things happen when administrators make engineering decisions (in this case select the I/O device)!
Thanks again,
Jim
07-12-2012 10:55 AM
Jim,
I misunderstood what you needed to do when paused... I thought you were only attempting to change the data in the buffer. If you need to change the output, then yes, you'll need to stop the task as you've already discovered.
One last idea. If you're not regenerating data from the buffer, and you're keeping track of the data that you're writing, then you should be able to query the 'Total Samples Per Channel Generated' property (DAQmx Write Property Node->Status) after you stop your task. This should tell you exactly how many samples the DAC has output. If you can correlate this to the data you've written, you should be able to figure out what data to re-write if you want to restart the buffered task with the same data that was previously buffered before you stopped the task. While it will require a fair amount of book keeping in your application, it should allow you to do what you need. Note, there may be an issue with this value rolling over when it reaches 2^32, however at the rates you're running I suspect that this would not be an issue.
Hope that helps,
Dan
08-03-2017 10:28 AM
I am struggling to make this method work (suggested to the OP)... I am using USB-6211:
1) Use a pause trigger to pause your output. This way you will avoid stopping and starting the task, and you will not lose all of the buffered up data.
- There is no software pause trigger, so the source will need to be an actual signal. You can make this happen by using DIO on your device to write a digital line high or low depending on whether you would like to pause or not. Wire this digital line to a PFI line, and use the PFI line as your pause trigger source.
I am not finding a way to use a PFI line as the /Dev1/aoPauseTrigger source.
For example, using DAQmx Connect Terminals, I get error -89121 for the small bit of code in the attachment.
I'm able to create analog output tasks and run the analog output, no problem. Same for creating digital I/O tasks.
Just can't get the AO Pause Trigger working. I'm using non-regenerative analog outputs, analog data is transferred in small buffers when the device buffer is less than half full. The aoPauseTrigger is not even shown as an option when I browse /Dev1. Any suggestions?
08-03-2017 10:43 AM
Solved my own problem.
Turns out that you need to specify the aoPauseTrigger signal as:
/Dev1/ao/PauseTrigger
Then the bit of code I pasted above works for the USB-6211.