Raspberry Pi_Kor_25.7.2 Digital 입력 – button 입력


Published Book on Amazon


All of IOT Starting with the Latest Raspberry Pi from Beginner to Advanced – Volume 1
All of IOT Starting with the Latest Raspberry Pi from Beginner to Advanced – Volume 2


출판된 한글판 도서


최신 라즈베리파이(Raspberry Pi)로 시작하는 사물인터넷(IOT)의 모든 것 – 초보에서 고급까지 (상)
최신 라즈베리파이(Raspberry Pi)로 시작하는 사물인터넷(IOT)의 모든 것 – 초보에서 고급까지 (하)


Original Book Contents


25.7.2  Digital 입력 – button 입력

 

여기서는 button Raspberry Pi에 연결하고, button이 눌려졌는지를 확인하기 위해서 pin의 입력 신호를 읽어서 처리하는 사례에 대해서 살펴 볼 것이다.

 

25.7.2.1    <RPi.GPIO> library의 입력 방식

 

<RPi.GPIO> library를 이용하여 입력을 처리하는 방법에는 falling 방식과 interrupt 방식이 있다. 다음은 그 각각에 대해서 설명하고자 한다.

 

   falling 방식의 입력

 

falling 방식이란 pin의 상태를 지속적으로 점검하는 방식으로 pin의 상태가 변경되었는지를 확인하기 위해서 지속적으로 pin의 입력 값을 읽어서 이전 상태와 비교하여 변경여부를 확인하는 방식이다.

 

다음과 같은 방식으로 프로그램을 작성한다.  

 

~ 중략

 

while True:

    if  GPIO.input(11) == False:

       # action code to be done

 time.sleep(0.1)

 

~ 중략

 

위에서는 "input( )" 함수를 이용하여 pin에서 지속적으로 입력을 받아서 그 값이 변동되었는지를 자체적으로 판단하고 있다. 값이 변동된 경우에 필요한 작업을 처리하도록 되어 있다.

 

이 방식은 상태가 변경되었는지를 점검하는 동안 아무 것도 처리하지 못한다. 버튼을 아주 빨리 눌렀을 경우는 입력 값을 읽기도 전에 변경 상태가 끝나 버릴 수도 있다.


 

   interrupt 방식 입력

 

반면 interrupt 방식은 어떤 사건이 일어나거나 pin의 상태가 변경되면, 프로그램이 자동적으로 변경을 감지하여 interrupt를 발생시켜서 변경되었음을 통지를 해주고, 해당 interrupt가 발생했을 때 수행할 사전에 지정된 작업을 처리하는 방식을 말한다.

 

이 방식에서는 특정 pin의 입력 전압이 "HIGH"에서 "LOW", 또는 "LOW"에서 "HIGH"로 변경될 때 실행할 작업을 사전에 등록해 놓고, 상태가 변경되면 자동으로 그 작업이 실행되도록 하는 것이다.

 

다음과 같은 방식으로 프로그램을 작성한다.

 

~ 중략

 

def callback_routine(channel) :

# action code to be done

 

GPIO.add_event_detect(11, GPIO.FALLING, callback=callback_routine)

 

while True:

time.sleep(1)

 

~ 중략

 

위에서는 먼저 "callback_routine( )" 함수를 정의하여 interrupt가 발생했을 때 실행할 작업을 정의하고 있다.

 

다음으로 "add_event_detect( )" 함수를 사용하여 특정 pin에 대해서 interrupt가 발생해야 하는 조건으로 "GPIO.FALLING"을 지정하고 interrupt가 발생했을 때 처리해야 할 작업으로 "callback_routine"을 지정하고 있다. 이렇게 event를 등록해 놓으면, 해당 event가 발생했을 때 즉시 지정된 작업이 처리된다.


 

interrupt 발생 조건에서 사용할 수 있는 선택조건은 다음과 같다.

    GPIO.FALLING          -- pin 전압이 "HIGH"에서 "LOW"로 변경될 때 interrupt 호출.

    GPIO.RISING            -- pin 전압이 "LOW"에서 "HIGH"로 변경될 때 interrupt 호출.

 

