20221013 메타버스 5. Raspberry IR Receiver
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+ 모델에서 사용 가능 한지 테스트 하였다.
테스트를 위한 회로 구성은 다음과 같다.
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 형태로 만들었다.
그후 버튼을 통해 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()