본문 바로가기
코딩/라즈베리파이 피코

라즈베리파이 피코 버튼 입력하는 방법 (PULL UP 회로이용)

by DIYver 2022. 7. 22.

거의 모든 MCU의 기본이 되는 버튼 입력받는 방법을 
라즈베리파이 피코에서도 해보려한다.

이제부터는 빵판(브레드보드)이 있어야 하겠다.
준비물은 라즈베리파이 피코, 빵판, 점퍼케이블, 버튼 
이렇게만 있으면 된다.

 

대부분의 MCU에는 내부적인 PULL UP 회로가 구성이 다 되어 있다.
라즈베리파이 피코도 마찬가지로 PULL UP 회로가 내장되어 있기 때문에
코딩에서 PULL UP 회로를 사용하겠다고 명령만 해주면 된다.

PULL UP 회로를 뭐고, 왜 써야하는지 잘 모르겠다면
아래 글을 읽고 오면 되겠다.
https://diyver.tistory.com/18

 

[아두이노 강좌] 예제로 배우는 아두이노 #7 DigitalInputPullup, 아두이노 내장 pullup 저항 이용하기

<목표> - 아두이노 내부 회로에 내장되어 있는 풀업저항을 pinMode() 함수를 사용하여 설정하고, digitalRead() 함수를 사용하여 스위치 상태를 읽은 후 digitalWrite() 함수를 이용하여 LED를 제어한다. <준

diyver.tistory.com

 

간단히 설명하자면,
보통 흔히 스위치나 센서는 PULL DOWN 회로로 구성하여서 사용한다.
그래서 보통 버튼을 누르면 HIGH 신호가 감지하는 구조로 회로를 짜거나 코딩을 하는데,
이렇게 되면 문제가 저항도 있어야하고 +전원도 센서에 계속 주고 있어야 한다는 것이다.

그런데 이걸 PULL UP 회로로 구성한다면
저항이 따로 필요 없고 +전원도 따로 배선을 할 필요도 없게 된다.
단지, 버튼이 안눌렸을 때에는 HIGH 신호가, 버튼이 눌리면 LOW 신호가 입력된다는 것만 주의하면 된다.
코딩 할 때, 헷갈리는 것 빼고는 모든게 장점이 된다.

 

배선은 아래처럼 구성하면 되겠다.

 

버튼의 양쪽으로 GND 하나, GP14 하나를 연결해주면 된다.

텍트 스위치는 위와 같은 구조로 되어 있어서,
1번과 2번은 같은 라인이고,  3번과 4번은 같은 라인이니
GND를 1번 또는 2번에,  GP14를 3번 또는 4번에 연결해야 한다.

 

이제 버튼을 이용한 다양한 실제에서 쓰일 법한 코드를 짜보도록 하자.

1. 버튼 누른 횟수 카운트하여 출력하기

import machine
import utime

button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)
count = 0

while True:
    if button.value() == 0:
        count = count+1
        print("You pressed the button!")
        print("count : ", count)
        utime.sleep(2)

버튼을 눌러보면 즉각적으로 카운트가 되지 않고 2초마다 눌러야 카운트가 된다.

버튼을 빠르게 반복적으로 눌러서 카운트를 하려면 코드를 어떻게 짜야 할까?

우선 직접 해보고  안 된다면 아래 방법을 확인해보도록 하자

무한 반복문 안에 버튼 상태가 off가 되는 것을 감지하여 무한 반복문을 끝내는 구조로 작성하면 되겠다.

 

위의 버튼 카운트 까지 했다면, 
코드를 재실행 한 다음에 눈을 감고  20번 버튼을 클릭해보자.

보통의 경우 count 가 20회가 아니라 더 많이 기록 되었을 것이다.
이 현상이 무엇이고, 어떻게 잡는지가 궁금하다면 아래 접은글을 확인해보자.

더보기

버튼이 여러번 눌리는 현상은 주변에서 흔히 볼 수 있다. 
당장 수명이 다한 키보드에서 발생되는 경우가 있겠다.

 

이런 현상을 채터링 현상이라고 하는데,
물리적인 버튼 같은 경우, 버튼을 누르면 금속이 서로 닿으면서 전기신호가 이동하여 감지한다.

이 때, 금속이 닿았다 떨어졌다 닿았다를 빠르게 반복하다보니 버튼이 여러번 눌리는 것으로 감지되는 것이다.

해결방법은 다양하게 있을 수 있다.

