Arduino ADC and analogRead() Tutorial – Measure Analog Voltage in Arduino
In this tutorial, you’ll learn everything you need to know about the Arduino ADC (Analog-to-Digital Converter) and how to use the analogRead()
function to measure analog voltages. These two features allow your Arduino to read real-world signals like temperature, light intensity, and sound — and convert them into digital values your code can use.
We’ll start by understanding what an ADC is and how it works inside the Arduino. Then we’ll look at how the analogRead()
function converts sensor signals into numeric data. Finally, we’ll build a few practical examples such as a LED dimmer and motor speed controller using analog inputs.

What is ADC in Arduino?
The ADC (Analog-to-Digital Converter) in Arduino is a built-in feature that allows the microcontroller to read analog signals. These signals change continuously, like voltage from sensors. The ADC convert them into digital numbers, so that the Arduino code can process them.
Without the ADC, the Arduino wouldn’t be able to understand values from most sensors, such as light sensors, potentiometers, or temperature sensors. The ADC acts as a translator between the real, continuously changing world and the digital brain of your Arduino.
Understanding Analog-to-Digital Conversion
In simple terms, an analog signal is a voltage that can take any value within a range (for example, 0V to 5V). However, a microcontroller like the Arduino can only understand discrete digital values (like 0, 1, 2… up to a certain limit). The ADC converts this smooth analog input into a series of digital numbers that represent the voltage level at a given moment.
This process is called analog-to-digital conversion. Each voltage range is divided into equal steps, and each step is assigned a digital value. The higher the resolution of the ADC, the more precise the conversion will be.
Why Arduino Needs an ADC
Most sensors used in Arduino projects output analog voltages. For example:
- A temperature sensor outputs voltage proportional to the temperature.
- A light sensor (LDR) changes its resistance with light, creating different voltages.
- A potentiometer provides a variable voltage depending on its position.
The Arduino’s ADC is essential for reading these voltage values and converting them into numbers. These numbers can be used in calculations, displayed on screens, or used to control outputs like motors or LEDs.
How ADC Converts Analog Voltage to Digital Value
The conversion process is simple but powerful. The Arduino measures voltage on the analog pin and converts it into a number between 0 and 1023 (for a 10-bit ADC like on the Arduino UNO). The conversion depends on the reference voltage (VREF), which sets the maximum readable voltage — usually 5V or 3.3V depending on the board.
For example, if the reference voltage is 5V:
- 0V → digital value 0
- 2.5V → digital value 512
- 5V → digital value 1023
This means the Arduino can detect even small voltage changes, making it ideal for reading sensor outputs accurately.
Arduino ADC Explained
The Arduino ADC (Analog-to-Digital Converter) is a key feature that allows the board to read varying voltage signals from sensors and convert them into numbers your code can process. This makes it possible to measure things like light, temperature, or pressure and use those readings in your Arduino projects.
Arduino UNO ADC Features
The Arduino UNO is powered by the ATmega328P microcontroller, which includes a built-in 10-bit ADC. This converter can read analog signals on the board’s six analog input pins (A0–A5).
Each of these pins can detect voltages between 0V and 5V (the reference voltage), and the ADC translates that range into digital values from 0 to 1023. The ADC operates automatically when you use the analogRead()
function.
Other Arduino boards may have more analog pins or different reference voltages (like 3.3V on the Arduino Due or MKR series), but the conversion principle remains the same.
10-bit ADC and Resolution (0–1023)
The term 10-bit ADC means that the ADC divides the voltage range into 2¹⁰ = 1024 discrete levels. Each level represents a small voltage difference, also known as the ADC step size.
If your Arduino’s reference voltage (VREF) is 5V, then each digital step represents:
Step size = 5V ÷ 1024 = 4.88 mV per step
This means the Arduino can detect voltage changes as small as 4.88 millivolts. The more bits in the ADC, the finer and more accurate the readings will be.
How ADC Converts Voltage Steps
When you apply a voltage to one of the analog pins, the ADC measures that voltage and determines which digital “step” it corresponds to. The closer the input voltage is to the reference voltage, the higher the resulting ADC number.
The ADC conversion formula is:
ADC Value = (Input Voltage / VREF) × (2ⁿ – 1)
Where:
- VREF = Reference voltage (usually 5V or 3.3V)
- n = ADC resolution (10 bits for Arduino UNO)
Example – How 5V Input Becomes 1023 in ADC
Let’s take the Arduino UNO with a 10-bit ADC and 5V reference voltage as an example.
According to the formula:
ADC Value = (Vin / 5V) × 1023
- If Vin = 0V, ADC value = 0
- If Vin = 2.5V, ADC value = (2.5/5) × 1023 = 511.5 ≈ 512
- If Vin = 5V, ADC value = (5/5) × 1023 = 1023
This is how the Arduino converts a smooth analog voltage into a digital value your code can easily use in calculations, decisions, and control logic.
Arduino ADC Reference Voltage (VREF)
The reference voltage (VREF) in Arduino defines the maximum voltage that the Analog-to-Digital Converter (ADC) can measure. It sets the upper limit for the conversion range, meaning any voltage equal to VREF will give the highest possible ADC value (for example, 1023 on a 10-bit ADC).
Choosing the right reference voltage is important because it directly affects the accuracy and precision of your analog readings. A smaller VREF gives higher sensitivity for low-voltage signals, while a higher VREF allows measuring larger voltages.
Default and Internal Reference Options
By default, the Arduino uses its operating voltage as the reference:
- 5V reference on 5V boards such as Arduino UNO and Mega.
- 3.3V reference on 3.3V boards like Arduino Due, Nano 33, or MKR series.
However, Arduino also provides internal and external reference voltage options for more flexibility:
- DEFAULT – Uses the operating voltage (5V or 3.3V depending on the board).
- INTERNAL – Uses an internal voltage reference, typically around 1.1V (on UNO) or 2.56V (on some ATmega chips).
- EXTERNAL – Lets you connect your own reference voltage to the AREF pin.
Using an internal or external reference helps when working with low-voltage sensors or when you need more stable readings unaffected by power supply variations.
How to Change VREF using analogReference()
Arduino provides a simple function to change the reference voltage source — analogReference()
. This function allows you to select which reference voltage the ADC should use for conversions.
Syntax:
analogReference(type);
Example:
analogReference(INTERNAL); // Use the internal 1.1V reference
analogReference(DEFAULT); // Use the default 5V or 3.3V reference
analogReference(EXTERNAL); // Use external voltage applied to AREF pin
Important: When using the EXTERNAL option, make sure to connect a stable reference voltage to the AREF pin before calling analogReference(EXTERNAL)
. Never apply more than 5V to AREF to avoid damaging the board.
Why Reference Voltage Affects ADC Accuracy
The reference voltage determines the ADC’s sensitivity—that is, how much each step of the digital output represents in volts. The smaller the reference voltage, the smaller each step becomes, giving you finer measurement resolution.
For example:
- At VREF = 5V → Each step = 4.88 mV (5V / 1024)
- At VREF = 1.1V → Each step = 1.07 mV (1.1V / 1024)
This means using a lower reference voltage allows more precise readings of small signals. However, if your input voltage exceeds the reference voltage, the ADC will just output the maximum value (1023 for a 10-bit ADC).
So, choosing the right reference voltage depends on your project — use a smaller VREF for low-voltage sensors and the default reference for full-range measurements up to 5V.
Arduino ADC Speed, Sampling Time, and Conversion Rate
The Arduino ADC speed determines how fast the microcontroller can convert an analog signal into a digital value. This speed depends on the ADC’s internal clock frequency, conversion time, and the resolution used. Understanding how the ADC timing works is essential for applications that need fast or frequent analog readings, such as signal processing or real-time monitoring.
Default ADC Clock and Conversion Time
On the Arduino UNO (based on the ATmega328P), the ADC runs using a clock derived from the system clock (16 MHz) divided by a prescaler. By default, the prescaler is set to 128, which gives an ADC clock frequency of:
ADC Clock = 16 MHz / 128 = 125 kHz
This clock frequency is ideal for 10-bit conversions, providing a balance between speed and accuracy. Each ADC conversion takes approximately 13 ADC clock cycles, so the total conversion time is about:
Conversion Time = 13 × (1 / 125 kHz) ≈ 104 microseconds
This means the Arduino can perform roughly 9,600 to 10,000 ADC readings per second under default conditions.
Arduino ADC Sampling Rate Calculation
The sampling rate tells how many analog samples the Arduino can take per second. It is the inverse of the conversion time:
Sampling Rate = 1 / Conversion Time
Using the previous example:
- Conversion time ≈ 104 µs
- Sampling rate ≈ 1 / 104 µs ≈ 9,600 samples per second (9.6 kSPS)
If you increase the ADC clock frequency by lowering the prescaler, you can achieve a higher sampling rate, but it will slightly reduce the accuracy. For example:
- At 200 kHz ADC clock → Conversion time ≈ 65 µs → 15.4 kSPS
However, running the ADC too fast may cause noisy or unstable readings, so it’s important to find the right balance between speed and precision.
How to Increase ADC Speed Safely
You can safely increase the ADC speed by adjusting the prescaler value in the microcontroller’s ADC control register. Lowering the prescaler increases the ADC clock frequency, resulting in faster conversions.
Common prescaler values are 2, 4, 8, 16, 32, 64, and 128. The default (128) provides maximum accuracy, but you can reduce it for faster sampling:
- Prescaler 128 → 125 kHz ADC clock → Full accuracy (default)
- Prescaler 64 → 250 kHz ADC clock → Faster, slight accuracy loss
- Prescaler 32 → 500 kHz ADC clock → Much faster, more noise
For reliable 10-bit conversions, the ADC clock should remain below 200 kHz. Going beyond that may lead to inaccurate or fluctuating results.
In short:
- Default speed: ~10,000 samples/sec (accurate)
- Maximum safe speed: ~15,000 samples/sec (slightly less accurate)
If you need faster and more stable analog readings, you can also use techniques like averaging multiple samples or filtering the input signal in your code to improve measurement quality even at higher ADC speeds.
Arduino Analog Input Pins
The analog input pins on an Arduino are special pins that allow the board to read varying voltage signals from the outside world. These pins are internally connected to the Analog-to-Digital Converter (ADC), which converts the analog voltage into a digital number that your Arduino can use in calculations, displays, or control systems.
List of Analog Pins on Different Boards
Different Arduino boards have different numbers of analog input pins and reference voltages. Here’s a quick overview:
- Arduino UNO – 6 analog pins (A0 to A5), 10-bit ADC, 5V reference.
- Arduino Nano – 8 analog pins (A0 to A7), 10-bit ADC, 5V reference.
- Arduino Mega – 16 analog pins (A0 to A15), 10-bit ADC, 5V reference.
- Arduino Leonardo – 12 analog pins (A0 to A11), 10-bit ADC, 5V reference.
- Arduino Due – 12 analog pins (A0 to A11), 12-bit ADC, 3.3V reference.
- Arduino MKR Series – 7 analog pins (A0 to A6), 12-bit ADC, 3.3V reference.
Although the pin count and resolution may vary, all analog pins work similarly and are read using the analogRead()
function.
Connecting Sensors to Analog Pins
You can connect any device that outputs a varying voltage signal to an analog pin. Common examples include:
- Potentiometers – for adjustable voltage inputs.
- Light sensors (LDRs) – to measure light intensity.
- Temperature sensors – to read temperature as an analog voltage.
- Sound sensors or microphones – to detect sound levels.
- Flex, pressure, or gas sensors – to measure force, pressure, or gas concentration.
To connect a sensor:
- Connect the sensor’s VCC pin to the Arduino’s 5V or 3.3V supply (depending on your board).
- Connect the sensor’s GND pin to Arduino GND.
- Connect the sensor’s output pin to one of the analog input pins (A0–A5, etc.).
Once connected, use the analogRead()
function to get a digital value that represents the input voltage.
Voltage Range and Pin Behavior
Each analog pin can measure voltages between 0V and the board’s reference voltage (VREF). The typical ranges are:
- 0V to 5V for 5V boards (UNO, Mega, Nano).
- 0V to 3.3V for 3.3V boards (Due, MKR series).
When you read an analog input using analogRead()
, the result is a number proportional to the voltage level:
- 0V → ADC value 0
- Half of VREF → ADC value around 512
- VREF → ADC value 1023 (for 10-bit ADC)
Note: Applying a voltage higher than VREF (for example, more than 5V on a UNO) can damage the ADC or the entire microcontroller. Always make sure your sensor’s output stays within the board’s safe input range.
By understanding how analog pins work, you can easily interface sensors, control systems, and analog devices to bring real-world data into your Arduino projects.
Arduino analogRead() Function
The analogRead()
function is used in Arduino to read the voltage from an analog input pin and convert it into a digital value using the board’s Analog-to-Digital Converter (ADC). It’s one of the most commonly used functions in Arduino programming when working with sensors and variable inputs such as potentiometers, LDRs, or temperature sensors.
When you call analogRead()
, the Arduino measures the voltage on the specified analog pin (e.g., A0) and returns a number between 0 and 1023 for 10-bit boards (like the UNO). This number represents the proportion of the input voltage to the reference voltage (VREF).
analogRead() Syntax
analogRead(pin);
This simple one-line command reads the voltage applied to the selected analog pin.
analogRead() Parameters Explained
The analogRead() function takes a single parameter — the analog pin you want to read. Each Arduino board supports different analog pin configurations:
- Arduino UNO, Nano – A0 to A5
- Arduino Mega – A0 to A15
- Arduino Due, MKR Series – A0 to A11 (depending on model)
Example:
int sensorValue = analogRead(A0);
In this example, the voltage from pin A0 is read and stored in the variable sensorValue
.
analogRead() Return Values and Data Type
The analogRead()
function returns an integer (int) value that represents the digital equivalent of the input voltage.
- For 10-bit ADC (UNO, Mega, Nano): returns values from 0 to 1023.
- For 12-bit ADC (Due, MKR boards): returns values from 0 to 4095.
The returned value can be converted back to voltage using the following formula:
Voltage = (analogRead value × VREF) / ADC steps
Example (Arduino UNO, VREF = 5V):
float voltage = (sensorValue * 5.0) / 1023.0;
This allows you to get the actual voltage level measured at the analog pin.
analogRead() Speed and Performance
The speed of the analogRead()
function depends on the ADC’s clock and conversion settings. On the Arduino UNO (ATmega328P), a single analogRead()
call takes approximately 100 microseconds, allowing around 10,000 readings per second.
This speed is determined by the default ADC clock frequency of 125 kHz (derived from a 16 MHz system clock divided by a prescaler of 128).
If your project requires faster readings (for example, reading an analog sensor multiple times per loop), you can increase the ADC speed by changing the prescaler value in the registers. However, note that increasing speed slightly reduces accuracy due to less sampling time.
Typical speed trade-offs:
- Default speed (prescaler 128): ~10,000 samples/second (accurate)
- Higher speed (prescaler 64): ~20,000 samples/second (less precise)
- Maximum safe speed (prescaler 32): ~40,000 samples/second (reduced accuracy)
For most Arduino applications, the default sampling rate provides the best balance between speed and accuracy.
Practical Arduino ADC Examples
Now that you understand how the Arduino ADC and analogRead()
function work, let’s look at some practical examples. These projects demonstrate how to use analog inputs to control outputs and read sensor data in real-world applications.
Reading Sensor Data using analogRead()
Analog sensors such as LDRs, temperature sensors, or gas sensors output voltages that can be read with analogRead()
. You can convert the ADC value back to the actual voltage or sensor units for further processing:
int sensorValue = analogRead(A0); // Read sensor
float voltage = (sensorValue * 5.0) / 1023.0; // Convert to volts
Serial.println(voltage); // Print voltage
Below is the full code to read the data from the Potentiometer, convert the read data to voltage and print the voltage on the console.
int sensorPin = A0; // Analog pin connected to sensor output
int sensorValue = 0; // Variable to store raw ADC value
float voltage = 0.0; // Variable to store converted voltage
void setup() {
Serial.begin(9600); // Initialize Serial Monitor at 9600 baud
Serial.println("Arduino ADC Sensor Reading Example");
}
void loop() {
// Read the analog input (0 to 1023 for 10-bit ADC)
sensorValue = analogRead(sensorPin);
// Convert the ADC value to voltage
voltage = (sensorValue * 5.0) / 1023.0;
// Print both raw value and voltage
Serial.print("Raw ADC Value: ");
Serial.print(sensorValue);
Serial.print(" Voltage: ");
Serial.print(voltage);
Serial.println(" V");
delay(100); // Wait 500ms before next reading
}
Explanation:
- sensorPin – The analog input pin (A0) connected to your sensor.
- analogRead() – Reads the sensor voltage and returns a value from 0–1023 (10-bit ADC).
- Voltage conversion – The raw ADC value is scaled to the reference voltage (usually 5V).
- Serial Monitor – Displays the readings in real time.
Connect your sensor’s output pin to A0, power it from 5V and GND, and open the Serial Monitor (Ctrl + Shift + M) to see the changing voltage values as the sensor responds to light, temperature, or other physical changes.
The image below shows how the Potentiometer is connected to Analog pin A0 of the Arduino Uno.
The gif below shows the output of the above code. The ADC data read from the potentiometer is converted to voltage. It is then logged back to the serial console.
LED Brightness Control using analogRead() and analogWrite()
You can use a potentiometer and analogRead()
to control the brightness of an LED. The analog input from the potentiometer is read and then mapped to the PWM output using analogWrite()
:
int potValue = analogRead(A0); // Read potentiometer
int ledValue = map(potValue, 0, 1023, 0, 255); // Map to PWM range
analogWrite(LED_PIN, ledValue); // Set LED brightness
This allows smooth dimming of the LED depending on the potentiometer position.
Below is the full code to read the data from the Potentiometer, convert the read data to voltage and control the LED brightness based on the potentiometer value.
int potPin = A0; // Potentiometer connected to analog pin A0
int ledPin = 9; // LED connected to digital pin 9 (PWM-capable)
int potValue = 0; // Variable to store potentiometer reading
int ledValue = 0; // Variable to store mapped PWM value
void setup() {
pinMode(ledPin, OUTPUT); // Set LED pin as output
Serial.begin(9600); // Start Serial Monitor for debugging
Serial.println("LED Brightness Control using Potentiometer");
}
void loop() {
// Step 1: Read potentiometer value (0–1023)
potValue = analogRead(potPin);
// Step 2: Map potentiometer range (0–1023) to PWM range (0–255)
ledValue = map(potValue, 0, 1023, 0, 255);
// Step 3: Write the mapped value to the LED pin
analogWrite(ledPin, ledValue);
// Step 4: Print readings for reference
Serial.print("Potentiometer: ");
Serial.print(potValue);
Serial.print(" LED Brightness (PWM): ");
Serial.println(ledValue);
delay(100); // Small delay for stable readings
}
How It Works:
- The potentiometer acts as a variable voltage divider, producing an analog voltage between 0V and 5V.
analogRead()
reads this voltage and returns a value between 0 and 1023.map()
converts this range to 0–255, matching the PWM range used byanalogWrite()
.analogWrite()
adjusts the LED brightness by varying the PWM duty cycle.
As you turn the potentiometer knob, the LED smoothly brightens or dims. Make sure your LED is connected through a 220Ω resistor to protect it from excessive current.
The image below shows how to potentiometer and LED are connected to Arduino Uno.
The potentiometer is connected to the analog pin A0, whereas the LED is connected to the digital pin D9.
The gif below shows the output of the above code. The ADC data read from the potentiometer is converted to voltage. It is then fed to the LED, whose brightness varies according to the voltage.

