Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and other free resources.
Don't worry -- youre-mail address is totally secure. I promise to use it only to send you MicroZine.

Arduino ADC

The Arduino ADC or Analogue to Digital Converter takes an input voltage and converts it into a digital value. With the standard setup you can measure a voltage between 0V and 5V with a resolution of 4.9mV so you can get a lot of detail when measuring analogue voltages.

Arduino Analog Pins

There are six pins on the Arduino Uno (shown below A0 ~ A5) that can be selected for an ADC measurement; A multiplexor feeds one of the six analogue input pins into the ADC.

TIP: Arduino Analog pin numbers for different Arduino devices are here.

To read an analogue voltage from pin A4 you use the following function:


Setting of the multiplexor is done in that function for you automatically.

arduino uno analogue pins

Arduino ADC Specification

Arduino Uno/Nano
  Voltage Supply (Vs)
 1V8 ~ 5V5
Built in
8 bit
  Absolute accuracy (Including INL, DNL,
  quantization error, gain,offset error) [1]
  Offset error (ADC, DAC) [1]
  INL [1]
0.50 LSB
  DNL [1]
0.25 LSB
  Gain error [1]
  Sampling frequency
  Operating temperature
-40°C ~ 85°C
            [1] for 4V operation and 200kHz clock.

Arduino ADC size

The Arduino ADC has a 10 bit converter, and that means there are 1024 distinct values that can be returned as a result from the ADC:

since  pow(2,10) = 2^10 = 1024

Divide by 1023 or 1024?

There is always some confusion about whether to divide by 1024 or 1023 to get the voltage value for each bit.

However the ATMega328P datasheet gives the following formula:

ADC= (Vin*1024)/Vref

re arranging that gives:

Vin = (Vref/1024)*ADC

Arduino ADC resolution at 5V

So for Vref=5V, an ADC value of 1 would result in a Voltage step of 4.88mV - the value of voltage for one LSB - this is the Arduino ADC resolution for a 5V Vref.

Note however that the maximum ADC value is 1023 so the maximum ADC value that can ever be reported is:

1023 * (5/1024) = 4.9951V

As it states in the datasheet:

"0x000 represents analog ground, and 0x3FF represents the selected reference voltage minus one LSB."

The reason that you will see the wrong equation on the web is so that the output "feels" right i.e. 1023*(5/1023) = 5.000. This is the wrong equation to use and means there is an offset added to all values.

How the Arduino ADC works

This ADC is known as a successive approximation ADC and requires several clock cycles to zoom in on the correct ADC output.

The ADC converter compares the input analogue voltage to a portion of Vref using a divide by two sequence. The sample and hold capacitor is charged to the input voltage and then the input disconnected so that the same voltage is measured throughout the conversion process.

It first checks whether the input voltage is higher or lower than half the Vref voltage, by using a DAC to generate half the reference voltage. The DAC voltage is the fed into a comparator.

The output of the DAC forms the high bit of the result (stored in a shift register). If the input voltage is higher then the bit is one, otherwise the bit zero.

If the input is lower than half Vref then control logic generates a DAC voltage that is 1/4 the reference voltage. The comparison is made again and this forms the next bit in the ADC output.

The process continues until all the bits are collected.

ADC clock

For the Arudino the conversion process takes 13 cycles of the ADC clock - which you set using a prescaler in the ADC module. The ADC clock must be between 50kHz and 200kHz so you choose the prescaler value to get a valid ADC clock.

The ADC clock prescaler can be set as a 2n division from 2 to 128. You obviously want the fastest conversion rate for the clock in use so for a 16MHz system clock you would calculate 16e6/200e3 = 80 so the closest could be 64.

However 16e6/64 is 250kHz and is too big. Therefore choosing a divisor of 128 must be used so the ADC clock will be 16e6/128 = 125kHz.

A conversion will take (check these settings are used in the Arduino Source code! - I have not - they are extremely likely though)

Arduino Uno sampling rate (16MHz crystal)

1.0 / ( 13 * 1.0/125e3) = 9615Hz

Actually, reading the Arduino reference page it says the sample rate is about 10kHz so this calculation matches that information.

So the maximum Arduino ADC sampling rate is:


Changing the Arduino Sampling Rate

ADC clock calculations

If you set the system clock to 20MHz you get 20e6/128 = 156250.0 - for a bit faster conversion.

Interestingly if you go the other way as a design decision you want the fastest ADC clock rate of 200kHz, then you have to ask the question:

"What crystal clock results in a 200kHz rate after ADC prescaling?" i.e.

Xtal = 200e3 * prescale - trying 64 gives 12800000 or 12.8Mhz

12.8e6/64 = 200e3

So  reducing the Xtal clock allows a faster conversion rate of 200kHz!

Giving a max samping rate of:

1.0 / ( 13 * 1.0/200e3) = 15384Hz (THIS IS FOR  A 12.8MHz XTAL)

...and yes you can get crystals made to your spec! - but you'll probably use a 12MHz crystal, as its easier to get, so the sample rate above will be a bit lower.

Example operation of 4bit ADC

This is a diagram of the action or the successive approximation ADC using Vref as 5V. Here a 4 bit ADC is shown but the principle is the same however many bits are used.

