100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

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.

I/O & SensorsBeginner9 min readJul 10, 2026
Analogies

What Digital I/O Means

A digital pin on an Arduino has exactly two states: HIGH and LOW. On a 5V board like the Uno, HIGH means the pin is driven to roughly 5 volts and LOW means it is pulled to 0 volts (ground); on a 3.3V board like the Nano 33, HIGH is about 3.3 volts. There is no in-between value in the digital world — a reading is either a logic 1 or a logic 0. This binary model is what makes buttons, LEDs, relays, and simple switches straightforward to control.

🏏

Cricket analogy: It is like an umpire's out or not-out decision after a DRS review — the verdict is one of exactly two states with no halfway ruling, just as a digital pin is only ever HIGH or LOW.

Configuring Pins with pinMode()

Before you use a pin you must tell the microcontroller which direction it operates in by calling pinMode() inside setup(). Passing OUTPUT lets the pin source or sink current to drive an LED or transistor, while INPUT configures it to sense an external voltage. A third option, INPUT_PULLUP, enables the chip's internal pull-up resistor so a floating input settles to a known HIGH when nothing is connected. Choosing the wrong mode is a common beginner bug: an output pin cannot reliably read a button, and an input pin cannot light an LED.

🏏

Cricket analogy: Setting pinMode is like a captain deciding whether a player will bat or bowl this innings — you commit the role first, just as you declare a pin as INPUT or OUTPUT before it does any work.

cpp
const int ledPin = 13;
const int buttonPin = 2;

void setup() {
  pinMode(ledPin, OUTPUT);          // drive an LED
  pinMode(buttonPin, INPUT_PULLUP); // read a button, no external resistor needed
}

void loop() {
  // With INPUT_PULLUP, an unpressed button reads HIGH and a
  // pressed button (wired to GND) reads LOW.
  if (digitalRead(buttonPin) == LOW) {
    digitalWrite(ledPin, HIGH);     // button pressed -> LED on
  } else {
    digitalWrite(ledPin, LOW);      // button released -> LED off
  }
}

digitalWrite() only makes sense on a pin configured as OUTPUT, and digitalRead() only makes sense on a pin configured as INPUT or INPUT_PULLUP. The built-in LED on most Arduino boards is wired to pin 13, which is why tutorials use it for the classic Blink sketch.

Reading Digital Inputs

digitalRead() returns HIGH or LOW based on the voltage present at an input pin. The critical rule is that a bare input pin is high-impedance and 'floating' — if nothing drives it, electrical noise can make it read HIGH and LOW at random. That is why every switch or button needs a defined resting state provided by a resistor. Without one, your button will appear to trigger by itself. Mechanical switches also 'bounce', producing several rapid transitions per press, which often requires software debouncing to read cleanly.

🏏

Cricket analogy: A floating input is like a batsman with no clear guard mark — without a defined stance the reading drifts randomly, the way a scorer's eye wanders. The pull resistor is the crease line that fixes the resting position.

Never leave an input pin floating. Always give it a defined level with an external pull-up/pull-down resistor (typically 10 kilohm) or by enabling INPUT_PULLUP. A floating pin will read unpredictable, noise-driven values that make your button or switch appear to fire on its own.

Pull-up and Pull-down Resistors

A pull-up resistor connects the input to VCC so the pin idles HIGH, and a button wired to ground pulls it LOW when pressed — this is the most common Arduino pattern and it inverts your logic (pressed equals LOW). A pull-down resistor connects the input to ground so the pin idles LOW and reads HIGH when the button connects it to VCC. The internal pull-up enabled by INPUT_PULLUP is roughly 20-50 kilohm and saves you an external component, but Arduino has no internal pull-down, so pull-down configurations require an external resistor.

🏏

Cricket analogy: A pull-up idling HIGH is like a fielder returning to a default position between deliveries — the resting state is fixed, and the press momentarily pulls it elsewhere just as a batsman running disturbs the set field.

  • Digital pins have exactly two states: HIGH (near VCC) and LOW (0V / ground).
  • Call pinMode() in setup() to set a pin as OUTPUT, INPUT, or INPUT_PULLUP.
  • digitalWrite() drives an OUTPUT pin; digitalRead() senses an INPUT pin.
  • Never leave an input floating — use a pull-up or pull-down resistor to define its resting level.
  • INPUT_PULLUP enables the chip's internal ~20-50k pull-up; Arduino has no internal pull-down.
  • With a pull-up, a button wired to ground reads LOW when pressed (inverted logic).
  • Mechanical switches bounce, so debounce in software when you need one clean press.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ArduinoProgrammingStudyNotes#DigitalInputAndOutput#Digital#Input#Output#Means#StudyNotes#SkillVeris#ExamPrep