한편 시스템에서 발생하는 모든 event를 관리하는 event handler 프로그램이 별도의 thread에서 실행되고 있는데, "add_event_detect( )" 함수로 event를 등록하면 event handler에 그 event가 등록이 된다. event handler는 등록된 event에 대해서 실제로 event가 발생했는지를 지속적으로 확인하고, event가 발생한 경우에는 event를 등록한 프로그램으로 통지하고, 지정된 작업을 수행하게 되는 것이다.  

 


 

25.7.2.2    push button 연결 및 회로 설명

 

여기서는 push button Raspberry Pi에 연결하고, button을 누르면 화면에 button을 눌렀다는 메시지를 출력하는 사례를 만들어 보도록 할 것이다.

 

먼저 다음 회로도와 같이 Raspberry Pi push button과 연결하는 작업을 한다. 먼저 breadboard push button을 좌측 IC와 우측 IC에 걸쳐서 동일한 선을 행으로 설치한다. button의 한 선을 pin 6(GND)에 연결하고, 반대편 선을 pin 11에 연결한다.  


그림 25‑19 push button 연결 및 회로

 

여기서 회로에 전류를 흐르게 할 때는 Raspberry Pi pin 1에서 공급되는 공식적인 전원을 사용하지 않고 회로에 연결된 pin 11에서 나오는 출력을 전원으로 이용할 것이다.

 

pin에서 전원 출력이 나오게 하는 방법에는 두 가지가 있는데, 하나는 프로그램에서 해당 pin "HIGH"로 출력하는 방법이고, 다른 하나는 해당 pin pull-up resistor를 사용하는 방법이다.


 

여기서 우리의 목적은 해당 pin에 출력하는 것이 아니라 pin에서 입력되는 신호를 처리하는 것이므로, 해당 pin pull-up resistor를 사용하여 출력을 만드는 방법을 사용할 것이다. pin pull-up resistor를 설정하면, button을 누르지 않은 상태에서 pin의 기본적인 전압은 "HIGH" 상태이며, button을 누르면 전류가 흘러서 pin 6(GND)로 연결되므로, pin 11에 가해지는 전압이 해제되어 "LOW" 상태가 되는 것이다.

 

여기서 한가지 기억할 것은 GPIO의 각 pin에는 pull-up resistor pull-down resistor이 있으며, 이들을 선택적으로 사용할 수 있다는 것이다.

 

저항의 의미는 다음과 같다.

    pull-up resistor을 사용하면 해당 pin에 전압을 걸어서 "HIGH" 상태가 되도록 한다.

    pull-down resistor을 사용하면 해당 pin에 전압이 낮은 "LOW" 상태가 되도록 한다.  


 

25.7.2.3    falling 방식의 push button 입력 처리하기

 

여기서는 falling 방식으로 push button 입력을 처리하는 방법을 사용한다. 이를 위해 pin의 입력을 지속적으로 읽어서 상태가 변경되었는지를 확인하고, button을 누른 것으로 확인된 경우에는 지정된 작업을 처리하도록 할 것이다.

 

프로그램 개발언어는 Python 3를 사용하고, GPIO 처리를 위해서 <RPi.GPIO> library를 사용한다. Python 3 IDLE를 시작하고, 아래와 같은 Python 프로그램을 작성하여 "button_falling.py" 파일에 저장한다.

 

import RPi.GPIO as GPIO

import time

 

GPIO.setmode( GPIO.BOARD)

GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)

 

request_count = int(raw_input("Enter Button Press Count ->"))

button_count = 0

 

while True :

           button_input = GPIO.input(11)

 

           if   button_input == False :

               button_count = button_count + 1

               print("Button Pressed ->%d"  %(button_count ) )

               time.sleep(1)

 

               if  button_count >= request_count :

                      break

 

GPIO.cleanup()

print ("Button Press Ended")

 


 

