Note: The functions described here use an old feature that is no longer implemented by the Comedi kernel layer. THEY WILL NOT WORK!
Sometimes, your input channels change slowly enough that
you are able to average many successive input values to get a
more accurate measurement of the actual value. In general,
the more samples you average, the better your estimate
gets, roughly by a factor of
sqrt
(number_of_samples
).
Obviously, there are limitations to this:
you are ultimately limited by “Spurious Free Dynamic Range”. This SFDR is one of the popular measures to quantify how much noise a signal carries. If you take a Fourier transform of your signal, you will see several “peaks” in the transform: one or more of the fundamental harmonics of the measured signal, and lots of little “peaks” (called “spurs”) caused by noise. The SFDR is then the difference between the amplitude of the fundamental harmonic and of the largest spur (at frequencies below half of the Nyquist frequency of the DAQ sampler!).
you need to have some noise on the input channel,
otherwise you will be averaging the same number N
times. (Of course, this only holds if the noise is large enough to
cause at least a one-bit discretization.)
the more noise you have, the greater your SFDR, but it takes many more samples to compensate for the increased noise.
if you feel the need to average samples for, for example, two seconds, your signal will need to be very slowly-varying, i.e., not varying more than your target uncertainty for the entire two seconds.
As you might have guessed, the Comedi library has functions to help you in your quest to accurately measure slowly varying inputs:
int comedi_sv_init( | comedi_sv_t *sv, |
comedi_t *device, | |
unsigned int subdevice, | |
unsigned int channel) ; |
The above function comedi_sv_init
initializes the
comedi_sv_t data structure, used
to do the averaging acquisition:
typedef struct comedi_sv_struct { comedi_t *dev; unsigned int subdevice; unsigned int chan; /* range policy */ int range; int aref; /* number of measurements to average (for analog inputs) */ int n; lsampl_t maxdata; } comedi_sv_t;
The actual acquisition is done with the function
comedi_sv_measure
:
int comedi_sv_measure( | comedi_sv_t *sv, |
double *data) ; |
The number of samples over which the function
comedi_sv_measure
averages is limited by the
implementation (currently the limit is 100 samples).
One typical use for this function is the measurement of thermocouple voltages. And the Comedi self-calibration utility also uses these functions. On some hardware, it is possible to tell it to measure an internal stable voltage reference, which is typically going to be very slowly varying; on the kilosecond time scale or more. So, it is reasonable to measure millions of samples, to get a very accurate measurement of the A/D converter output value that corresponds to the voltage reference. Sometimes, however, this is overkill, since there is no need to perform a part-per-million calibration to a standard that is only accurate to a part-per-thousand.