공부중
[Arduino] 푸시 버튼 실습 본문
따라서 아래 사진처럼 연결해야 버튼을 사용할 수 있다.
각도를 돌리면 버튼을 누르는 의미가 없어질듯..
기존 상태 | 버튼 누르기 전 | 버튼 누른 후 |
1. 버튼 실습
int pushButton = 12; // 버튼이 연결된 핀 번호
void setup() {
Serial.begin(19200); // 시리얼 통신 초기화
pinMode(pushButton, INPUT); // 버튼 핀을 입력 모드로 설정
}
void loop() {
int buttonState = digitalRead(pushButton); // 버튼 상태 읽기
Serial.println(buttonState); // 버튼 상태를 시리얼 모니터에 출력
}
위 코드를 동작시켜 보자.
아직 버튼을 누르지 않은 상태임에도 LED에 불이 들어와 있는 것을 확인할 수 있다.
위의 회로 상태에서 불이 들어와 있는 것으로 이해할 수 있다.
위와 같은 현상이 발생하는 이유는 0이 아니라 0.3과 같이 미세 전류가 흐르기 때문이다.
시리얼 모니터를 확인해보자.
버튼을 누르지 않을 경우는 대부분 0이 나온다.
버튼을 눌러도 바로 반응되지 않을 뿐 아니라 아래와 같이 0과 1이 반복되어 나오는 현상도 관찰된다.
2. 풀업
회로도를 수정하여 풀업 회로를 만든 후 확인해보자. 코드는 위와 동일한 코드를 사용하자.
스위치가 on일때는 그라운드와 연결되며, 0 .
이때 R1에서 5V에 해당하는 전압 강하가 나타날 것이다.
스위치가 off 일때는 단락회로이므로 VDD와 연결된다. input으로 설정하여, 아두이노 입력 핀 내의 내부 저항이 매우 클 것으로 예상.
따라서 R1은 상대적으로 작으며, 대부분의 VDD 값이 PIN12에서 확인 가능해짐.
풀업 저항 회로와 동작 원리
- 회로 구성:
- 스위치가 ON일 때:
- 버튼이 눌려 GND와 연결되므로 핀에서 LOW (0) 신호를 읽습니다.
- 이때 저항(R1)은 5V 전압을 소모하며, 전류가 GND로 흐릅니다.
- 스위치가 OFF일 때:
- 버튼이 눌리지 않으면 **VDD (5V)**에 연결됩니다.
- 핀에서 HIGH (1) 신호를 읽습니다.
- 스위치가 ON일 때:
- 풀업 저항의 역할:
- 버튼이 눌리지 않은 상태에서 핀이 **부동 상태(Floating)**가 되는 것을 방지합니다.
- 저항(R1)은 VDD와 입력 핀 사이에 위치하여 안정적으로 HIGH 신호를 제공합니다.
- 내부 풀업 저항:
- 아두이노는 내부 풀업 저항을 활성화할 수 있어 외부 저항이 필요 없는 경우도 많습니다. 이를 활용하면 더 간단히 풀업 회로를 구현할 수 있습니다.
회로도 설명
- 구성 요소:
- R1 (풀업 저항):
- 일반적으로 10kΩ 정도의 저항값을 사용합니다.
- 너무 낮으면 전류 소모가 커지고, 너무 높으면 핀이 안정적으로 HIGH 신호를 읽지 못할 수 있습니다.
- 스위치:
- 하나의 단자는 GND에 연결.
- 다른 단자는 R1과 핀(예: PIN12) 사이에 연결.
- VDD (5V):
- R1과 연결.
- R1 (풀업 저항):
- 회로 연결:
-
VDD --- R1 --- PIN12 --- Switch --- GND
-
3. 풀다운
스위치가 연결된 상태에서는 저항보다는 pin12가 저항이 적으므로 노이즈를 제거할 수 있다.
스위치가 연결되지 않은 상태에서는 그라운드와 연결되어 있어 노이즈를 제거할 수 있다.
풀다운 저항 회로와 동작 원리
- 풀다운 저항의 역할:
- 풀다운 저항은 버튼이 눌리지 않았을 때 입력 핀이 안정적으로 LOW (0) 상태를 유지하도록 합니다.
- 스위치가 눌리지 않으면 핀이 GND에 연결되어 있어 전기적 노이즈로 인해 발생할 수 있는 불안정한 상태(부동 상태)를 방지합니다.
- 스위치 동작:
- 스위치가 ON (눌림):
- 핀(PIN12)은 VDD(5V)에 직접 연결됩니다.
- 입력 핀의 저항은 매우 크기 때문에 대부분의 전류가 핀으로 흐르고, 핀이 안정적으로 HIGH (1) 상태를 읽습니다.
- 스위치가 OFF (눌리지 않음):
- 핀이 GND(0V)에 연결되고, LOW (0) 상태를 유지합니다.
- 풀다운 저항은 노이즈 제거 및 안정적인 상태를 유지하는 데 도움을 줍니다.
- 스위치가 ON (눌림):
- 저항 값 선택:
- 풀다운 저항(R1)은 보통 10kΩ을 사용합니다.
- 저항 값이 너무 작으면 전력 낭비가 커지고, 너무 크면 핀 상태가 불안정해질 수 있습니다.
회로도 설명
- 구성 요소:
- R1 (풀다운 저항):
- 한쪽 단자는 GND에 연결.
- 다른 쪽 단자는 버튼과 입력 핀 사이에 연결.
- 스위치:
- 하나의 단자는 VDD(5V)에 연결.
- 다른 단자는 저항과 핀(PIN12)에 연결.
- R1 (풀다운 저항):
- 회로 연결:
VDD --- Switch --- PIN12 --- R1 --- GND
- 동작 원리:
- 스위치가 눌리면 PIN12가 VDD에 연결되어 HIGH (1) 상태를 읽음.
- 스위치가 눌리지 않으면 R1을 통해 GND에 연결되어 LOW (0) 상태를 읽음.
4. 아두이노 내장 함수
회로를 통해 풀업과 기능을 구현할 수 있지만, 아두이노의 마이크로 컨트롤러 내부에 내장 풀업, 저항이 포함되어 있으므로 위에서 저항을 통해 회로를 구현한것처럼 하지 않아도, 내장함수를 사용하여 풀업과 기능을 사용할 수 있다.
풀업
pinMode(pushButton, INPUT_PULLUP);
참고로 풀다운은 없다.
아두이노에서 내부 풀다운 저항을 제공하지 않습니다. 따라서 풀다운 저항을 사용하려면 외부 저항을 추가로 회로에 연결해야 합니다. 반면에, 아두이노는 내부 풀업 저항을 지원하며, 이는 INPUT_PULLUP 모드를 통해 활성화할 수 있습니다.
int pushButton = 12; // 버튼이 연결된 핀 번호
void setup() {
Serial.begin(115200); // 시리얼 통신 초기화
pinMode(pushButton, INPUT_PULLUP); // 버튼 핀을 입력 모드로 설정
}
void loop() {
int buttonState = digitalRead(pushButton); // 버튼 상태 읽기
Serial.println(buttonState); // 버튼 상태를 시리얼 모니터에 출력
}
참고로 이때는 회로를 다음과 같이 만들어야 한다.
아까처럼 VDD랑 연결하면 풀업 인풋을 사용하기 때문에 그냥 버튼 유무랑 관계없이 1이 나올 뿐 아니라 쇼트날 수 있다..
버튼을 누르지 않으면 1, 누르면 0이 나오게 된다.
5. 버튼을 누른 횟수
아두이노의 내장 pullup을 사용할 경우,,
버튼을 누르지 않는다면 기본값은 1이고, 버튼을 누르면 0이 될 것이다.
int pin_button = 12; // 버튼이 연결된 핀 번호
bool state_current = false; // 버튼의 현재 상태
bool state_previous = false; // 버튼의 이전 상태
int count = 0; // 버튼이 눌린 횟수 저장
void setup() {
Serial.begin(9600); // 시리얼 통신 초기화
pinMode(pin_button, INPUT_PULLUP); // 내부 풀업 저항 활성화
}
void loop() {
state_current = digitalRead(pin_button); // 버튼의 현재 상태 읽기
// 버튼이 눌린 상태인지 확인 (LOW는 눌린 상태인 것. )
if (state_current == 0) { // 버튼이 눌린 경우
if (state_previous == 0) { // 이전 상태가 눌리지 않았다면
count++; // 카운트 증가
state_previous = true; // 중복 카운트 방지
Serial.println(count); // 카운트 값 출력
}
//delay(50); // 디바운싱
} else {
state_previous = false; // 버튼이 눌리지 않은 상태로 리셋
}
}
채터링은 버튼의 기계적인 진동에 의해 on.off가 반복해서 나타나는 현상을 의미하며, 디바운싱을 사용하여 채터링을 완화할 수 있다.
6. 예제 실습
// 데이터 핀을 통한 디지털 데이터 입력
// 4개의 LED와 버튼 1개를 연결하여, 버튼을 누를 때마다 LED가 하나씩 켜지게 하기
|
// 데이터 핀을 통한 디지털 데이터 입력
// 4개의 LED와 버튼 1개를 연결하여, 버튼을 누를 때마다 LED가 하나씩 켜지게 하기
#define PIN1 4 // LED가 연결된 핀 번호
#define PIN2 5 // LED가 연결된 핀 번호
#define PIN3 6 // LED가 연결된 핀 번호
#define PIN4 7 // LED가 연결된 핀 번호
int pin_button = 12; // 버튼이 연결된 핀 번호
bool state_current = false; // 버튼의 현재 상태
bool state_previous = false; // 버튼의 이전 상태
int count = 0; // 버튼이 눌린 횟수 저장
void setup() {
Serial.begin(9600); // 시리얼 통신 초기화
pinMode(pin_button, INPUT_PULLUP); // 내부 풀업 저항 활성화
pinMode(PIN1, OUTPUT);
pinMode(PIN2, OUTPUT);
pinMode(PIN3, OUTPUT);
pinMode(PIN4, OUTPUT);
}
void loop() {
state_current = digitalRead(pin_button); // 버튼의 현재 상태 읽기
if (count > 4){
count = 0;
}
// 버튼이 눌린 상태인지 확인 (LOW는 눌린 상태인 것. )
if (state_current == 0) { // 버튼이 눌린 경우
if (state_previous == 0) { // 이전 상태가 눌리지 않았다면
count++; // 카운트 증가
state_previous = true; // 중복 카운트 방지
Serial.println(count); // 카운트 값 출력
}
delay(50); // 디바운싱
} else {
state_previous = false; // 버튼이 눌리지 않은 상태로 리셋
}
if (count == 0) {
digitalWrite(PIN1, LOW);
digitalWrite(PIN2, LOW);
digitalWrite(PIN3, LOW);
digitalWrite(PIN4, LOW);
}
if (count == 1) {
digitalWrite(PIN1, HIGH);
}
if (count == 2) {
digitalWrite(PIN2, HIGH);
}
if (count == 3) {
digitalWrite(PIN3, HIGH);
}
if (count == 4) {
digitalWrite(PIN4, HIGH);
}
}
7. 예제 실습
버튼을 누른 횟수에 따라 결과값 2진수를 LED로 표현하기
---
15까지의 수만 표현 가능할 듯.
#define PIN1 4 // LED가 연결된 핀 번호
#define PIN2 5 // LED가 연결된 핀 번호
#define PIN3 6 // LED가 연결된 핀 번호
#define PIN4 7 // LED가 연결된 핀 번호
int pin_button = 12; // 버튼이 연결된 핀 번호
bool state_current = false; // 버튼의 현재 상태
bool state_previous = false; // 버튼의 이전 상태
int count = 0; // 버튼이 눌린 횟수 저장
void setup() {
Serial.begin(9600); // 시리얼 통신 초기화
pinMode(pin_button, INPUT_PULLUP); // 내부 풀업 저항 활성화
pinMode(PIN1, OUTPUT);
pinMode(PIN2, OUTPUT);
pinMode(PIN3, OUTPUT);
pinMode(PIN4, OUTPUT);
}
void loop() {
state_current = digitalRead(pin_button); // 버튼의 현재 상태 읽기
if (!state_current && !state_previous) { // 버튼이 눌린 경우 (LOW가 눌린 상태)
state_previous = true; // 중복 카운트 방지
count++; // 카운트 증가
count %= 16; // 카운트가 16에 도달하면 0으로 리셋
delay(50); // 디바운싱
Serial.println(count); // 카운트 값 출력
Serial.println(count, BIN); // 카운트 값을 이진수로 출력
} else if (state_current) {
state_previous = false; // 버튼이 눌리지 않은 상태로 리셋
}
// LED 상태 업데이트
digitalWrite(PIN1, (count & 0b0001) ? HIGH : LOW);
digitalWrite(PIN2, (count & 0b0010) ? HIGH : LOW);
digitalWrite(PIN3, (count & 0b0100) ? HIGH : LOW);
digitalWrite(PIN4, (count & 0b1000) ? HIGH : LOW);
}
LED 상태 업데이트 하는 부분 설명
count 변수는 십진수 값으로 저장되지만, 컴퓨터 내부에서는 이진수로 표현되고 처리됩니다.
- LED1 (PIN1): count & 0b0001 연산을 수행합니다.
- 1010 & 0001 = 0000 (결과는 0)
- 따라서, LED1은 꺼집니다 (LOW).
- LED2 (PIN2): count & 0b0010 연산을 수행합니다.
- 1010 & 0010 = 0010 (결과는 2, 0이 아님)
- 따라서, LED2는 켜집니다 (HIGH).
- LED3 (PIN3): count & 0b0100 연산을 수행합니다.
- 1010 & 0100 = 0000 (결과는 0)
- 따라서, LED3은 꺼집니다 (LOW).
- LED4 (PIN4): count & 0b1000 연산을 수행합니다.
- 1010 & 1000 = 1000 (결과는 8, 0이 아님)
- 따라서, LED4는 켜집니다 (HIGH).
? HIGH : LOW는 삼항 연산자(Ternary Operator)를 사용한 구문입니다. 삼항 연산자는 조건식을 기반으로 한 두 개의 결과 중 하나를 선택하여 반환하는데 사용됩니다. 이 연산자는 일반적으로 다음과 같은 형식을 가집니다:
조건 ? 참일 때의 값 : 거짓일 때의 값;
개인적으로 버튼은 너무 잘 안되서, 나중에 프로젝트에서 사용 잘 안할듯..
'프로그래밍 > Arduino' 카테고리의 다른 글
[Arduino] 조도센서 CDS 실습 (0) | 2025.01.23 |
---|---|
[Arduino] error 해결 'ledcAttachPin' was not declared in this scope; did you mean 'ledcAttach? (0) | 2025.01.23 |
[Arduino] 가변저항 실습 (0) | 2025.01.22 |
[Arduino] PIN 출력 실습 (0) | 2025.01.22 |
[Arduino] 입출력 실습 (0) | 2025.01.21 |