이렇게 중간에 delay를 걸어서 빠른 시간내에 입력된 신호를 감지하지 않는 방식으로 중복 입력을 막는 방법이 있다.

 

다른 방법으로는 micro python 공식 홈페이지에서 추천하는 방식이다.

wait_pin_change( ) 라는 사용자 함수를 만들어서 사용하는데,
모듈화 되어 있어서 다른 코드에 접목시키기도 쉬워서 좋은 코드라 생각한다.

보면 현재 버튼 상태를 감지하고, 상태가 바뀌었으면 active 카운트를 올리는데 20까지 올라갔다면 신호 입력으로 감지하고 넘어간다는 뜻이다.

보면 약 20ms 정도 버튼을 누르고 있으면 버튼을 누른 것으로 감지한다는 뜻이다.

이 코드가 정상적으로 작동하지 않으려면, 사람이 버튼을 누름에 있어서 누르고 있는 시간이 20ms 이하가 되면 되는 것이다.

아두이노에서는 Debounce 방법으로 타이머를 이용하여 버튼이 눌린 시점에서 약 50ms 까지 입력된 모른 신호는 무시하는 그런 방법을 썼었는데, 
해당 방법을 사용해도 같은 결과가 나올 것이다.

여기서 중요한 것은, 버튼 카운트가 중요한 프로젝트라면 이런 Debounce 기술을 생각하고 적용해야 한다는 것이다.
어떤 방식이 더 좋고 이런것을 떠나서 자신에게 맞거나, 해당 프로젝트에 맞는 방법을 사용하면 된다.

채터링 현상을 잡지 못하면 왜 버튼은 한번 눌렀는데, 2~3번 눌려서 오작동 하지? 하는 패닉상태에 빠질 수 있다.

https://docs.micropython.org/en/latest/pyboard/tutorial/debounce.html?highlight=debounce 

 

1. Debouncing a pin input — MicroPython 1.19.1 documentation

© Copyright - The MicroPython Documentation is Copyright © 2014-2022, Damien P. George, Paul Sokolovsky, and contributors. Last updated on 29 Jul 2022.

docs.micropython.org

자세한 내용이 궁금하면 위의 micro python 공식 홈페이지 자료를 찾아보도록 하자.

 

이 방식은 버튼 뿐만이 아니라, 각종 센서에서 감지 카운트를 증가 시킬 때, 사용하는 방법으로
필수적으로 할 줄 알아야 한다.

 

 

2. 버튼 입력으로 내부 LED ON/OFF 제어

import machine
import utime

led_onboard = machine.Pin(25, machine.Pin.OUT)

button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)
count = 0


while True:
    if button.value() == 0:
        count = count+1
        print("You pressed the button!")
        print("count : ", count)
        while True:
            if button.value() == 1:
                break
        
        if count%2 == 0:
            led_onboard.value(0)
        else:
            led_onboard.value(1)

버튼을 한 번 누르면 LED 가 켜지고, 다시 한 번 누르면 LED가 꺼지는 코드이다.

count 에 저장

된 값을 2로 나누어서 짝수인지 홀수인지 구별하여 
홀 수 이면 LED를 켜고,  짝 수이면 LED를 끄는 방식의 코드이다.

다른 방법도 여러개 있으니 정상적으로 구동하면 된 것이다.

이 방식은 정말 다양한 곳에 쓰일 수 있는 기초로, 버튼으로 모터제어, 센서제어 등에 사용된다.

 

3. 버튼 입력하고 있는 동안에만 내부 LED 점등

import machine
import utime

led_onboard = machine.Pin(25, machine.Pin.OUT)

button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)
count = 0

while True:
    
    while button.value() == 0:
        led_onboard.value(1)
        
    led_onboard.value(0)

코드는 위의 코드처럼 짜면 된다.

그러면 버튼을 누르고 있는 동안에만 LED가 점등되고,
손을 떼면 바로 LED가 소등된다.

이 방식은 나중에 버튼으로 모터를 작동한다거나, 스피커를 작동할 때 쓰이는 방법이다.

 

2번과 3번에는 굳이 채터링 현상 방지 코드가 들어가있지 않아서,
오작동 할 수 있다.
해결방법이 궁금하신 분들은 위의 1번 밑에 있는 접힌글을 읽어보면 된다.

 

 

위의 3가지 경우의 코딩을 완벽하게 할 수 있다면 
어지간한 버튼을 사용하는 프로젝트에서 문제없이 코딩을 할 수 있을 것이다.

댓글