행복한 하루

라즈베리파이 제로 프로젝트(13) – Pioneer600 모듈 (키 버튼 입력받기) 본문

RaspberryPi/Raspberry Pi Zero

라즈베리파이 제로 프로젝트(13) – Pioneer600 모듈 (키 버튼 입력받기)

변화의 물결 2021. 2. 14. 23:34

 

 

안녕하세요.

 

  세 번째 시간으로 버튼에 대해서 알아보도록 하겠습니다. Pioneer600에 보면 작은 조이스틱이 하나 있는데 회로를 보면 PCF8574 IC에 붙어 있습니다. KEY A, KEY B, KEY C, KEY D 4방향으로 인식할 수 있게 되어 있습니다.

  그런데 여기서 하나 더 CTR 핀이 있는데 이것이 가운데를 꾹 누르면 입력을 받을 수 있게 되어 있습니다. 이것을 가지고 이용해보도록 하겠습니다.

 

 

1. 회로 확인

- 조이스틱 부분의 회로는 다음과 같이 연결되어 있습니다. 여기서 CTR에 연결해서 Key Press를 처리해 보도록 하겠습니다.

 - CTR은 라즈베리파이 제로 P28 핀과 연결되어 있습니다.

 

조이스틱 연결회로

 

- 여기서 주의할 점은 핀 번호입니다. wiringPi와 BCM 라이브러리의 핀 번호가 다르므로 프로그래밍할 때 어떤 핀인지 확인이 필요합니다. P28은 wPi 경우 28번으로 BCM, Python 인 경우 20번으로 설정하셔야 합니다.

 

Pioneer600 컨넥터

2. 소스 확인

  - 공통적인 부분을 설명하고 조금 특별한 부분에 관해서 설명하도록 하겠습니다.

  - 우선 핀을 입력으로 상태로 바꾸고, 입력 상태를 풀업으로 합니다. (입력이 없을 때는 HIGH로 하기 위해서입니다) 그리고 입력을 받아들이는 방식에 있어서 핀을 항상 기다리는 Polling 방식과 신호가 들어오는 것을 감시해 처리하는 인터럽트 방식으로 나누어집니다.

 

2.1 Polling 방식

  - 입력을 받기 위해서 입력 핀을 계속 검사합니다. 그리고 입력이 들어오면 그에 맞게 처리하는 방식입니다.

 

1) BCM2835 사용 (key.c)

  - bcm2835_gpio_fsel(KEY, BCM2835_GPIO_FSEL_INPT);  

  bcm2835_gpio_set_pud(KEY, BCM2835_GPIO_PUD_UP);

  - 20번 핀을 입력으로 설정하고 풀업으로 설정합니다. 핀마다 여러 기능을 할 수 있기 때문에 된다면 데이터 시트를 한번 보는 것도 도움이 되지 않을까 합니다.  라이브러리에서 미리 만들어 놓은 설정값입니다.

 

typedef enum

{

    BCM2835_GPIO_FSEL_INPT  = 0b000,   // Input

    BCM2835_GPIO_FSEL_OUTP  = 0b001,   // Output

    BCM2835_GPIO_FSEL_ALT0  = 0b100,   // Alternate function 0

    BCM2835_GPIO_FSEL_ALT1  = 0b101,   // Alternate function 1

    BCM2835_GPIO_FSEL_ALT2  = 0b110,   // Alternate function 2

    BCM2835_GPIO_FSEL_ALT3  = 0b111,   // Alternate function 3

    BCM2835_GPIO_FSEL_ALT4  = 0b011,   // Alternate function 4

    BCM2835_GPIO_FSEL_ALT5  = 0b010,   // Alternate function 5

    BCM2835_GPIO_FSEL_MASK  = 0b111  //Function select bits mask

} bcm2835FunctionSelect;

 

- bcm2835_gpio_lev(KEY) == 0  입력 핀에서 신호를 읽어서 비교를 합니다.

 

  

#include <bcm2835.h>
#include <stdio.h>

char KEY = 20;
unsigned char i;
int main(int argc, char **argv)
{
        if (!bcm2835_init())return 1;
        bcm2835_gpio_fsel(KEY, BCM2835_GPIO_FSEL_INPT);
        bcm2835_gpio_set_pud(KEY, BCM2835_GPIO_PUD_UP);
        printf("Key Test Program!!!!\n");
        while (1)
        {
                if(bcm2835_gpio_lev(KEY) == 0)
                {
                        printf ("KEY PRESS\n") ;
                while(bcm2835_gpio_lev(KEY) == 0)
                                bcm2835_delay(100);
                }
                bcm2835_delay(100);
        }
        bcm2835_close();
        return 0;
}
 

 

2) Python 소스 (key.py)

  - 특별한 것은 없이 GPIO.setup(KEY,GPIO.IN,GPIO.PUD_UP) 으로 핀 설정을 하고  GPIO.input(KEY) == 0: 에서 입력 핀 상태를 지속적으로 감시합니다. 

  

#!/usr/bin/python
# -*- coding:utf-8 -*-
import RPi.GPIO as GPIO
import time

KEY = 20

GPIO.setmode(GPIO.BCM)
GPIO.setup(KEY,GPIO.IN,GPIO.PUD_UP)
print("Key Test Program")
while True:
        time.sleep(0.05)
        if GPIO.input(KEY) == 0:
                print("KEY PRESS")
                while GPIO.input(KEY) == 0:
                        time.sleep(0.01) 

 

3) WiringPi 소스(key.c)

  - 입력 키 번호가 28로 되어 있고, 코드는 파이썬과 유사하게 되어 있습니다. 

