[아두이노] [강좌] 8. digitalRead() 함수(2) – 풀업 저항과 INPUT_PULLUP 모드
지난 강좌에서 스위치를 눌렀을 때는 ‘1’의 값이 잘 나오다가 스위치에서 손을 떼면 ‘0’도 나오고 ‘1’도 나오는 예상치 못한 결과가 나왔었다. 이유가 뭘까? 연결이 끊기면 당연히 ‘0’이 나와야 되는거 아닌가?
다음 사진을 보자. 다음 사진은 스위치를 눌렀을 때와 누르지 않았을 때 아두이노 보드의 12번 핀으로 입력되는 전압의 크기를 ‘오실로스코프’라는 장비를 이용해서 측정한 것이다.

스위치를 눌렀을 때

스위치를 누르지 않았을 때
우선 스위치를 눌렀을 때의 사진을 보자. 빨간색 선으로 표시한 곳이 0V를 나타내는 곳이고, 세로 축 한 칸 당 1V를 나타낸다. 그래서 노란색 굵은 선이 있는 곳의 위치가 3.3V. 스위치를 눌렀을 때 3.3V의 전압이 깨끗하게 입력되고 있는 것을 확인할 수 있다. (참고로 가로 축은 시간을 나타냄)
그럼 아래에 스위치를 누르지 않았을 때의 신호를 보자. 똑같이 빨간색 선이 0V를 나타내는 자리인데, 스위치를 눌렀을 때처럼 깨끗한 직선이 나오는 것이 아니라 위아래로 마구 흔들리는 신호를 확인할 수 있다.
이것이 스위치를 누르지 않았을 때 ‘0’이 계속해서 나오지 않는 이유이다.
이러한 상태를 “플로팅(Floating) 상태”라고 하는데, Floating이라는 단어 뜻 그대로 ‘떠 있는’ 상태라는 말이다.
스위치에서 손을 떼서 두 핀이 떨어지게 되면 12번 핀에는 전기와 관련된 어떠한 입력도 없게 된다. 선이 끊어져 있는 상태. 이 상태에서는 ‘LOW’도 아니고 ‘HIGH’도 아닌, 그냥 떠 있는 상태가 된다.
그럼 ‘LOW’는 언제 입력되는 거야? 전기가 안 들어올 때 ‘LOW’가 들어오는게 아니라는 말?
아니라는 말. ‘LOW’가 들어올 때는 기준 입력 전압보다 낮은 전압이 입력될 때, 즉 전기는 들어오되 전압의 크기가 0~3V(우노 또는 메가의 경우)인 전기가 연결되었을 때 그 값을 ‘LOW’라고 한다.
헷갈려. ㅜㅜ
정리하자면, 입력 핀에 아무것도 연결이 되지 않은 상태에서는 정확한 입력 값을 알 수 없다. 입력 핀에는 0V의 전기든, 5V의 전기든 일단 연결이 된 상태에서 그 전압의 크기를 가지고 ‘0’이냐, ‘1’이냐를 판단할 수 있다는 말.
그래서 스위치처럼 연결이 끊어지는 상황이 생길 수 있을 경우, 연결이 끊어졌을 때 플로팅 상태가 되는 것을 방지하기 위해 하드웨어 또는 소프트웨어에서 추가 장치를 해주는데, 이 것이 바로 ‘풀업(Pull-up)’ 또는 ‘풀다운(Pull-down)’ 저항이다.
흠.
우선 ‘풀업’ 저항에 대해 설명하자. ‘풀업’만 알면 ‘풀다운’은 자동으로 알게 됨.
풀업 저항과 풀다운 저항의 구조는 다음과 같다.

저항이 필요하다. 여기서는 330옴짜리 저항을 사용했다. 아래 내용은 풀업 저항의 구조에 대해 설명하기 위한 실습이므로, 저항이 없다면 내용만 읽고 이해해도 좋다. 대신 뒤에 나오는 ‘INPUT_PULLUP’ 모드에 대한 부분은 꼭 해보기.
저항이 있다면, 브레드 보드에 연결된 스위치를 다음 그림과 같이 변경하자. 저항의 방향은 상관 없다. 3.3V와 GND 연결 부분에 주의할 것. 빨간색 선이 3.3V, 흰색 선이 GND.
그림이 어렵다면, 사진으로.



알아보기 쉽도록 모두 다른 색 핀 케이블을 이용해 연결했다. 복잡해 보일지 모르지만, 위에서 말한 풀업 저항의 구조와 동일하다.
업로드 한 후 시리얼 모니터를 실행하여 값을 살펴보자.
나온다!
스위치를 눌렀다 뗐다 하며 값이 변하는 것을 보자. 스위치를 눌렀을 때 ‘0’이 나오고, 손을 떼면 ‘1’이 나와야 한다. 아까와는 ‘0’과 ‘1’이 반대로 나오기는 하지만, 스위치를 누르지 않았을 때 ‘0’과 ‘1’이 널뛰며 나오던 것은 사라지고 ‘1’이 꾸준하게 나올 것이다.
오실로스코프를 이용해 신호를 살펴보자.