위의 프로그램의 내용을 좀 살펴보면 다음과 같다.

    프로그램에서 <RPi.GPIO> library 기능을 사용할 수 있도록 "RPi.GPIO" import한다.

    프로그램에서 시간에 대한 처리를 하기 위해서 "time" import하고 있다.

    "setmode( )" 함수를 이용해서 pin 번호체계를 BOARD 체계로 설정한다.

    "setup( )" 함수를 사용하여 11 pin input으로 설정하면서, parameter "pull_up_down=GPIO.PUD_UP"를 이용하여 해당 pin에 대해서 pull_up 저항을 활성화한다. 즉 해당 pin에 대해서 기본 전압을 "HIGH" 상태로 설정하는 것이다.

    "raw_input( )" 함수로 button을 누르는 최대 회수를 입력 받는다.

    "input( )" 함수를 사용하여 button에서 들어오는 값을 읽는다. 입력 값이 "True"이면 button이 눌러지지 않은 상태이고, "False" 이면 button을 누른 것이다.

    button이 눌러지면 화면에 메시지를 출력하고, button이 눌러진 회수가 사전에 입력한 회수보다 많으면 button 입력처리를 더 이상 하지 않도록 한다.

    모든 처리가 완료되면, "cleanup( )" 함수를 사용하여 GPIO를 처음 상태로 초기화한다.

 

Terminal 화면에서 "sudo" 명령으로 다음과 같이 프로그램을 실행한다. 그러면 button을 누르는 최대 회수를 입력하게 되고, 다음에는 button을 누를 때마다 화면에 메시지가 출력될 것이다

 

sudo  python  button_falling.py


 


 

25.7.2.4    interrupt 방식의 push button 입력 처리하기

 

여기서는 interrupt 방식으로 push button 입력을 처리하는 방법을 사용한다. 이를 위해 pin의 입력 상태가 변경되었는지를 자동으로 탐지하는 기능을 사용하고, button을 누른 것으로 확인된 경우에는 지정된 작업을 처리하도록 할 것이다.

 

프로그램 개발언어는 Python 3를 사용하고, GPIO 처리를 위해서 <RPi.GPIO> library를 사용한다. Python 3 IDLE를 시작하고, 아래와 같은 Python 프로그램을 작성하여 "button_event.py" 파일에 저장한다.

 

import RPi.GPIO as GPIO

import time

 

GPIO.setmode( GPIO.BOARD)

GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)

 

request_count = int(raw_input("Enter Button Press Count ->"))

button_count = 0

 

def  button_press_rtn(channel) :

    button_count = button_count + 1

     print("Button Pressed ->%d"  %(button_count ) )

    time.sleep(1)

 

GPIO.add_event_detect(11, GPIO.FALLING, callback=button_press_rtn)

 

while True :

    time.sleep(1)

    if  button_count >= request_count :

break

 

GPIO.cleanup()

print ("Button Press Ended")

 


 

위의 프로그램의 내용을 좀 살펴보면 다음과 같다.

    프로그램에서 <RPi.GPIO> library 기능을 사용할 수 있도록 "RPi.GPIO" import한다.

    프로그램에서 시간에 대한 처리를 하기 위해서 "time" import하고 있다.

    "setmode( )" 함수를 이용해서 pin 번호체계를 BOARD 체계로 설정한다

    "setup( )" 함수를 사용하여 11 pininput으로 설정하면서, parameter "pull_up_down=GPIO.PUD_UP" 를 이용하여 해당 pin에 대해서 pull_up 저항을 활성화한다. 즉 해당 pin에 대해서 기본 전압을 "HIGH" 상태로 설정하는 것이다.

    "raw_input( )" 함수로 button을 누르는 최대 회수를 입력 받는다.

    "button_press_rtn" 함수를 정의하여 button이 눌러지면 수행할 작업을 지정한다.

    "add_event_detect( )" 함수를 사용하여 interrupt가 발생하는 조건과 interrupt가 발생했을 때 처리할 작업을 지정한다. 여기서 "GPIO.FALLING"을 지정했으므로 pin의 전압이 "HIGH"에서 "LOW"로 변경되는 경우에 interrupt가 발생할 것이다.   

    button이 눌러지면 "button_press_rtn" 함수가 실행되어 화면에 메시지를 출력한다.

    "while" 문으로 프로그램 종료될 때까지 지속적으로 대기하고, button이 눌러진 회수가 사전에 입력한 회수보다 많으면 대기 상태를 중단한다.

    모든 처리가 완료되면, "cleanup( )" 함수를 사용하여 GPIO를 처음 상태로 초기화한다.

 


 

Terminal 화면에서 "sudo" 명령으로 다음과 같이 프로그램을 실행한다. 그러면 button을 누르는 최대 회수를 입력하게 되고, 다음에는 button을 누를 때마다 화면에 메시지가 출력될 것이다.

 

sudo  python  button_event.py


 


 

Leave a Reply