This example demonstrates how analogRead() and analogWrite() work together to convert analog input into a controllable digital output, forming the basis for many analog control projects in Arduino.
These examples show how versatile analogRead()
is for interacting with the physical world, from lighting control to motor speed adjustment and sensor monitoring.
Tips for Accurate ADC Readings
Getting reliable analog readings from your Arduino requires attention to detail. Noise, fluctuating voltages, and improper reference settings can cause inaccurate measurements. Here are some tips to improve the accuracy of your ADC readings.
Avoiding Noise and Fluctuations
Electrical noise from motors, relays, or nearby electronics can affect ADC readings. To reduce noise:
- Keep analog signal wires short and away from high-current wires.
- Use decoupling capacitors (0.1 µF) near the sensor or analog input pin.
- Use shielded cables for sensitive sensors when possible.
Using Proper Voltage References
The reference voltage (VREF) defines the maximum measurable input voltage. Using a stable and appropriate reference voltage improves accuracy:
- Use DEFAULT reference for general purposes (5V or 3.3V).
- Use INTERNAL or EXTERNAL reference for more precise or low-voltage measurements.
- Avoid fluctuating supply voltages as they directly affect the ADC output.
Averaging Multiple Readings
Small fluctuations or noise can be smoothed out by taking multiple readings and calculating the average. For example:
long sum = 0;
for(int i = 0; i < 10; i++){
sum += analogRead(A0);
}
int averageValue = sum / 10;
Averaging helps stabilize the readings, making your sensor data more consistent and accurate.
By combining these techniques, you can significantly improve the reliability of your Arduino ADC measurements for any project.
Conclusion
The Arduino ADC and the analogRead()
function are powerful tools that allow your Arduino to read real-world analog signals and convert them into digital values for processing. Understanding how the ADC works, its resolution, reference voltage, and sampling speed is essential for accurate and reliable measurements.
- The Arduino UNO uses a 10-bit ADC, giving values from 0 to 1023 for a 0–5V input range.
- Choosing the right reference voltage (VREF) improves precision, especially for low-voltage sensors.
- ADC speed and sampling rate affect how quickly you can read data; faster readings may reduce accuracy.
- Analog pins (A0–A5 on UNO) can read voltage from sensors like potentiometers, LDRs, and temperature sensors.
- Use techniques like noise reduction and averaging multiple readings to get stable and accurate values.
- Practical applications include LED dimming, motor speed control, and sensor monitoring.
By following these guidelines and understanding the concepts of ADC and analogRead()
, you can confidently read and use analog inputs in all your Arduino projects.
Browse More Arduino Tutorials
Arduino ADC Project Download
Info
You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.
Arduino ADC FAQs
Small fluctuations are normal due to electrical noise, loose connections, or inconsistent power supply. You can minimize this by adding a capacitor (e.g., 0.1 µF) near the analog input, averaging multiple readings in code, or using the internal reference voltage for better stability.
Most classic Arduino boards (UNO, Nano, Mega) have a 10-bit ADC. However, some newer boards like the Arduino Due, Nano 33, or Portenta support 12-bit ADC resolution, which gives finer measurement steps.
You can’t connect voltages above the board’s reference voltage directly. Use a voltage divider circuit with resistors to scale down the voltage within 0–5V (or 0–3.3V) range before connecting it to the analog pin.
analogRead()
always returns values based on the default ADC resolution (typically 10-bit). On boards that support variable resolutions, you can use analogReadResolution(bits)
to change the ADC bit depth (e.g., 8, 10, or 12 bits).
Use a stable reference voltage, shielded cables for long connections, and read the sensor multiple times before averaging. Additionally, isolating analog and digital grounds can help in high-precision applications.
Search This Site
Subscribe
