Data Acquisition Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
Kevin_Price

AO, DO - query for current output value

Status: New

We need a way to query an output task to determine its most recently output value.  Or alternately, a general ability to read back data from an output task's buffer.

 

This one's been discussed lots of times over the years in the forums but I didn't see a related Idea Exchange entry.  Most of the discussion I've seen has related to AO but I see no reason not to support this feature for DO as well.

 

There are many apps where normal behavior is to generate an AO waveform for a long period of time.  Some apps can be interrupted unexpectedly by users or process limit monitoring or safety range checking, etc.  When this happens, the output task will be in a more-or-less random phase of its waveform.  The problem is: how do we *gently* guide that waveform back to a safe default value like 0.0 V?  A pure step function is often not desirable.  We'd like to know where the waveform left off so we can generate a rampdown to 0.  In some apps, the waveform shape isn't directly defined or known by the data acq code.  So how can we ramp down to 0 if we don't know where to start from?  This is just one example of the many cases where it'd be very valuable to be able to determine the most recently updated output value.

 

Approach 1:

  Create a DAQmx property that will report back the current output value(s).  I don't know if/how this fits the architecture of the driver and various hw boards.  If it can be done, I'd ideally want to take an instantaneous snapshot of whatever value(s) is currently held in the DAC.  It would be good to be able to polymorph this function to respond to either an active task or a channel list.

 

Approach 2 (active buffered tasks only):

   We can currently query the property TotalSampPerChanGenerated as long as the task is still active.  But we can't query the task to read back the values stored in the buffer in order to figure out where that last sample put us.  It could be handy to be able to query/read the *output* buffer in a way analogous to what we can specify for input buffers.  I could picture asking to DAQmx Read 1 sample from the output buffer after setting RelativeTo = MostRecentSample , Offset = 0 or -1 (haven't thought through which is the more appropriate choice).  In general, why *not* offer the ability to read back data from our task's output buffers?

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
5 Comments
JB
Trusted Enthusiast
Trusted Enthusiast

Hi Kevin,

 

You can measure the current value of an analog output without any external wiring by the use of the _aox_vs_aognd internal channel (x = number of analog output). Among others, this internal channel is used by the DAQ board during its self-diagnostics and self-calibration.

I don't know if all listed channels (for E-Series) are still supported for M and X-Series boards or, in opposite, if there are some additionnal channels for these boards. At least, I have used _aox_vs_aognd in one of my recent applications with X-Series DAQ boards.

 

Here is a snippet of my code. Sorry for the original french comments ! The upper measurement returns the raw voltage, the lower the signal according to the custom scale of the virtual global channel.

 

Mesurer voie globale AO interne.png 

 

The value of a DO can be read by a simple DI measurement.

 

Obviously, the suggested DAQmx property would made this much easier.

 

Best regards

Kevin_Price
Proven Zealot

JB,

 

Thanks!  This method looks like a viable solution, provided that these direct untimed reads can be done without disturbing any clocked AI task that may be running. 

 

I forgot all about those internal channels. I only ever tinkered with them once when I was troubleshooting a rig under strict wiring config control.  I interleaved the _aignd_vs_aignd between the real ai channels in my channel list as a quick-and-dirty attempt to bleed off ADC charge and minimize "ghosting" effects when going from large to small signals.  (Dunno if it was a good idea or not.  It made no appreciable difference in our readings, but I don't know whether that's because it was a bad idea or because it's an ok idea for solving a problem we didn't happen to be experiencing.  ANYway...)

 

I don't have access to a data acq board now, but can you perform a DAQmx Read on a DO task?   Or do you just quickly create a DI task from the same channel to do the read?  I coulda sworn I got errors trying to perform a Read operation on an output task way back in the early days of DAQmx and have been avoiding it for all these years since.  Maybe it's just a case of me learning the wrong lesson and having it stick.

 

Thanks again for the work-around tip!

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Brad_K
Active Participant

Hi Kevin,

 

Thanks for posting, this is an interesting idea.

 

Another feature to think about is the AO.IdleOutputBehavior property, which is supported on the NI 4461 and NI 4431 DSA devices, but there's no technical reason it couldn't be supported on more devices, minus the "High Impedance" option. It controls what happens to the AO output when the task is stopped, with options of "Zero Volts", "High Impedance", and "Maintain Existing Value". Perhaps a "Ramp to Zero Volts" option would make sense, with an additional property to control how quickly it ramps?

 

> I don't have access to a data acq board now, but can you perform a DAQmx Read on a DO task?

 

Yes, you can read from a DO task. You can also monitor DIO lines while another task is using them by creating a DI task and setting DI.Tristate=false.

 

> Approach 1: Create a DAQmx property that will report back the current output value(s).  I don't know if/how this fits the architecture of the driver and various hw boards.

 

One corner case that is probably difficult to handle without additional hardware support is on-board regeneration. In that mode, I'm not sure if DAQmx keeps a copy of the data around anywhere except the board's AO FIFO, which is typically write-only from software's perspective.

 

Custom scales also add an interesting twist. Polynomial custom scales have separate forward and reverse polynomials. For AO, the forward polynomial is used when scaling data from engineering units to raw DAC codes, and the reverse polynomial is an approximation used when coercing the AO.Min and AO.Max properties. Reading the raw DAC code from the hardware or from the buffer and scaling it to floating point may result in a different value than was originally written. And DAQmx doesn't keep all of the original floating point values around.

 

Brad

---
Brad Keryan
NI R&D
stilly32
Active Participant

Hey Kevin,

 

Thanks for posting. Just to tack on another possible work around: if you have a spare counter you can just count the AO/DO sample clocks. If what you know you've written you can figure out the last sample - even for onboard regeneration. It wouldn't help much if you were writing new waveforms on the fly with regeneration enabled. With non regeneration it should still be workable.

 

It obviously wouldn't help if your whole program was interrupted however, so a DAQmx solution to query would still be valuable.

 

Cheers,

Andrew S  

BertMcMahan
Active Participant

I'd like to ring this bell a little. I hadn't seen this idea before but I just gave it a Kudo and wanted to throw in a comment as well to give it a little more traction. I personally would love to be able to know where I left off as I deal with piezoelectric actuators very frequently, and sudden changes in voltage can break the actuator. I normally have to use non-regenerating output and write my own sinusoid "tapering" waveform from wherever the buffer was when the user clicked "Stop". This works most of the time but isn't a solution for systems that need to stop right now and can't wait a couple of buffers to slowly taper to zero.

 

A "ramp to zero" mode wouldn't work for my case as it needs to be a smooth curve. Spikes/corners like a sudden ramp can, in extreme cases, cause damage to the actuators. You can certainly make it work with a slow enough ramp, but in general it's better to start out at dV/dt=0.

 

Hopefully we get this feature one of these days 🙂