4 bit ADC Operation

Initially the input voltage (Vin) is greater than the starting value of the DAC voltage (set by initial DAC value of B1000) so this bit is kept. In the next processing period the DAC output is set to B1100 but in this case the DAC voltage becomes greater than Vin (and that bit is discarded).

The next two DAC values are kept because the DAC voltage is always lower than Vin and you end up with an ADC output value of B1011 - the ADC successively approaches the final value.

Example of successive approximation 4bit ADC

The final output DAC voltage is 2.5 + 0.625 + 0.3125 = 3.4375V

The advantage of the successive approximation ADC is that it is deterministic i.e. it always takes the same amount of time. Consider using a binary counter as the input to the DAC that always started at zero and counted up. For a low Vin it would take a few counts to find the value and for a high Vin it would take lots of counts (possibly 255 cycles for an 8 bit DAC) i.e. it would take different times depending on the input voltage!

Note: As the number of bits in the ADC increases so does the acquisition time.

Arduino Uno ADC resolution

As we saw earlier the resolution of the ADC, when Vref=5V is 4.88mV per step.

The Arduino analogRead resolution which is the same as the resolution of the ADC is governed by two things

  1. The ADC size - 10bits for the Uno.
  2. The ADC reference voltage.
Note: The arduino function analogReadResoution() allows the analogRead() function to return a different number of bits.

Some of the Arduinos e.g. DUE have 12 bit ADCs built in, so returning 10bits will keep the code in these boards compatible with other Arduino boards that only have a 10 bit ADC. This is the default operation - to get 12 bits you will need to use analogReadResoution(12). 

ADC bits

Using an ADC with more bits makes the the minimum step size (LSB) smaller to give higher resolution. The Arduino Uno is fixed at 10 bits.

ADC Reference voltage

The other way to affect the arduino ADC resolution is to use a different reference voltage. The reference voltage is the full-scale voltage applied to the ADC converter operating as described above.

Say you changed the Vref value to 1V then the minimum LSB you could detect would be 1/1024 or


TIP: You can select the internal 1.1V reference and this will give a step size of about 0.1V: Exact calculation is 1.1/1024 = 0.00107V ~0.11mV per step . This does mean the ADC can't read voltages above 1.1V - they will just return 1024.

Example ADC Use

Connect a 10k potentiometer with wiper (middle) to pin A0 and one end to 5V, and the other end to Ground. This example simply uses the arduino analog read function analogRead() to read data from the specified analogue pin.

Start the serial monitor, and observe the led period. The on-off time is twice the value of the analogue value so it varies from 2s to ~0.

  Analog Input

  Demonstrates analog input by reading an analog sensor on analog pin 0 and
  turning on and off a light emitting diode(LED) connected to digital pin 13.
  The amount of time the LED will be on and off depends on the value obtained
  by analogRead().

  The circuit:
  - potentiometer
    center pin of the potentiometer to the analog input 0
    one side pin (either one) to ground
    the other side pin to +5V
  - LED
    anode (long leg) attached to digital output 13
    cathode (short leg) attached to ground

  - Note: because most Arduinos have a built-in LED attached to pin 13 on the
    board, the LED is optional.

  created by David Cuartielles
  modified 30 Aug 2011
  By Tom Igoe

  This example code is in the public domain.

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() {
  // declare the ledPin as an OUTPUT:
  pinMode(ledPin, OUTPUT);

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  // turn the ledPin on
  digitalWrite(ledPin, HIGH);
  // stop the program for <sensorValue> milliseconds:
  // turn the ledPin off:
  digitalWrite(ledPin, LOW);
  // stop the program for for <sensorValue> milliseconds:

New! Comments

Have your say about what you just read! Leave me a comment in the box below.

Privacy Policy | Contact | About Me

Site Map | Terms of Use

Visit our Facebook Page:
To Visit Click Here

Recent Articles

  1. INA219: A voltage and current sensing chip using I2C

    INA219: How to use the INA210 for maximum accuracy in current and power measurements

    Read more

  2. How to use Arduino shiftIn() for reading data from a 3 wire serial interface

    The Arduino shiftIn() function can simply can accept data from paralle to serial converter chips. Find out how it works and how fast it operates.

    Read more

  3. Logic Level Converters made easy

    How to easily make a logic level converter e.g. between 3V and 5V.

    Read more

  4. How to use Arduino shiftOut() for controlling chips with a 3 wire serial interface

    The Arduino shiftOut() function can simply control many different serial interfaced chips. Find out how it works and how fast it operates.

    Read more

  5. How to use the ADS1115

    A tutorial on using the ADS1115 precision 16 bit ADC for low power use.

    Read more

  6. The TP4056: Lithium Ion/polymer Battery Charger IC

    Learn how to use the TP4056 properly. There's a right, and a wrong way, to use it to safely charge Lithium Ion batteries.

    Read more

Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's


- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan


"Awesome site,
very, very easy and nice
to navigate!"

- Matt

Learn Microcontrollers

"Interested in

Sign up for The
Free 7 day guide:


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."

- Dave


"Your site is a great
and perfect work.

- Suresh


"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.

- Anon

Back to Top