Analog Versus Digital Signals
Where a digital pin sees only HIGH or LOW, an analog input can sense a continuous range of voltages between 0V and the reference (5V on an Uno). This lets you read sensors whose output varies smoothly — a potentiometer knob, a light sensor, or a temperature sensor. The Arduino Uno dedicates six pins (A0 through A5) to analog input. Internally, an analog-to-digital converter, or ADC, samples that voltage and turns it into a number your program can work with, bridging the smooth physical world and the discrete digital one.
Cricket analogy: Analog versus digital is like a run rate that climbs smoothly over an innings versus a wicket that is a single binary event; the potentiometer is the gradually rising run rate the ADC must capture.
Reading Voltages with analogRead()
analogRead() returns an integer from 0 to 1023 because the Uno's ADC has 10-bit resolution (2^10 = 1024 possible levels). A reading of 0 corresponds to 0V, 1023 corresponds to the reference voltage (5V by default), and each step represents about 4.9 millivolts. You can convert a raw reading back to volts by multiplying by 5.0 and dividing by 1023. The ADC takes about 100 microseconds per conversion, so you can sample roughly 10,000 times per second. Note that only the analog-capable A-pins support analogRead().
Cricket analogy: The 10-bit ADC is like a scoreboard that can only show whole runs from 0 to 1023 — it quantizes a smoothly rising total into discrete integers, just as the ADC rounds a voltage to one of 1024 steps.
The pins labeled with a tilde (~) on the board, such as ~3, ~5, ~6, ~9, ~10, and ~11 on the Uno, are the PWM-capable outputs. The A0-A5 pins are analog INPUTS. Do not confuse analog input pins with PWM output pins — they are different sets of pins with different jobs.
Faking Analog Output with PWM
Arduino cannot output a true varying voltage on most pins, so analogWrite() uses pulse-width modulation instead. PWM rapidly switches the pin fully HIGH and fully LOW; by varying the fraction of time it stays HIGH — the duty cycle — the average voltage changes. analogWrite() takes a value from 0 (always off, 0% duty) to 255 (always on, 100% duty), giving 8-bit control. On the Uno most PWM pins run near 490Hz, while pins 5 and 6 run near 980Hz. This is perfect for dimming LEDs and setting motor speed, because the switching is far too fast for the eye or a motor to notice.
Cricket analogy: Duty cycle is like a strike rate: a batsman scoring off 50% of balls averages a steady run flow even though each ball is boundary-or-dot. PWM's rapid on/off likewise averages out to a middle brightness.
Scaling Values with map()
Because analogRead() gives 0-1023 but analogWrite() wants 0-255, you frequently need to rescale. The map() function does linear scaling: map(value, fromLow, fromHigh, toLow, toHigh). For example, map(sensorValue, 0, 1023, 0, 255) turns a potentiometer reading into a PWM brightness level. map() uses integer math and does not constrain its output, so feeding it a value outside the input range yields a proportionally out-of-range result — pair it with constrain() when you need to clamp. It is a convenience helper, not a hardware feature, so it works on any integers.
Cricket analogy: map() is like converting a required run rate onto a projected final score using a linear rule; you rescale one range onto another, just as map turns a 0-1023 reading into a 0-255 brightness.
const int potPin = A0; // potentiometer on an analog input
const int ledPin = 9; // LED on a PWM (~) pin
void setup() {
pinMode(ledPin, OUTPUT);
// Analog input pins do not need pinMode() for analogRead().
}
void loop() {
int sensorValue = analogRead(potPin); // 0..1023
int brightness = map(sensorValue, 0, 1023, 0, 255); // scale to 0..255
brightness = constrain(brightness, 0, 255); // clamp for safety
analogWrite(ledPin, brightness); // PWM the LED
}analogWrite() only works on PWM-capable pins (marked with ~). Calling it on a non-PWM pin will simply set the pin fully HIGH for values 128 and above and fully LOW below that, giving on/off behavior instead of smooth dimming. Also remember analogWrite() takes 0-255, not 0-1023.
- analogRead() digitizes 0V-5V into 0-1023 using the Uno's 10-bit ADC.
- Analog input pins are A0-A5; each ADC step is about 4.9mV.
- analogWrite() does not output true analog voltage — it uses PWM.
- PWM varies the duty cycle (0-255) to change the average voltage at ~490Hz (or ~980Hz on pins 5 and 6).
- PWM is ideal for dimming LEDs and controlling motor speed.
- map() linearly rescales values, e.g. 0-1023 into 0-255, but does not clamp its output.
- Use constrain() alongside map() to keep values within a safe range.
Practice what you learned
1. What range of values does analogRead() return on an Arduino Uno?
2. How does analogWrite() produce an intermediate 'analog' level?
3. What value range does analogWrite() accept?
4. What does map(sensorValue, 0, 1023, 0, 255) do?
5. Which pins on an Arduino Uno can perform analogWrite() (PWM)?
Was this page helpful?
You May Also Like
Digital Input and Output
Learn how Arduino pins read and drive binary HIGH/LOW signals using pinMode(), digitalWrite(), and digitalRead(), including the role of pull-up and pull-down resistors.
Reading Common Sensors
Learn how to interface Arduino with common sensors — potentiometers, light-dependent resistors, temperature sensors, PIR motion detectors, and ultrasonic rangefinders — using voltage dividers, libraries, and pulse timing.
Controlling Motors and Servos
Drive DC motors, servos, and stepper motors from an Arduino using transistors, H-bridge drivers, and the Servo library, and understand why motors must not be powered directly from a pin.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics