Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Arduino & Microcontrollers

Arduino ADC Tutorial: analogRead(), Resolution & Accuracy

Arduino ADC Tutorial: analogRead(), Resolution & Accuracy

March 11, 2026 /Posted byJayesh Jain / 0

The ability to read real-world analogue signals — voltages from sensors, potentiometers, thermistors, light-dependent resistors — is one of the most powerful features of any microcontroller. Arduino’s built-in Analogue-to-Digital Converter (ADC) makes this straightforward with the familiar analogRead() function. But there’s a lot more to the Arduino ADC than that single function call. In this tutorial you’ll understand exactly how the ADC works, what limits its accuracy, and how to squeeze the best possible precision from your analogue readings.

How the Arduino ADC Works

The ATmega328P (Arduino Uno/Nano) contains a 10-bit successive approximation ADC with a built-in sample-and-hold circuit and a 6:1 multiplexer that connects six analogue input pins (A0–A5) to a single ADC core.

“10-bit” means the ADC divides the input voltage range into 2¹⁰ = 1024 discrete steps (values 0 to 1023). With the default 5 V reference, each step represents:

Voltage per step = 5.0 V / 1024 = 4.88 mV

So analogRead(A0) returning 512 means the pin is at approximately 5.0 × 512/1024 = 2.5 V.

The conversion uses a successive approximation technique: it internally generates a test voltage using a DAC, compares it against the input, and converges on the correct digital value bit by bit. Each 10-bit conversion typically takes 100 µs (13 ADC clock cycles at the default 125 kHz ADC clock derived from the 16 MHz system clock with a 128 prescaler).

Recommended: Arduino Uno R3 Beginners Kit — includes a potentiometer and multiple sensors perfect for exploring all six ADC channels and comparing readings in real time.

analogRead() Basics and Voltage Conversion

The analogRead(pin) function returns a value from 0 to 1023:

int rawValue = analogRead(A0);  // 0 to 1023

// Convert to voltage (assuming 5V AREF)
float voltage = rawValue * (5.0 / 1023.0);
Serial.print("Voltage: ");
Serial.print(voltage, 3);
Serial.println(" V");

Notice 5.0 / 1023.0 (not 1024). The maximum reading of 1023 corresponds to AREF, so dividing by 1023 maps 1023 → full AREF voltage. Dividing by 1024 would give a maximum of 1023/1024 × 5.0 = 4.995 V — technically more correct if you think of it as a step index, but convention varies. For most practical purposes, the difference is negligible.

Practical Example: LM35 Temperature Sensor

#include <Arduino.h>

void setup() {
  Serial.begin(9600);
}

void loop() {
  int raw = analogRead(A0);
  float voltage = raw * (5.0 / 1023.0);  // Voltage at A0
  float tempC = voltage * 100.0;          // LM35: 10mV per °C

  Serial.print("Temperature: ");
  Serial.print(tempC, 1);
  Serial.println(" °C");
  delay(1000);
}
Recommended: LM35 Temperature Sensors — the classic linear temperature sensor with 10 mV/°C output; the definitive ADC learning component for Arduino beginners.

Voltage Reference: AREF, Internal, and External

The ADC measures voltage relative to a reference. The reference sets what voltage corresponds to a full-scale reading (1023). Arduino supports three reference options:

DEFAULT (5V or 3.3V supply)

Uses the AVcc power supply pin as reference. On a 5V Uno, this is nominally 5 V. Simple, but tracks power supply noise.

analogReference(DEFAULT);  // This is the default — usually not needed

INTERNAL (1.1V)

The ATmega328P has a built-in 1.1 V bandgap reference. Switching to this dramatically improves resolution for low-voltage sensors:

analogReference(INTERNAL);  // 1.1V reference on Uno/Nano

// Now each ADC step = 1.1V / 1024 = 1.07 mV (vs 4.88 mV default)
// Much better for reading small voltage differences!

float voltage = analogRead(A0) * (1.1 / 1023.0);

With INTERNAL reference, inputs above 1.1 V will saturate at 1023 — watch your signal levels.

EXTERNAL (AREF pin)

Apply any voltage between 0 V and VCC to the AREF pin for a custom reference:

analogReference(EXTERNAL);
// Connect a precision 2.048V reference IC to AREF pin
// Each step = 2.048V / 1024 = 2.0 mV exactly
// Great for calibrated measurements

Always call analogReference() before the first analogRead(). Switching reference mid-session causes the first few readings to be inaccurate (the sample-and-hold capacitor needs to charge to the new reference level). Discard the first 5–10 readings after switching.

ADC Speed: Changing the Prescaler

By default the ADC clock is 16 MHz / 128 = 125 kHz, giving ~10,000 samples/second. You can increase ADC speed by reducing the prescaler — at the cost of accuracy:

// Prescaler settings: higher prescaler = slower but more accurate
// ADPS2, ADPS1, ADPS0 bits in ADCSRA register

// Prescaler 16 → ADC clock 1 MHz → ~77,000 samples/s (reduced accuracy)
ADCSRA = (ADCSRA & ~0x07) | 0x04;

// Prescaler 32 → ADC clock 500 kHz → ~38,000 samples/s
ADCSRA = (ADCSRA & ~0x07) | 0x05;

// Prescaler 64 → ADC clock 250 kHz → ~19,000 samples/s
ADCSRA = (ADCSRA & ~0x07) | 0x06;

// Prescaler 128 → ADC clock 125 kHz → ~10,000 samples/s (default, best accuracy)
ADCSRA = (ADCSRA & ~0x07) | 0x07;

For most sensor applications the default is ideal. Only use faster prescalers for audio sampling or fast waveform capture where you need >10 kSps and can tolerate 8–9 effective bits of precision instead of 10.

Recommended: BMP280 Barometric Pressure and Altitude Sensor I2C/SPI Module — uses digital I2C/SPI output with 24-bit internal ADC for precision that far exceeds the Arduino’s 10-bit ADC; shows when you need external high-resolution conversion.

Reducing ADC Noise

Raw analogRead() often shows ±2–4 LSB of noise from digital switching, power supply ripple, and electromagnetic interference. Several techniques help:

Software Averaging

int averagedRead(int pin, int samples = 16) {
  long sum = 0;
  for (int i = 0; i < samples; i++) {
    sum += analogRead(pin);
  }
  return (int)(sum / samples);
}

void loop() {
  int reading = averagedRead(A0, 32);  // Average 32 samples
  Serial.println(reading);
  delay(100);
}

Averaging 16 samples improves noise immunity by a factor of 4 (2 bits). Averaging 64 samples improves by a factor of 8 (3 bits). Beyond 256 samples the ADC’s own nonlinearity dominates.

Oversampling and Decimation (Free Extra Bits)

A clever technique: if you oversample by 4ⁿ samples and sum them (without averaging), you gain n extra bits of resolution:

// Oversampling for 12-bit resolution (4× = 2 extra bits)
long oversampledRead(int pin) {
  long sum = 0;
  for (int i = 0; i < 16; i++) {  // 4^2 = 16 samples for 2 extra bits
    sum += analogRead(pin);
  }
  return sum >> 2;  // Right-shift by n (2) → 12-bit result (0 to 4095)
}

// For 13-bit: 64 samples, shift right by 3
// For 14-bit: 256 samples, shift right by 4

This works because random noise partially cancels when summed, while the true signal accumulates. The result is a legitimately higher-resolution reading — not just filtered noise.

ADC Noise Canceller Sleep Mode

The ATmega328P has a dedicated ADC Noise Canceller mode that halts the CPU during conversion to eliminate digital switching noise:

#include <avr/sleep.h>

int quietRead(int pin) {
  analogRead(pin);  // Discard first reading to stabilise MUX
  set_sleep_mode(SLEEP_MODE_ADC);
  sleep_enable();
  sleep_cpu();      // CPU halts; ADC completes its conversion
  sleep_disable();
  return ADC;       // Read the ADC result register directly
}

This can reduce ADC noise by 2–3 LSB in electrically noisy environments.

Recommended: DHT20 SIP Packaged Temperature and Humidity Sensor — uses a calibrated digital output rather than raw ADC; shows how digital sensor protocols bypass ADC limitations for high-accuracy environmental measurements.

Understanding ADC Accuracy Limits