스위치를 누르지 않았을 때
0V에서도, 3.3V에서도 직선으로 신호가 깨끗하게 나오는 것을 볼 수 있다. 이 것이 바로 풀업 저항의 효과다.
근데 왜? 왜 이렇게 되는 거지?
다시 한 번 아두이노 보드와 스위치가 연결된 그림을 살펴보자. 스위치에서 떨어진 두 핀을 빨간색 선으로 표시해 두었다.

자, 스위치의 빨간색 선을 기준으로 양쪽 두 핀은 떨어져 있기 때문에 전기는 저 선을 넘어갈 수 없다. 그럼 아두이노 보드에서 나오는3.3V(빨간색 핀 케이블→주황색 핀 케이블)의 전기는 어디로 흐를까?

입력 핀으로 흐른다. 그래서 스위치를 누르지 않았을 때 시리얼 모니터 화면에 ‘1’, 즉 ‘HIGH’의 값이 출력됐던 것이다.
그럼 스위치를 눌러서 떨어져 있던 양쪽 핀이 서로 연결되면 전기가 어디로 흐를까?

전기는 낮은 곳을 향해 흐른다. GND(접지)는 모든 전기가 모이는 가장 낮은 곳이다. 그리고 쉬운 곳으로 흐른다. 3.3V로 연결되는 쪽에는 저항이 붙어 있어 GND로 연결된 쪽에 비해 전기가 흐르기 어렵다.
따라서 입력 핀으로 흐르던 전기가 스위치의 양쪽 핀이 연결됨에 따라 모두 GND로 방향을 바꿔 흐르게 되고, 입력 핀은 GND와 연결된 상태가 된다. 즉, 0V와 연결된다는 말. 입력 핀에 3.3V가 여전히 연결되어 있지만, 말했다시피 3.3V 쪽에는 저항이 달려 있어서 결국 입력 핀은 쉽게 흐를 수 있는 GND에 연결되게 되는 것.
아무것도 연결되지 않았던 플로팅 상태를 방지하기 위해 이처럼 풀업 저항을 사용하여 스위치가 눌려지지 않아도 안정된 값이 나오도록 하는 것이다. 이 때 플로팅 상태의 값을 'HIGH'로 끌어 올린다고 하여 풀업(Pull-Up).
풀다운 저항은 풀업 저항과 반대로 스위치를 눌렀을 때 ‘1’, 뗐을 때 ‘0’이 나오도록 하는 방법이고, 풀업 저항에서 3.3V와 GND의 위치만 바꿔주면 된다. 이 때는 기본 입력 값을 'LOW'로 끌어 내린다고 하여 풀다운(Pull-Down)이라고 한다.
눌렀을 때 ‘1’이 나오는 것이 보기도 편하고 맘도 편하겠지만, 실제로 회로를 설계할 때는 풀다운보다 풀업 저항을 많이 사용한다. 이유는 풀업이 풀다운에 비해 노이즈나 충격에 강하기 때문.
대.다.나.다.
아니. 저항이 없는 사람들은 그럼, 스위치 실습을 못하나? 작품에 스위치 못 넣나??
아니다. 기억력이 좋은 사람은 여기서 뭔가 생각나겠지. pinMode() 함수에서 ‘OUTPUT’, ‘INPUT’ 모드 외에 ‘INPUT_PULLUP’이라는 모드가 존재했었다는 걸.
아.. 이걸 설명하기 위해서 나는 이만큼 긴 글을 써왔는지도. ㅜㅜ
아두이노의 모든 핀에는 ‘내부’ 풀업 저항이 달려있어서, 이 것을 사용하겠다고 선언만 해주면 자동으로 풀업 저항이 동작하게 된다.
엄청 간단하잖아!
내부 풀업 저항을 사용하겠다고 선언하는 방법이 바로 pinMode() 함수의 'INPUT_PULLUP’ 모드.
자, 그럼 사용해볼까?
우선 DigitalReadSerial 예제에서 pinMode() 함수의 매개 변수를 ‘INPUT_PULLUP’으로 바꾸자.
DigitalReadSerial_InputPullup.ino |
int pushButton = 12;
void setup() { Serial.begin(9600); pinMode(pushButton, INPUT_PULLUP); }
void loop() { int buttonState = digitalRead(pushButton);
Serial.println(buttonState); delay(500);
} |
그리고 아두이노 보드와 스위치의 연결은 다시 깔끔하게. 단, 유의할 것은 스위치의 두 핀 중 한 쪽이 입력 핀(12번 핀), 다른 한 쪽이 GND에 연결되어야 한다는 것.

업로드 한 후 시리얼 모니터로 값을 확인해보자. 외부 풀업 저항을 연결했을 때와 동일한 결과가 나올 것이다. 안 나오면 안됨.
이 것이 바로 'INPUT_PULLUP' 모드.
아. 이번 강좌는(이 아니라 이번 강좌도) 너무 길었다...
자, 이번 강좌의 주제.
pinMode() 함수로 ‘INPUT’ 또는 ‘INPUT_PULLUP’ 모드로 설정했다면, digitalRead() 함수를 이용해 핀으로 입력되는 값을 읽어올 수 있다. ‘INPUT_PULLUP’ 모드는 플로팅 상태를 방지하기 위해 내부 풀업 저항을 사용하기 위한 모드이다.
끝!