34 Analog Input
Resolution in Analog to Digital Conversion
Analog to Digital Conversion (ADC or A/D) gives an unsigned integer result proportional to an analog voltage input and the resolution of that result is expressed in bits, e.g. an Arduino UNO has a 10 bit ADC, or an M0 processor has a 12 bit A/D. The number of possible values an integer can take on is limited by the number of binary bits. A single bit can be either 1 or 0 for two values, 2 bits can represent 4 values, etc.
The 10 bit resolution of the UNO can have 1024 distinct values, 0-1023, so each step represents 1/1024 of the range or 0.0009765. If the range is 5 volts, this results in a resolution of 4.88 mV per division.
Other common resolutions are 12 and 16 bits, resulting in 4096 and 65536 steps respectively. To make high resolutions worthwhile, it is important to reduce other sources of uncertainty such as noise.
When estimating the uncertainty due to an analog conversion process, start by assuming plus or minus one resolution step unless you have better information. Thus, when measuring temperature with a TMP36 on an UNO, the zero order uncertainty would be +/- 4.88 mV or +/-0.488 C simply due to the analog to digital conversion process.
Conversion Processes and Translation to Voltage Values.
Initially we will use the default voltage reference of the nominal processor power supply ( 5.0 V on the UNO and 3.3 V on the M0) and we can make an approximate conversion with V = Vref * analogRead(A0) / 1023.
Later we will look at measuring the reference voltage more accurately and options for using different reference voltages.
Following the conceptual process the UNO uses to convert analog voltages into integer representations helps understand why the process isn’t instantaneous. It also helps to see why the best conversion is V=Vref*(A+0.5)/1024
instead of the nearly identical V=Vref*A/1023
for this low resolution conversion.
(Video 9:29)
With 32 bit processors like the M0 you can set the resolution at which the results will be reported using the analogReadResolution(bits)
function. It defaults to 10 bits (0-1023) even on boards that allow better resolution. You can set it to 16 bits (0-65535) even if the processor doesn’t support the full resolution and the results will be scaled accordingly. If you choose 16 bits, you can use V=Vref*A/65535
for conversion for all processors. (The UNO always uses 10 bit resolution and doesn’t support the analogReadResolution()
function.)
Choosing a Reference Voltage
The Arduino IDE lets us choose the reference voltage for comparisons when doing analog to digital conversions by using the analogReference()
function. On the M0 there are a wide range of options, including the default 0-3.3V and options like analogReference(AR_INTERNAL1V65)
for a 0-1.65 volt range. With internal ranges of 1.0, 1.65, and 2.23 volts, you probably have enough flexibility to avoid needing analogReference(AR_EXTERNAL)
to create your own range.
On the UNO the range can be 0-5V (default to the power supply voltage), 0-1.1V with analogReference(INTERNAL)
, or anywhere in between with analogReference(EXTERNAL)
. Using the 3.3V supply as a reference can help reduce the noise and uncertainty compared to using the primary power supply as a reference. Just make sure the hardware matches the code! (Video 2:08)
Higher Impedance Circuits
If you build a voltage divider with large resistances like 10K, there will be very little current flowing. Every analog to digital conversion will require a little bit of current, and that will pull down the centre voltage of the divider just for a moment. On an Arduino UNO, the drop will be about 8 millivolts and the moment will last less than a microsecond. You can smooth out that drop by adding a capacitor, but on the UNO it makes no difference in the result you get from analogRead(), no matter how quickly you sample, and that’s a good thing. The video (3:59) shows the circuit and the resulting transient signals when collecting data on an UNO and an M0.
On an M0 processor like the Adafruit Feather M0 board, things are a little more complicated. The analog input channel is noisy and the current draw during analog to digital conversion is more complex because it takes multiple samples in hardware. Once again, you can smooth out the transient by adding a capacitor, and there is still a minimal effect on individual samples, however sampling at a high sample rate pulls the voltage down repeatedly, resulting in a slightly lower average reading. In a 10K voltage divider this was still less than 1%, but merits correction if you want your measurements to be as accurate as possible. Two easy options are to either slow your sample rate until the effect disappears, or use an op-amp as a voltage follower to provide higher current output from your circuit.