Even with perfect hardware, the Arduino’s ADC has fundamental accuracy limits you should understand:

  • Offset error: The ADC may read a small non-zero value for a zero-volt input (typically ±1–2 LSB). Calibrate by measuring a known 0 V reference.
  • Gain error: The slope of the ADC transfer curve may differ slightly from ideal. Calibrate with a known reference voltage at full scale.
  • INL/DNL (Integral/Differential Non-Linearity): The ATmega’s ADC is specified for ±2 LSB INL (absolute accuracy). This is the hard floor — you cannot calibrate away nonlinearity.
  • Power supply dependency: With DEFAULT reference, a 1% power supply variation causes a 1% reading error. Use INTERNAL or EXTERNAL reference for supply-independent measurements.
  • Crosstalk between channels: The MUX and sample-and-hold circuit need settling time after switching channels. Read the same channel twice and discard the first reading when switching.

Reading Multiple ADC Channels Correctly

// Best practice for multi-channel reading:
void readAllChannels() {
  int lastChannel = -1;

  for (int ch = 0; ch <= 5; ch++) {
    if (lastChannel != ch) {
      analogRead(ch);   // Dummy read to allow MUX to settle
    }
    int value = analogRead(ch);  // Real reading
    lastChannel = ch;

    Serial.print("A");
    Serial.print(ch);
    Serial.print(": ");
    Serial.println(value);
  }
}

Frequently Asked Questions

What is the maximum voltage I can read with Arduino analogRead()?

With the DEFAULT reference on a 5V Arduino, the maximum measurable voltage is 5 V (reading = 1023). On a 3.3V board like Arduino Nano 33 IoT, the maximum is 3.3 V. Never apply more than VCC to an analogue input pin — it can permanently damage the ADC and the microcontroller.

Why does my analogRead() value fluctuate even with nothing connected?

A floating (unconnected) analogue pin picks up ambient electromagnetic interference, resulting in random readings. Always connect analogue inputs to a defined voltage — use a pull-down resistor to GND if the source has high impedance, or connect directly to GND when testing with no sensor.

Can I get more than 10-bit resolution from Arduino ADC?

Yes, through oversampling and decimation. By taking 4ⁿ samples and shifting right by n bits, you gain n extra bits of effective resolution. Taking 256 samples gives 4 extra bits (14-bit resolution), though this takes 256 × 100 µs = 25.6 ms per reading. For true high-resolution ADC, use an external I2C ADC like the ADS1115 (16-bit, 4 channels).

How do I measure negative voltages with Arduino ADC?

The Arduino ADC is unipolar — it cannot directly measure voltages below GND. To measure negative voltages, use an op-amp circuit to shift the signal up into the 0–5 V range before feeding it to the ADC. A simple voltage divider with a mid-point bias shifts a ±2.5 V signal to 0–5 V.

What is the input impedance of Arduino analogue pins?

The ATmega328P ADC datasheet specifies a maximum source impedance of 10 kΩ for accurate readings. Higher source impedance means the sample-and-hold capacitor doesn’t fully charge during the sampling window, causing reading errors. If your sensor has high output impedance (>10 kΩ), buffer it with a voltage follower op-amp before the ADC input.

Start Reading the Analogue World

Understanding the Arduino ADC fully — its resolution, reference options, noise sources, and calibration techniques — puts precise analogue measurement firmly within your reach. From reading a simple potentiometer to building a calibrated multi-channel data logger, the 10-bit ADC (and oversampling beyond that) covers a remarkable range of real-world applications.

Ready to build your next sensor project? Find sensors, Arduino boards, and accessories at Zbotic.in — genuine components delivered fast across India.

Tags: adc resolution, arduino adc, arduino analog input, arduino analogread, arduino sensor reading, arduino voltage reference
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Arduino IR Remote Decode: NEC ...
blog arduino ir remote decode nec vs sony vs rc5 protocols 594861
blog raspberry pi kubernetes deploy k3s cluster on multiple pis 594863
Raspberry Pi Kubernetes: Deplo...

Related posts

Svg%3E
Read more

Arduino Batch Programming: Flash Multiple Boards Quickly

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Based Radar System with Ultrasonic Sensor

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Automatic Plant Monitor: Sunlight, Moisture, Temperature

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Lie Detector: GSR Sensor Polygraph Project

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Metal Detector: Build a Treasure Finder

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now