프로젝트들/메타버스게임

20221013 메타버스 5. Raspberry IR Receiver

Choi Jaekuk 2022. 10. 13. 11:36

Github : https://github.com/cjk09083/meta

 

GitHub - cjk09083/meta: 메타버스 게임 [Flutter(iOS), Arduino]

메타버스 게임 [Flutter(iOS), Arduino]. Contribute to cjk09083/meta development by creating an account on GitHub.

github.com

 

프로젝트 진행 도중 Arduino대신 Raspberry를 이용하여 셋탑박스를 개발하기로 변경하였다.

 

이에 따라 리모콘 신호를 받아오던 KY-022 IR Recevier 모듈을 Raspberry 3 b+ 모델에서 사용 가능 한지 테스트 하였다.

 

테스트를 위한 회로 구성은 다음과 같다.

Raspberry 와 KY-022 연결 회로

 

Arduino 테스트때와 동일하게 VCC(5V)와 GND를 연결해주고 SIG선은 12(GPIO18)번 PIN에 연결해주었다.

 

그 후 다음 사이트를 참조하여 Python 코드를 작성후 신호를 테스트 하였다.

https://www.thegeekpub.com/wiki/sensor-wiki-ky-022-infrared-sensor/

 

Sensor Wiki: KY-022 Infrared Sensor

This sensor wiki entry covers the KY-022 infrared sensor with technical specs, pinouts, and code samples for the Arduino and Raspberry Pi.

www.thegeekpub.com

 

신호 테스트를 통해 리모콘의 방향키와 OK 버튼의 int code 값을 기록하였고 이를 DIct 형태로 만들었다.

KEYMAP = {
    1526924029 : 'top',
    1526940349 : 'left',
    1526932189 : 'center',
    1526972989 : 'right',
    1526956669 : 'bottom',
    }

그후 버튼을 통해 code값이 들어오면 KEYMAP을 매칭시켜 명령어를 확인하도록 하였다.

code = on_ir_receive(PIN)
if code:
    try:
        key = KEYMAP[code]
    except KeyError:
        key = "ERROR"
    print(str(hex(code)),"(",str(code),")",key)

 

이후 다시 리모콘 신호를 테스트하여 명령어가 잘 인식되는지 확인하였다.

리모콘 신호 확인 결과

 

확인결과 KEYMAP에 지정되어 있는 신호는 해당 명령어로, 없는 신호는 ERROR로 잘 판별되었다.

 

 

 

전체코드

import RPi.GPIO as GPIO
from time import time

PIN = 12

KEYMAP = {
    1526924029 : 'top',
    1526940349 : 'left',
    1526932189 : 'center',
    1526972989 : 'right',
    1526956669 : 'bottom',
    }

def setup():
    GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location
    GPIO.setup(PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

def binary_aquire(pin, duration):
    # aquires data as quickly as possible
    t0 = time()
    results = []
    while (time() - t0) < duration:
        results.append(GPIO.input(pin))
    return results

def on_ir_receive(pinNo, bouncetime=150):
    # when edge detect is called (which requires less CPU than constant
    # data acquisition), we acquire data as quickly as possible
    data = binary_aquire(pinNo, bouncetime/1000.0)
    # print(len(data))
    if len(data) < bouncetime:
        return
    rate = len(data) / (bouncetime / 1000.0)
    pulses = []
    i_break = 0
    # detect run lengths using the acquisition rate to turn the times in to microseconds
    for i in range(1, len(data)):
        if (data[i] != data[i-1]) or (i == len(data)-1):
            pulses.append((data[i-1], int((i-i_break)/rate*1e6)))
            i_break = i
    # decode ( < 1 ms "1" pulse is a 1, > 1 ms "1" pulse is a 1, longer than 2 ms pulse is something else)
    # does not decode channel, which may be a piece of the information after the long 1 pulse in the middle
    outbin = ""
    for val, us in pulses:
        if val != 1:
            continue
        if outbin and us > 2000:
            break
        elif us < 1000:
            outbin += "0"
        elif 1000 < us < 2000:
            outbin += "1"
    try:
        return int(outbin, 2)
    except ValueError:
    # probably an empty code
        return None

def destroy():
    GPIO.cleanup()
    
if __name__ == "__main__":
    setup()
    try:
        print("Starting IR Listener")
        while True:
            #print("Waiting for signal")
            GPIO.wait_for_edge(PIN, GPIO.FALLING)
            code = on_ir_receive(PIN)
            if code:
                try:
                    key = KEYMAP[code]
                except KeyError:
                    key = "ERROR"
                print(str(hex(code)),"(",str(code),")",key)
            #else:
            #    print("Invalid code")
    except KeyboardInterrupt as e:
        print(e)
        pass
    except RuntimeError as e:
        # this gets thrown when control C gets pressed
        # because wait_for_edge doesn't properly pass this on
        print(e)
        pass
    print("Quitting")
    destroy()