Overview
A potentiometer (often called a "pot") is a simple yet powerful analog input device. It's essentially a variable resistor that you can adjust by turning a knob, allowing you to control voltage levels in your circuits.
In this lesson, you'll learn how to read the potentiometer's position using the ATmega328P's ADC (Analog-to-Digital Converter) and create interactive projects that respond to your input.
Potentiometers are used in:
- Volume controls on audio equipment
- Brightness controls on displays
- Throttle controls in robotics
- Adjustable power supplies
- Game controller joysticks
- Industrial process controls
Prerequisites
Before starting, make sure you have completed:
Completed Lessons
- Lesson 1: Blinking LED
- Lesson 2: Push Button Input
- Lesson 3: Buzzer Sound Generation
- Understanding of Serial Monitor
Hardware Requirements
- Vumbua Synapse Kit with potentiometer
- USB Type-C cable
- Computer with Arduino IDE
The potentiometer is pre-connected to the Vumbua board on Analog Pin A0. You can simply rotate the knob to adjust its value - no additional wiring needed!
Learning Objectives
By the end of this lesson, you will be able to:
- Understand how potentiometers work as variable resistors
- Read analog values using
analogRead() - Use the
map()function to convert values - Control LED brightness with PWM
- Create interactive dials and sliders
- Understand the ADC in ATmega328P
- Display analog values on Serial Monitor
- Build practical applications with analog input
What is a Potentiometer?
The Variable Resistor
A potentiometer has three terminals and acts as a variable voltage divider:
- Terminal 1: Connected to ground (0V)
- Terminal 2: The wiper (variable output)
- Terminal 3: Connected to voltage source (5V)
As you turn the knob, the wiper moves along a resistive track, changing the resistance between the wiper and each end terminal.
Types of Potentiometers
Common types found in electronics:
- Rotary: Knob you turn (like volume control)
- Linear/Slide: Slider you move back and forth
- Trimmer: Small screwdriver-adjustable pot
- Digital: Uses digital signals instead of resistance
Specifications
Potentiometers are specified by:
- Resistance Value: 10kΩ (10,000 ohms) is common
- Taper: Linear (most common) or logarithmic
- Power Rating: How much power they can handle
- Tolerance: How accurate the resistance is
Potentiometer Connections
The potentiometer on Vumbua Synapse Kit has 3 pins:
The potentiometer is wired as a voltage divider:
- 5V applied to one end
- Ground connected to the other end
- Middle pin provides variable voltage (0-5V)
- Arduino reads this voltage on pin A0
Voltage Divider Principle
Understanding how a potentiometer works requires understanding voltage dividers:
Voltage Divider Formula
When two resistors are connected in series, the voltage at their junction is:
As you turn the potentiometer knob, R1 and R2 change (but R1 + R2 always equals total resistance), causing Vout to vary between 0V and 5V.
Potentiometer Positions
| Knob Position | Output Voltage | Arduino Reading |
|---|---|---|
| Fully Counter-Clockwise | 0V | 0 |
| Middle | 2.5V | 512 |
| Fully Clockwise | 5V | 1023 |
Using analogRead() Function
The analogRead() function is key to reading potentiometer values:
Function Syntax
int sensorValue = analogRead(pin);
Where pin is the analog pin number (A0-A5 on Vumbua).
Return Values
analogRead() returns an integer between 0 and 1023:
- 0 = 0V input
- 512 = 2.5V input
- 1023 = 5V input
This is because the ATmega328P has a 10-bit ADC (2¹⁰ = 1024 values).
Resolution
The ADC resolution determines the smallest voltage change it can detect:
This means the Arduino can detect voltage changes as small as 4.9 millivolts!
Basic Potentiometer Reading
Let's start with a simple program to read and display potentiometer values:
potentiometer_basic.ino
/* Vumbua Synapse Kit - Lesson 4: Basic Potentiometer Reading Read analog values from potentiometer on pin A0 Display raw value, voltage, and percentage */ const int potPin = A0; // Potentiometer connected to analog pin A0 void setup() { // Initialize Serial communication Serial.begin(9600); // Note: No pinMode needed for analog input pins Serial.println("Potentiometer Reading Program"); Serial.println("============================="); Serial.println("Turn the potentiometer knob to see values change"); Serial.println(); } void loop() { // Read the potentiometer value (0-1023) int rawValue = analogRead(potPin); // Convert raw value to voltage (0-5V) float voltage = rawValue * (5.0 / 1023.0); // Convert to percentage (0-100%) int percentage = map(rawValue, 0, 1023, 0, 100); // Display results in Serial Monitor Serial.print("Raw Value: "); Serial.print(rawValue); Serial.print(" | Voltage: "); Serial.print(voltage); Serial.print("V | Position: "); Serial.print(percentage); Serial.println("%"); // Wait before next reading (20 readings per second) delay(50); }
Testing the Program
1. Upload the Code
Upload to your Vumbua Synapse Kit. The potentiometer is already connected to pin A0 on the board.
2. Open Serial Monitor
Go to Tools → Serial Monitor or press Ctrl+Shift+M.
Set the baud rate to 9600.
3. Rotate the Potentiometer
Turn the potentiometer knob slowly from one end to the other. Watch the values change:
- Raw Value: Should change from 0 to 1023
- Voltage: Should change from 0.00V to 5.00V
- Percentage: Should change from 0% to 100%
Unlike digital pins, analog pins (A0-A5) don't require pinMode() setup for reading.
They're automatically configured as inputs when you use analogRead().
Using map() Function
The map() function is incredibly useful for converting values from one range to another:
potentiometer_map.ino
/* Vumbua Synapse Kit - Lesson 4: Using map() Function Demonstrate different mapping applications */ const int potPin = A0; void setup() { Serial.begin(9600); Serial.println("map() Function Demonstration"); Serial.println("=========================="); } void loop() { int rawValue = analogRead(potPin); // Example 1: Percentage (0-100%) int percentage = map(rawValue, 0, 1023, 0, 100); // Example 2: Angle (0-270 degrees) int angle = map(rawValue, 0, 1023, 0, 270); // Example 3: PWM Value (0-255 for analogWrite) int pwmValue = map(rawValue, 0, 1023, 0, 255); // Example 4: Temperature simulation (-10°C to 50°C) int temperature = map(rawValue, 0, 1023, -10, 50); // Example 5: Reverse mapping (1023 to 0) int reversed = map(rawValue, 0, 1023, 1023, 0); // Display all mapped values Serial.print("Raw: "); Serial.print(rawValue); Serial.print(" | %: "); Serial.print(percentage); Serial.print(" | Angle: "); Serial.print(angle); Serial.print("° | PWM: "); Serial.print(pwmValue); Serial.print(" | Temp: "); Serial.print(temperature); Serial.print("°C | Rev: "); Serial.print(reversed); Serial.println(); delay(200); }
The map(value, fromLow, fromHigh, toLow, toHigh) function linearly scales a value:
It's perfect for converting analog readings into meaningful values for your projects!
LED Brightness Control
Now let's combine potentiometer reading with LED control to create a brightness dimmer:
led_brightness_control.ino
/* Vumbua Synapse Kit - Lesson 4: LED Brightness Control Control LED brightness using potentiometer Uses PWM (Pulse Width Modulation) on pin 9 */ const int potPin = A0; // Potentiometer on A0 const int ledPin = 9; // LED on pin 9 (PWM capable) void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); Serial.println("LED Brightness Controller"); Serial.println("Turn potentiometer to adjust LED brightness"); } void loop() { // Read potentiometer value (0-1023) int potValue = analogRead(potPin); // Map potentiometer value to PWM range (0-255) int brightness = map(potValue, 0, 1023, 0, 255); // Set LED brightness using analogWrite() analogWrite(ledPin, brightness); // Calculate percentage for display int percentage = map(brightness, 0, 255, 0, 100); // Display status Serial.print("Potentiometer: "); Serial.print(potValue); Serial.print(" | Brightness: "); Serial.print(brightness); Serial.print(" ("); Serial.print(percentage); Serial.println("%)"); // Small delay for readability delay(100); }
Understanding PWM (Pulse Width Modulation)
What is PWM?
PWM rapidly switches a digital signal on and off to simulate an analog output. The percentage of time the signal is HIGH determines the "effective voltage."
PWM Values
analogWrite() accepts values from 0 to 255:
- 0: Always OFF (0% duty cycle)
- 127: Half brightness (~50% duty cycle)
- 255: Always ON (100% duty cycle)
PWM Pins on Vumbua
On the ATmega328P, PWM is available on specific pins marked with ~:
- Pin 3
- Pin 5
- Pin 6
- Pin 9
- Pin 10
- Pin 11
Potentiometer Position
LED Brightness
Advanced Applications
Project 1: Volume Control with Buzzer
Combine potentiometer with buzzer from Lesson 3 to create a volume control:
volume_control.ino
/* Vumbua Synapse Kit - Volume Control System Use potentiometer to control buzzer frequency and volume */ const int potPin = A0; // Potentiometer on A0 const int buzzerPin = 3; // Buzzer on pin 3 const int ledPin = 9; // LED on pin 9 void setup() { Serial.begin(9600); pinMode(buzzerPin, OUTPUT); pinMode(ledPin, OUTPUT); Serial.println("Volume Control System Active"); Serial.println("Turn potentiometer to adjust tone"); } void loop() { int potValue = analogRead(potPin); // Map to frequency range (100Hz to 2000Hz) int frequency = map(potValue, 0, 1023, 100, 2000); // Map to LED brightness (0-255) int brightness = map(potValue, 0, 1023, 0, 255); // Generate tone with current frequency tone(buzzerPin, frequency); // Control LED brightness analogWrite(ledPin, brightness); // Display status Serial.print("Position: "); Serial.print(map(potValue, 0, 1023, 0, 100)); Serial.print("% | Frequency: "); Serial.print(frequency); Serial.println(" Hz"); delay(100); }
Project 2: RGB Color Mixer
Use potentiometer to cycle through colors on an RGB LED (if available):
rgb_color_mixer.ino
/* Vumbua Synapse Kit - RGB Color Mixer Cycle through colors using potentiometer Simulates RGB control using built-in LED */ const int potPin = A0; const int redPin = 9; // Simulated red channel const int greenPin = 10; // Simulated green channel const int bluePin = 11; // Simulated blue channel void setup() { Serial.begin(9600); pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.println("RGB Color Mixer"); Serial.println("Turn potentiometer to cycle through colors"); } void loop() { int potValue = analogRead(potPin); // Create a color cycle based on potentiometer position int red, green, blue; if (potValue < 341) { // Red to Yellow red = 255; green = map(potValue, 0, 340, 0, 255); blue = 0; } else if (potValue < 682) { // Yellow to Green red = map(potValue, 341, 681, 255, 0); green = 255; blue = 0; } else { // Green to Blue red = 0; green = map(potValue, 682, 1023, 255, 0); blue = map(potValue, 682, 1023, 0, 255); } // Set colors analogWrite(redPin, red); analogWrite(greenPin, green); analogWrite(bluePin, blue); // Display color values Serial.print("RGB: ("); Serial.print(red); Serial.print(", "); Serial.print(green); Serial.print(", "); Serial.print(blue); Serial.println(")"); delay(100); }
ATmega328P ADC - How It Works
The ATmega328P's built-in ADC is what makes analog reading possible:
10-bit Resolution
The ADC converts analog voltage (0-5V) to a 10-bit digital number (0-1023). This means it can distinguish 1024 different voltage levels.
Resolution = 5V ÷ 1024 = 0.0049V (4.9mV per step)
Conversion Process
When analogRead() is called:
- ADC connects to the selected pin
- Voltage is compared against internal reference (5V)
- Successive approximation algorithm determines digital value
- Conversion takes about 100 microseconds
- Result is stored and returned
ADC Channels
The ATmega328P has 6 ADC channels (A0-A5) that can be used for analog input:
- A0: Potentiometer on Vumbua
- A1-A5: Available for other sensors
- Each can measure 0-5V with 10-bit precision
By default, the ADC uses the 5V power supply as reference. For more precise measurements, you can use the internal 1.1V reference or an external reference voltage.
To change reference voltage: analogReference(type);
Troubleshooting Common Issues
- Solution: Add a small capacitor (10nF-100nF) between A0 and GND
- Alternative: Use software smoothing (averaging)
- Check: Make sure potentiometer is properly connected to A0
- Try: Different sampling rates with
delay()
- Check: LED is connected to a PWM pin (3, 5, 6, 9, 10, 11)
- Verify: Using
analogWrite()notdigitalWrite() - Test: Try different LED (some LEDs have minimum brightness threshold)
- Consider: Using a transistor for higher power LEDs
- Check: Potentiometer wiring (5V, GND, A0)
- Test: Measure voltage at A0 pin with multimeter
- Verify: Correct pin declaration:
const int potPin = A0; - Try: Different potentiometer or test with known values
Software Smoothing Example
// Smoothing algorithm for stable readings
const int numReadings = 10;
int readings[numReadings];
int readIndex = 0;
int total = 0;
int average = 0;
void setup() {
Serial.begin(9600);
// Initialize all readings to 0
for (int i = 0; i < numReadings; i++) {
readings[i] = 0;
}
}
void loop() {
// Subtract the last reading
total = total - readings[readIndex];
// Read from sensor
readings[readIndex] = analogRead(A0);
// Add the reading to the total
total = total + readings[readIndex];
// Advance to the next position
readIndex = readIndex + 1;
// If at end of array, wrap around
if (readIndex >= numReadings) {
readIndex = 0;
}
// Calculate average
average = total / numReadings;
Serial.println(average);
delay(1);
}
Video Demonstration
Video Tutorial Coming Soon!
We're preparing a detailed video walkthrough for this lesson.
Subscribe to our YouTube channel to be notified when it's available.
Subscribe to OLSPACEWhat's Next?
Congratulations! You've successfully mastered analog input with potentiometers. Here's what you've accomplished:
- ✓ Learned how potentiometers work as voltage dividers
- ✓ Used
analogRead()to read values from A0 - ✓ Mastered the
map()function for value conversion - ✓ Controlled LED brightness with PWM
- ✓ Created interactive projects with analog input
- ✓ Understood the ATmega328P ADC operation
In the next lesson, you'll explore light sensing:
Lesson 5: Light Sensor (BH170)
Learn to measure ambient light intensity using the BH170 light sensor. Create automatic lighting systems, daylight detectors, and light-activated projects that respond to environmental changes.
Resources & Downloads
Download Complete Code
Get all the code files for this lesson: