공부중

[Arduino] 푸시 버튼 실습 본문

프로그래밍/Arduino

[Arduino] 푸시 버튼 실습

복습 2025. 1. 22. 02:30
728x90

 

 

https://wikidocs.net/30758

 

05-1 푸시버튼으로 LED 켜고 끄기

푸시버튼은 버튼을 누르는 동안 HIGH 값을 가지며 뗄 때 LOW 값을 갖습니다. 엄밀히 누를 때 HIGH 또는 LOW 값을 선택적으로 가질 수 있지만 풀업(Pull-up), 풀…

wikidocs.net

 

 

 

따라서 아래 사진처럼 연결해야 버튼을 사용할 수 있다. 

각도를 돌리면 버튼을 누르는 의미가 없어질듯.. 

 

 

기존 상태  버튼 누르기 전  버튼 누른 후 

 

 

 

 

 

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에서 확인 가능해짐. 

더보기

풀업 저항 회로와 동작 원리

  1. 회로 구성:
    • 스위치가 ON일 때:
      • 버튼이 눌려 GND와 연결되므로 핀에서 LOW (0) 신호를 읽습니다.
      • 이때 저항(R1)은 5V 전압을 소모하며, 전류가 GND로 흐릅니다.
    • 스위치가 OFF일 때:
      • 버튼이 눌리지 않으면 **VDD (5V)**에 연결됩니다.
      • 핀에서 HIGH (1) 신호를 읽습니다.
  2. 풀업 저항의 역할:
    • 버튼이 눌리지 않은 상태에서 핀이 **부동 상태(Floating)**가 되는 것을 방지합니다.
    • 저항(R1)은 VDD와 입력 핀 사이에 위치하여 안정적으로 HIGH 신호를 제공합니다.
  3. 내부 풀업 저항:
    • 아두이노는 내부 풀업 저항을 활성화할 수 있어 외부 저항이 필요 없는 경우도 많습니다. 이를 활용하면 더 간단히 풀업 회로를 구현할 수 있습니다.

회로도 설명

  • 구성 요소:
    1. R1 (풀업 저항):
      • 일반적으로 10kΩ 정도의 저항값을 사용합니다.
      • 너무 낮으면 전류 소모가 커지고, 너무 높으면 핀이 안정적으로 HIGH 신호를 읽지 못할 수 있습니다.
    2. 스위치:
      • 하나의 단자는 GND에 연결.
      • 다른 단자는 R1과 핀(예: PIN12) 사이에 연결.
    3. VDD (5V):
      • R1과 연결.
  • 회로 연결:
    •  
      VDD --- R1 --- PIN12 --- Switch --- GND

 

 

3. 풀다운 

 

 

 

스위치가 연결된 상태에서는 저항보다는 pin12가 저항이 적으므로 노이즈를 제거할 수 있다. 

스위치가 연결되지 않은 상태에서는 그라운드와 연결되어 있어 노이즈를 제거할 수 있다. 

더보기

풀다운 저항 회로와 동작 원리

  1. 풀다운 저항의 역할:
    • 풀다운 저항은 버튼이 눌리지 않았을 때 입력 핀이 안정적으로 LOW (0) 상태를 유지하도록 합니다.
    • 스위치가 눌리지 않으면 핀이 GND에 연결되어 있어 전기적 노이즈로 인해 발생할 수 있는 불안정한 상태(부동 상태)를 방지합니다.
  2. 스위치 동작:
    • 스위치가 ON (눌림):
      • 핀(PIN12)은 VDD(5V)에 직접 연결됩니다.
      • 입력 핀의 저항은 매우 크기 때문에 대부분의 전류가 핀으로 흐르고, 핀이 안정적으로 HIGH (1) 상태를 읽습니다.
    • 스위치가 OFF (눌리지 않음):
      • 핀이 GND(0V)에 연결되고, LOW (0) 상태를 유지합니다.
      • 풀다운 저항은 노이즈 제거 및 안정적인 상태를 유지하는 데 도움을 줍니다.
  3. 저항 값 선택:
    • 풀다운 저항(R1)은 보통 10kΩ을 사용합니다.
    • 저항 값이 너무 작으면 전력 낭비가 커지고, 너무 크면 핀 상태가 불안정해질 수 있습니다.

회로도 설명

  1. 구성 요소:
    • R1 (풀다운 저항):
      • 한쪽 단자는 GND에 연결.
      • 다른 쪽 단자는 버튼과 입력 핀 사이에 연결.
    • 스위치:
      • 하나의 단자는 VDD(5V)에 연결.
      • 다른 단자는 저항과 핀(PIN12)에 연결.
  2. 회로 연결:
     
    VDD --- Switch --- PIN12 --- R1 --- GND
  3. 동작 원리:
    • 스위치가 눌리면 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)를 사용한 구문입니다. 삼항 연산자는 조건식을 기반으로 한 두 개의 결과 중 하나를 선택하여 반환하는데 사용됩니다. 이 연산자는 일반적으로 다음과 같은 형식을 가집니다:

조건 ? 참일 때의 값 : 거짓일 때의 값;

개인적으로 버튼은 너무 잘 안되서, 나중에 프로젝트에서 사용 잘 안할듯.. 

 

 

 

 

 

728x90