Arduino Analog I/O
Introduction
While digital signals can only be HIGH (1) or LOW (0), the real world isn't so black and white. Temperature, light levels, sound, and pressure all vary across ranges. This is where analog I/O comes in—allowing your Arduino to interact with these continuous signals.
In this tutorial, you'll learn how to:
- Read analog values from sensors
- Convert analog readings to useful information
- Output analog-like signals using PWM
- Build practical projects using analog I/O
Understanding Analog Input
How Analog Input Works
Arduino boards have a built-in Analog-to-Digital Converter (ADC) that converts varying voltage levels (0-5V) into digital values (0-1023) that the microcontroller can process.
The Arduino UNO has 6 analog input pins (A0-A5), each with 10-bit resolution, meaning they can detect 1,024 different values (2^10 = 1,024).
Reading Analog Values
To read an analog value, we use the analogRead()
function:
int sensorValue = analogRead(A0); // Read the value from analog pin A0
The result will be an integer between 0 (0V) and 1023 (5V).
Example: Reading a Potentiometer
A potentiometer is a variable resistor - perfect for demonstrating analog input.
Components needed:
- Arduino board
- Potentiometer (10kΩ)
- Breadboard
- Jumper wires
Circuit:
5V ---- Potentiometer ---- GND
|
└---- A0
Code:
void setup() {
Serial.begin(9600); // Initialize serial communication
}
void loop() {
int sensorValue = analogRead(A0); // Read the input on analog pin A0
Serial.print("Sensor Value: ");
Serial.println(sensorValue);
delay(100); // Small delay for readability
}
When you run this code, open the Serial Monitor to see the values change as you rotate the potentiometer. The values will range from 0 to 1023.
Converting Analog Values
Often, you'll need to convert the raw 0-1023 value to a more useful range. The map()
function is perfect for this:
int mappedValue = map(sensorValue, 0, 1023, 0, 255);
This converts values from the range 0-1023 to 0-255 (useful for LED brightness, for example).
For more precise conversions, use floating-point math:
float voltage = sensorValue * (5.0 / 1023.0);
Understanding Analog Output (PWM)
Arduino doesn't have true analog output. Instead, it uses Pulse Width Modulation (PWM) to create an analog-like effect.
How PWM Works
PWM rapidly switches a digital pin on and off with a varying duty cycle to simulate analog output.
A 0% duty cycle means the pin is always off (0V). A 100% duty cycle means it's always on (5V). Values in between create the appearance of analog voltage levels.
Writing Analog Values
To output a PWM signal, use the analogWrite()
function:
analogWrite(pin, value); // pin is a PWM pin, value is 0-255
On an Arduino UNO, PWM is available on pins 3, 5, 6, 9, 10, and 11 (marked with ~ on the board).
Example: Controlling LED Brightness
Components needed:
- Arduino board
- LED (any color)
- 220Ω resistor
- Breadboard
- Jumper wires
Circuit:
Arduino pin 9 ---- 220Ω resistor ---- LED ---- GND
Code:
const int ledPin = 9; // LED connected to pin 9 (PWM)
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as output
}
void loop() {
// Fade in
for(int brightness = 0; brightness <= 255; brightness++) {
analogWrite(ledPin, brightness); // Set LED brightness
delay(5); // Small delay to see the effect
}
// Fade out
for(int brightness = 255; brightness >= 0; brightness--) {
analogWrite(ledPin, brightness); // Set LED brightness
delay(5); // Small delay to see the effect
}
}
This code creates a smooth fading effect by gradually increasing and decreasing the PWM duty cycle.
Practical Examples
Example 1: Automatic Night Light
This project uses a photoresistor (light-dependent resistor) to measure ambient light and turn on an LED when it gets dark.
Components needed:
- Arduino board
- Photoresistor
- 10kΩ resistor
- LED (any color)
- 220Ω resistor
- Breadboard
- Jumper wires
Circuit:
5V ---- Photoresistor ---- A0 ---- 10kΩ resistor ---- GND
Arduino pin 9 ---- 220Ω resistor ---- LED ---- GND
Code:
const int photoPin = A0; // Photoresistor connected to A0
const int ledPin = 9; // LED connected to pin 9
const int threshold = 300; // Light threshold value
void setup() {
pinMode(ledPin, OUTPUT); // Set LED pin as output
Serial.begin(9600); // Initialize serial communication
}
void loop() {
int lightLevel = analogRead(photoPin); // Read light level
Serial.print("Light level: ");
Serial.println(lightLevel);
// If it's dark (low light level)
if (lightLevel < threshold) {
// Turn on LED with brightness inversely proportional to light level
int brightness = map(lightLevel, 0, threshold, 255, 0);
analogWrite(ledPin, brightness);
} else {
// Turn off LED if it's bright enough
analogWrite(ledPin, 0);
}
delay(100); // Small delay for stability
}
This code reads the light level and automatically adjusts the LED brightness based on how dark it is.
Example 2: Temperature-Controlled Fan
This project uses a temperature sensor to control a small DC motor's speed.
Components needed:
- Arduino board
- TMP36 temperature sensor
- DC motor
- Transistor (e.g., 2N2222)
- 1kΩ resistor
- Diode (e.g., 1N4001)
- External power for motor (if needed)
- Breadboard
- Jumper wires
Circuit: (Simplified - in a real project, you'd need a transistor to control the motor)
5V ---- TMP36 ---- GND
|
└---- A0
Arduino pin 9 ---- 1kΩ resistor ---- Transistor Base
Transistor Collector ---- Motor ---- Motor Power (+)
Transistor Emitter ---- GND
Motor Power (-) ---- GND
Code:
const int tempPin = A0; // Temperature sensor on A0
const int motorPin = 9; // Motor control on pin 9
const float minTemp = 22; // Minimum temperature in °C
const float maxTemp = 30; // Maximum temperature in °C
void setup() {
pinMode(motorPin, OUTPUT); // Set motor pin as output
Serial.begin(9600); // Initialize serial communication
}
void loop() {
// Read temperature sensor
int sensorValue = analogRead(tempPin);
// Convert ADC reading to voltage
float voltage = sensorValue * (5.0 / 1023.0);
// Convert voltage to temperature in °C (for TMP36)
float temperatureC = (voltage - 0.5) * 100;
Serial.print("Temperature: ");
Serial.print(temperatureC);
Serial.println(" °C");
// Map temperature to motor speed
int motorSpeed = 0;
if (temperatureC > minTemp) {
motorSpeed = map(constrain(temperatureC, minTemp, maxTemp) * 10, minTemp * 10, maxTemp * 10, 0, 255);
}
analogWrite(motorPin, motorSpeed); // Control motor speed
Serial.print("Motor speed: ");
Serial.println(motorSpeed);
delay(1000); // Read once per second
}
This code reads the temperature, converts it to degrees Celsius, and then adjusts the motor speed accordingly.
Common Analog Sensors
Arduino can interface with many analog sensors:
- Potentiometers: Variable resistors that can be used as controls
- Photoresistors (LDRs): Change resistance based on light levels
- Thermistors: Change resistance based on temperature
- Force-Sensitive Resistors (FSRs): Detect physical pressure
- Flex Sensors: Detect bending
- Microphones: Detect sound levels
- Accelerometers: Measure acceleration forces
- Gas Sensors: Detect specific gases (CO, CO2, methane, etc.)
- Moisture Sensors: Measure soil moisture levels
Most of these sensors follow the same pattern: connect to an analog pin, read the value, and convert it to a meaningful measurement.
Tips and Best Practices
-
Add capacitors for stability: A 0.1μF capacitor between the analog pin and ground can reduce noise.
-
Take multiple readings: For more reliable results, take several readings and average them:
int getStableReading(int pin, int samples = 10) {
int total = 0;
for (int i = 0; i < samples; i++) {
total += analogRead(pin);
delay(2);
}
return total / samples;
}
-
Be aware of PWM frequency: The default PWM frequency on most Arduino pins is about 490Hz, which might cause audible noise or visible flickering in some applications.
-
Remember the resolution limits:
- Analog input: 0-1023 (10-bit)
- Analog output (PWM): 0-255 (8-bit)
-
Use external references when precision matters: For more accurate readings, use the
analogReference()
function to set an external voltage reference.
Summary
In this tutorial, you've learned:
- How Arduino reads analog signals using the ADC
- How to convert analog readings to useful values
- How to generate analog-like output using PWM
- How to build practical projects using analog I/O
Analog I/O opens up a world of possibilities for your Arduino projects, allowing you to interact with the continuous nature of the physical world.
Exercises
-
Light Meter: Build a device that displays different light levels using multiple LEDs.
-
Temperature Logger: Create a system that records temperature readings and sends them to your computer.
-
Music Visualizer: Use a microphone module to create a light display that reacts to music.
-
Plant Monitor: Combine a moisture sensor, light sensor, and temperature sensor to monitor plant health.
-
Electronic Throttle: Use a potentiometer to control the speed of a small vehicle or robot.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)