Arduino pinMode(): OUTPUT, INPUT and INPUT_PULLUP
Or see every lesson.
- 455parts on the bench
- 43boards running now
- 1.00xreal time, on every board
pinMode(pin, mode) tells a pin which way it works. OUTPUT lets digitalWrite() drive it to 5 V or 0 V, for an LED or a buzzer. INPUT makes it listen, for a sensor that drives its own signal. INPUT_PULLUP listens too, with a resistor inside the chip holding the pin at 5 V, so a button from the pin to GND needs nothing else. Call it once for each pin, in setup().
The circuit above is an Uno with a button on pin 2 and an LED on pin 13. Press Run and hold the button: the LED lights while you hold it. The whole sketch is two pinMode() calls, pinMode(2, INPUT_PULLUP) and pinMode(13, OUTPUT), and a loop that copies one pin to the other.
Below is what each mode does, what goes wrong when pinMode is missing, how big the pull-up inside the chip is, and the mistakes people make with it, each run on an Uno with what it measured.
Want the step-by-step version? The lesson "Reading a pin, and the pull-up" walks through this with checkpoints.
Open the lessonThe three modes
OUTPUT connects the pin to the chip’s driver. digitalWrite(pin, HIGH) puts it at 5 V and LOW at 0 V, strongly enough to light an LED through a resistor. Use it for anything the board switches: LEDs, buzzers, relays, a transistor’s base.
INPUT is how every pin starts after a reset. The pin draws almost no current and just reports whether the voltage on it is high or low. Use it when the other side drives the pin, as a sensor module’s output or another board’s TX does.
INPUT_PULLUP is INPUT with a resistor from the pin up to 5 V switched on inside the chip. The pin reads HIGH until something pulls it to GND. Wire a button from the pin to GND and it reads LOW while pressed and HIGH while not, with no resistor on the breadboard at all.
Forget pinMode and the LED is dim
This is the blink sketch with pinMode left out. It builds, it runs, and the LED looks dead. In the simulator the LED reached half a percent of its brightness, where the same sketch with pinMode(LED, OUTPUT) reached 64 percent.
Here is why. On an input pin, digitalWrite(pin, HIGH) does not drive the pin. It switches on the pull-up. So the LED is lit through a 35k resistor instead of the pin’s driver. We read the pin’s voltage with A0: it was 1314 mV without pinMode and 4481 mV as an OUTPUT. If an LED glows faintly, check pinMode first.
const int LED = 13;
void setup() {
// pinMode(LED, OUTPUT); <- forgotten
}
void loop() {
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
delay(500);
}A pin left as INPUT with nothing on it
An input with nothing wired to it is floating, and it reads whatever noise it picks up. This sketch reads pin 7 twenty times as INPUT, then twenty times as INPUT_PULLUP. It printed "10000001110111110110 INPUT" and then "11111111111111111111 INPUT_PULLUP".
That is the case for INPUT_PULLUP with a button. As a plain INPUT, a button from the pin to GND only pulls the pin down while pressed; let go and it floats again. The digitalRead page has the same noise on the button bench.
void setup() {
Serial.begin(9600);
pinMode(7, INPUT); // nothing is wired to pin 7
for (int i = 0; i < 20; i++) {
Serial.print(digitalRead(7));
delay(50);
}
Serial.println(" INPUT");
pinMode(7, INPUT_PULLUP);
for (int i = 0; i < 20; i++) {
Serial.print(digitalRead(7));
delay(50);
}
Serial.println(" INPUT_PULLUP");
}
void loop() {
}How big is the pull-up?
The ATmega328P’s datasheet says the pull-up is between 20k and 50k. You can measure yours: put a known resistor from the pin to GND and read the voltage with A0. With a 10k it printed "1109 mV, so the pull-up is about 35085 ohms", and "pin 2 reads LOW".
That second line matters. The pull-up is weak, so a 10k to GND wins and the pin reads LOW. With a 47k to GND instead, the pin sat at 2864 mV and read HIGH. Anything that loads a pulled-up pin, a long cable, a sensor, a resistor, can change what it reads.
void setup() {
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
delay(10);
// A 10k from pin 2 to GND, and pin 2 wired to A0 to read its voltage.
long mv = analogRead(A0) * 5000L / 1023;
long pullup = 10000L * (5000 - mv) / mv;
Serial.print(mv);
Serial.print(" mV, so the pull-up is about ");
Serial.print(pullup);
Serial.println(" ohms");
Serial.println(digitalRead(2) == HIGH ? "pin 2 reads HIGH" : "pin 2 reads LOW");
}
void loop() {
}Analog pins work as digital pins
A0 to A5 on an Uno are ordinary digital pins as well. pinMode(A0, OUTPUT) and digitalWrite(A0, HIGH) light an LED on A0 the same way they do on pin 13; ours lit to 66 percent of full brightness. A0 is just a name for pin 14, and the sketch below printed "A0 is pin 14".
That helps when you run out of digital pins. The other way around does not work: pins 0 to 13 have no ADC behind them, so analogRead() only works on A0 to A5.
void setup() {
Serial.begin(9600);
pinMode(A0, OUTPUT);
digitalWrite(A0, HIGH);
Serial.print("A0 is pin ");
Serial.println(A0);
}
void loop() {
}Common mistakes
Forgetting pinMode(pin, OUTPUT). The LED glows faintly or not at all, as above.
A button from the pin to 5 V with INPUT_PULLUP. The pin is already at 5 V, so pressing changes nothing: ours printed 1 before, during and after the press. With INPUT_PULLUP, the button goes from the pin to GND, and pressed reads LOW.
Writing INPUT_PULLDOWN on an Uno. The ATmega328P has no pull-down, so the build stops. Clang says: use of undeclared identifier 'INPUT_PULLDOWN'. An ESP32 has one; on an Uno, use INPUT and a 10k from the pin to GND.
Calling pinMode on pin 0 or 1. They are the USB serial line. Leave them alone if you use the serial monitor.
Expecting a reading on a pin with nothing on it. A floating INPUT reads noise. Use INPUT_PULLUP or a resistor.
Questions
Do I need pinMode for INPUT?
Not strictly, since every pin starts as INPUT after a reset, but write it anyway so the sketch says what each pin is for. You do need pinMode for OUTPUT and for INPUT_PULLUP.
What does INPUT_PULLUP do?
It switches on a resistor of about 35k inside the chip, from the pin to 5 V. The pin reads HIGH until something pulls it to GND, so a button from the pin to GND reads LOW while pressed.
Why is my LED dim on Arduino?
Most often pinMode(pin, OUTPUT) is missing, so digitalWrite(pin, HIGH) only switches on the weak pull-up. Here that gave the LED half a percent of its brightness. Also check the resistor value.
Can I use analog pins as digital pins?
Yes. On an Uno, A0 to A5 are pins 14 to 19 and work with pinMode, digitalWrite and digitalRead like any other pin.
Does the Arduino Uno have INPUT_PULLDOWN?
No. The ATmega328P only has pull-ups, so INPUT_PULLDOWN does not build. Use INPUT with an external 10k from the pin to GND, or INPUT_PULLUP and wire the button to GND.
Do I need pinMode before analogWrite()?
No. analogWrite() makes the pin an output itself. Here `analogWrite(9, 128)` with no pinMode lit an LED on pin 9 exactly as brightly as the same line after `pinMode(9, OUTPUT)`. Calling pinMode first does no harm and makes the sketch easier to read.
Keep going
Where the facts on this page come from
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.