At the heart of nearly every Arduino project are three core functions:
digitalWrite()digitalRead()analogRead()
Arduino interacts with the real world by turning pins on and off, reading button states, and measuring sensor values. Even though they seem simple, it’s important to know what they really do behind the scenes in order to write Arduino code that works correctly, quickly, and as expected.
This tutorial explains:
- What each function does internally
- How Arduino pins work electrically
- Common mistakes and misconceptions
- Many practical code examples
- Performance and accuracy considerations
Arduino Pins: Digital vs Analog (Clarification)
Before diving into the functions, it’s important to understand Arduino pin types.
Digital Pins
- Can read HIGH or LOW
- Voltage-based logic
- Typically labeled
D0–D13(Uno)
Analog Pins
- Can read variable voltage levels
- Use an Analog-to-Digital Converter (ADC)
- Labeled
A0–A5(Uno) - Can also act as digital pins if needed
digitalWrite(): How Arduino Sets Pin Output
What digitalWrite() Does
digitalWrite() sets a digital output pin to one of two states:
HIGH→ near 5V (or 3.3V on some boards)LOW→ 0V (ground)
This function controls hardware registers inside the microcontroller that physically drive the pin voltage.
Basic digitalWrite() Example
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}
This toggles the voltage on pin 13.
What Happens Internally
- Arduino checks which port the pin belongs to
- It sets or clears the appropriate bit in the output register
- The pin’s output driver sources or sinks current
This abstraction is slower than direct register access, but far safer and more portable.
digitalWrite() with INPUT Pins (Pull-Up Trick)
void setup() {
pinMode(2, INPUT);
digitalWrite(2, HIGH);
}
This enables the internal pull-up resistor.
Equivalent and clearer version:
pinMode(2, INPUT_PULLUP);
digitalWrite() Common Mistakes
Mistake: Forgetting pinMode()
digitalWrite(13, HIGH); // Undefined behavior if not OUTPUT
Mistake: Driving too much current
digitalWrite(13, HIGH); // Pin cannot power motors or relays directly
digitalRead(): How Arduino Reads Digital Inputs
What digitalRead() Does
digitalRead() reads the logic level on a digital pin:
- Returns
HIGHorLOW - Compares pin voltage to internal thresholds
Basic digitalRead() Example
void setup() {
pinMode(2, INPUT);
Serial.begin(9600);
}
void loop() {
int state = digitalRead(2);
Serial.println(state);
}
Button Example with Pull-Up Resistor
void setup() {
pinMode(2, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
if (digitalRead(2) == LOW) {
Serial.println("Button Pressed");
}
}
Why LOW? With pull-ups enabled:
- Button pressed → connects pin to ground
- Button released → pin pulled HIGH internally
Floating Input Problem
pinMode(2, INPUT);
Without pull-up or pull-down resistors, the pin:
- Picks up electrical noise
- Produces random HIGH/LOW readings
Always define input state explicitly.
digitalRead() Timing and Speed
- Typical execution time: ~4–5 microseconds
- Fast enough for most applications
- Not suitable for very high-speed signals
analogRead(): How Arduino Reads Voltages
What analogRead() Does
analogRead() measures a voltage on an analog pin and converts it into a number using the ADC.
On Arduino Uno:
- ADC resolution: 10-bit
- Output range:
0–1023 - Voltage range:
0V–5V(default)
Basic analogRead() Example
void setup() {
Serial.begin(9600);
}
void loop() {
int value = analogRead(A0);
Serial.println(value);
delay(500);
}
Voltage Mapping
| Voltage | analogRead() Value | | – | | | 0V | 0 | | 2.5V | ~512 | | 5V | 1023 |
Converting analogRead to Voltage
int raw = analogRead(A0);
float voltage = raw * (5.0 / 1023.0);
Serial.println(voltage);
analogRead() Timing
- Takes ~100 microseconds per read
- Much slower than digitalRead
- Important in time-sensitive applications
Changing Analog Reference Voltage
void setup() {
analogReference(INTERNAL);
}
This improves resolution for low-voltage sensors.
analogRead vs digitalRead
int analogValue = analogRead(A0);
int digitalValue = digitalRead(A0);
analogRead()→ measures voltagedigitalRead()→ compares to threshold
Analog pins can be used as digital pins, but not vice versa.
Common Mistakes
Mistake 1: analogRead Produces Analog Values
Wrong. It produces digital numbers representing analog voltages.
Mistake 2: analogWrite Is Analog Output
analogWrite() produces PWM, not true analog voltage.
Mistake 3: digitalRead Is Instantaneous
Reads are fast, but not instantaneous. Electrical noise still matters.
Practical Example: Button Controls LED Brightness
int buttonPin = 2;
int potPin = A0;
int ledPin = 9;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
}
void loop() {
if (digitalRead(buttonPin) == LOW) {
int potValue = analogRead(potPin);
int pwmValue = map(potValue, 0, 1023, 0, 255);
analogWrite(ledPin, pwmValue);
}
}
This example combines:
digitalRead()for controlanalogRead()for measurementanalogWrite()for output modulation
Performance Optimization Tips
- Cache pin states when possible
- Avoid repeated analogRead in tight loops
- Use pull-ups to stabilize inputs
- Prefer
INPUT_PULLUPover external resistors when possible
Function Comparison Summary
| Function | Purpose | Speed | Output | | | | | – | | digitalWrite | Set pin state | Fast | HIGH / LOW | | digitalRead | Read pin state | Fast | HIGH / LOW | | analogRead | Measure voltage | Slower | 0–1023 |
Final Thoughts
| Function | Purpose | Speed | Output |
|---|---|---|---|
| digitalWrite | Set pin state | Fast | HIGH / LOW |
| digitalRead | Read pin state | Fast | HIGH / LOW |
| analogRead | Measure voltage | Slower | 0–1023 |
- Avoid unstable behavior
- Read sensors accurately
- Design reliable hardware interfaces
Mastery of these three functions is foundational for all Arduino projects, from blinking LEDs to complex embedded systems.

