02. 디지털 입출력: 버튼으로 세상과 소통하기

아두이노가 스스로 생각하는 것뿐만 아니라, 사용자의 입력을 감지하는 방법을 배웁니다.

1. 디지털 입력(Digital Input)이란?

1장에서는 아두이노가 전기를 내보내 LED를 켰습니다(출력). 이번에는 아두이노가 외부로부터 전기가 들어오고 있는지 확인하는 '디지털 입력'을 배웁니다.

디지털 신호는 딱 두 가지만 존재합니다.

Arduino Push Button Input Signal (0 or 1)
▲ 디지털 입력: 외부의 버튼 신호를 아두이노가 감지하는 과정

2. 브레드보드(Breadboard) 사용법

전선을 아두이노에 직접 꼬아 붙일 수는 없겠죠? 그래서 우리는 납땜 없이 회로를 구성할 수 있는 브레드보드(빵판)를 사용합니다.

+ (전체 연결) - (전체 연결) 세로로 연결됨
▲ 브레드보드 내부 구조: 양 끝의 전원 라인은 가로로, 안쪽 부품 라인은 세로로 연결되어 있습니다.

3. 중요: 플로팅(Floating) 현상과 저항

버튼을 아두이노에 연결할 때 가장 실수하는 부분이 '저항'을 빼먹는 것입니다. 저항 없이 버튼을 연결하면 아두이노는 버튼을 안 눌렀을 때 0인지 1인지 몰라 갈팡질팡하게 되는데, 이를 플로팅(떠 있는 상태)이라고 합니다.

방식 회로 연결 버튼 안 누를 때 버튼 누를 때
풀다운(Pull-down) 저항을 GND(-)에 연결 LOW (0V) HIGH (5V)
풀업(Pull-up) 저항을 5V(+)에 연결 HIGH (5V) LOW (0V)

💡 가장 쉬운 방법: INPUT_PULLUP

회로에 직접 저항을 달기 복잡하다면 아두이노 내부의 저항을 쓸 수 있습니다. 코드에서 pinMode(핀번호, INPUT_PULLUP)이라고 적으면 별도의 저항 부품 없이도 깔끔하게 작동합니다!

4. 💡 실습: 버튼으로 LED 제어하기

2번 핀에 버튼을, 13번 핀에 LED(내장)를 사용하여 버튼을 누르는 동안만 불이 켜지는 코드를 작성해 봅시다.

void setup() {
    pinMode(13, OUTPUT);       // LED를 출력으로 설정
    // 내부 풀업 저항 사용 (버튼을 안 누르면 1, 누르면 0이 들어옴)
    pinMode(2, INPUT_PULLUP);  
}

void loop() {
    // 2번 핀의 상태(0 또는 1)를 읽어서 변수에 저장
    int btnPush = digitalRead(2); 

    if (btnPush == LOW) {      // 누르면 0(LOW)이 들어오는 풀업 방식
        digitalWrite(13, HIGH); // LED 켜기
    } else {
        digitalWrite(13, LOW);  // LED 끄기
    }
}

5. 🎯 심화 미션: 스위치 만들기 (토글 방식)

현재 코드는 누르고 있을 때만 불이 켜집니다. 하지만 우리가 쓰는 전등 스위치는 한 번 누르면 켜지고, 다시 누르면 꺼지죠? C언어에서 배운 변수와 논리 연산을 활용해 '토글' 기능을 구현해 봅시다.

int ledState = LOW; // 현재 LED의 상태를 기억하는 변수

void setup() {
    pinMode(13, OUTPUT);
    pinMode(2, INPUT_PULLUP);
}

void loop() {
    if (digitalRead(2) == LOW) {  // 버튼이 눌렸다면
        ledState = !ledState;     // 상태를 반전 (! 연산자 사용)
        digitalWrite(13, ledState);
        
        delay(300); // 디바운싱: 버튼이 떨리면서 여러 번 눌리는 걸 방지
    }
}

⚠️ 디바운싱(Debouncing)이란?

기계식 버튼은 눈깜짝할 새에 수백 번 부딪히며 미세한 진동을 만듭니다. 아두이노는 너무 빨라서 이를 여러 번 누른 것으로 착각할 수 있는데, 이를 방지하기 위해 delay()를 살짝 주어 안정을 찾는 시간이 필요합니다.