#include <stdio.h>
#include<wiringPi.h>

char KEY = 28;

int main()
{
        if (wiringPiSetup() < 0)return 1 ;
        pinMode (KEY,INPUT);
        pullUpDnControl(KEY, PUD_UP);
    printf("Key Test Program!!!\n");
        while(1)
        {
                if (digitalRead(KEY) == 0)
        {
                        printf ("KEY PRESS\n") ;
                while(digitalRead(KEY) == 0)
                                delay(100);
                }
                delay(100);
        }
}

  

2.2 인터럽트 방식

1) BCM2835 사용 (event.c)

  - 인터럽트처럼 보이지 않지만, 핀에 이벤트가 발생하는 것을 감지하는 입력신호로 하는 것이 아니라서 인터럽트 쪽에 넣어 보았습니다.

  - 조금 다른 부분이 bcm2835_gpio_len(KEY); 함수가 추가되어 있습니다. 신호 레벨이 LOW 바뀌면 감지하는 기능을 활성화합니다.

  - bcm2835_gpio_eds(KEY)로 여러 가지 이벤트가 들어온 것을 확인하는 함수입니다.

  - bcm2835_gpio_set_eds(KEY); 이벤트를 다시 상태로 돌려줍니다.  

#include <bcm2835.h>
#include <stdio.h>

#define KEY  20
int main(int argc, char **argv)
{
        if (!bcm2835_init())return 1;
        bcm2835_gpio_fsel(KEY, BCM2835_GPIO_FSEL_INPT);
        bcm2835_gpio_set_pud(KEY, BCM2835_GPIO_PUD_UP);
        bcm2835_gpio_len(KEY);
        printf("Key Test Program!!!!\n");
        while (1)
        {
                if(bcm2835_gpio_eds(KEY))
                {
                        bcm2835_gpio_set_eds(KEY);
                        printf("EVENT DETECT\n");
                }
                bcm2835_delay(500);
        }
        bcm2835_close();
        return 0;
}

 

2) Python 소스 (Interrupt.py)

  - GPIO.add_event_detect(KEY,GPIO.FALLING,MyInterrupt,200)  콜백(Callback) 함수를 호출해서

키 입력 이벤트가 발생하면 특정 함수로 이동하게 되어 있습니다. 첫 번째 인자는 핀 번호이고, 두 번째는 LOW로 되었을 때 감지하겠다는 것이고, 세 번째는 콜백 함수로 이벤트 발생하면 호출되면 실행될 함수명, 네 번째 200은 bouncing time 혹은 채터링 방지를 위한 시간입니다. 

#!/usr/bin/python
# -*- coding:utf-8 -*-
import RPi.GPIO as GPIO
import time

KEY = 20

def MyInterrupt(KEY):
        print("KEY PRESS")
GPIO.setmode(GPIO.BCM)
GPIO.setup(KEY,GPIO.IN,GPIO.PUD_UP)
GPIO.add_event_detect(KEY,GPIO.FALLING,MyInterrupt,200)

while True:
        time.sleep(1)

  

3) WiringPi 소스 (Interrupt.c)

  - 입력 키 번호가 28로 되어 있고, wiringPiISR(button,INT_EDGE_RISING,&myInterrupt) 인터럽트 핀을 설정하고 파이썬과 같이 채터링 혹은 여러 번 눌리는 것을 방지해주려고 간단하게 플래그로 처리를 해주고 있습니다.  

#include <stdio.h>
#include <wiringPi.h>

#define button 28
char flag = 0;
void myInterrupt()
{
        flag ++;
}

int main()
{
        if(wiringPiSetup() < 0)return 1;
        pinMode(button,INPUT);
        pullUpDnControl(button,PUD_UP);
        if(wiringPiISR(button,INT_EDGE_RISING,&myInterrupt) < 0)
        {
                printf("Unable to setup ISR \n");
        }
        printf("Interrupt test program\n");
        while(1)
        {
                if(flag)
                {
                        while(digitalRead(button) ==0);
                        printf("button press\n");
                        flag = 0;
                }
        }
}  

 

3. 프로그램 실행

1) bcm2835와 wiringPi

  - bcm2835와 wiringPi는 c언어 보다 보니 Makefile로 컴파일을 실행하면 됩니다.

  - make clean && make로 컴파일과 실행파일을 만들면 됩니다.

 

  예)

  pi@raspberrypi:~/Pioneer600/KEY/wiringPi $ make clean && make

  pi@raspberrypi:~/Pioneer600/KEY/wiringPi $ ./key

 

wiringPi key 실행

 

2) python

  - sudo python3 key.py 실행시키고 키를 누르면 KEY PRESS 문자가 출력되는 것을 확인할 수 있습니다.

이후에 key.py 대신 Interrupt.py로 바꿔 실행해보시면 됩니다.

 

python key 실행

  

  - 키가 생각처럼 바로바로 눌리지 않았습니다. 4방향까지 누를 수 있는 조이스틱 형태이다 보니 조금 세게 중앙을 눌러주어야 이벤트가 발생합니다.

 

감사합니다.

 

 

<참고 사이트>

1. Pioneer600

https://www.waveshare.com/wiki/Pioneer600

2. bcm2835 GPIO register access

https://www.airspayce.com/mikem/bcm2835/group__gpio.html

3. [ICbanQ 전자 지식공유]

https://icbanq.tistory.com/entry/라즈베리파이-GPIO에-대하여2

4. Python 기반 GPIO활용 LED 제어

https://m.blog.naver.com/rpghksdlaehk/220984302784  

 

 

“쿠팡 파트너스 활동을 통해 일정액의 수수료를 받을 수 있음"

Comments