High-speed Analog Reads with AnalogInputArrays
Did you know that since Meadow.OS v1.6, you can use the Direct Memory Access (DMA) feature on the F7 to do Analog to Digital Conversions (ADC) at an incredibly high sampling rate?
While the AnalogInputPort
provides a powerful way to do analog port reads and oversampling, the AnalogInputArray
adds functionality to sample multiple analog inputs at an incredibly high rate of speed; up to 37,000 samples per second.
Classic AnalogInputPort
To understand how the new functionality differs from traditional analog sampling, consider the following sample code that uses an AnalogInputPort
:
var analogIn = Device.CreateAnalogInputPort(
pin: Device.Pins.A00,
sampleCount: 5,
sampleInterval: TimeSpan.FromSeconds(5)
);
analogIn.Updated += (s, result) =>
{
Resolver.Log.Info($"Analog event," +
$"new voltage: {result.New.Volts:N2}V," +
$"old voltage: {result.Old?.Volts:N2}V");
};
In the above sample, an IAnalogInputPort
is created IPin
, that takes a periodic reading a single analog input every 5 seconds, with an oversample count of 5, which takes 5 consecutive readings and then provides their average to account for noise.
This works great for reading analog sensors like thermistors where you don’t need the value very often; since the AnalogInputPort
on the F7Feather
can be read up to about twice a second.
But there are many cases where an application needs to read the ADC much faster and the IAnalogInputPort
simply cannot deliver the performance needed.
AnalogInputArray
Meadow 1.6 introduced a new type: the AnalogInputArray
. This new type has less “frills” than the Port
version. For example it has no events, and it does not support Observers. Instead, it is designed to just read data, and read it quickly. Once created, you simply have a single method to update the Array values: Refresh()
.
For example, assume we want to read 3 Analog input pins, having each fill a 1000-sample buffer as fast as we can. To do this, we simply create an AnalogInputArray
with our target pins, then call Refresh
1000 times, copying the read data to a local buffer after every read:
var array = Device.CreateAnalogInputArray(Device.Pins.A00, Device.Pins.A01, Device.Pins.A02);
var readsPerIteration = 1000;
var a0 = new double[readsPerIteration];
var a1 = new double[readsPerIteration];
var a2 = new double[readsPerIteration];
while (true)
{
// read 1k samples as fast as we can
for (var i = 0; i < readsPerIteration; i++)
{
// tell the Array to read all of its inputs
array.Refresh();
// copy the Array data to a local buffer
a0[i] = array.CurrentValues[0];
a1[i] = array.CurrentValues[1];
a2[i] = array.CurrentValues[2];
}
}
This provides the ability to do very high rates of sampling, and because it’s done via DMA, it won’t tax the processor and lower its ability to perform other tasks!
For more information, check out the High Speed Analog Input guide.