프로그래밍 언어/파이썬

파이썬으로 조이스틱 제어하기 (USB HID)

원원 2024. 5. 12. 23:18

안녕하세요. 오늘은 조이스틱을 사용해보겠습니다. 
조이스틱은 아래의 제품을 사용했습니다.
https://www.devicemart.co.kr/goods/view?no=1377049


해당제품은 라즈베리와 호환되는 제품인것같고 일반PC에서 사용하려면 USB 데이터를 받고나서 처리를 해줘야 합니다. USB HID 통신을 사용하고 파이썬을 이용했습니다.
제품에 대한 데이터시트를 못찾아서 프로토콜 분석기를 이용해서 키가 눌렸을때의 데이터를 얻었습니다.

해당 디바이스에서 아무것도 눌리지 않았을때 주기적으로 01 80 80 7F 7F 0F 00 00이 옵니다.

왼쪽 방향키를 누르는경우 01 80 80 00 7F 0F 00 00이 옵니다. 그래서 해당 데이터일때 왼쪽으로 움직여주면 됩니다.


모든 키의 데이터를 적으면 아래와 같습니다.

key_values = {
    "default": "01 80 80 7E 7F 0F 00 00",
    "LEFT_BTN": "01 80 80 7E 7F 0F 01 00",
    "RIGHT_BTN": "01 80 80 7E 7F 0F 02 00",
    "LEFT_ARROW": "01 80 80 00 7F 0F 00 00",
    "RIGHT_ARROW": "01 80 80 FF 7F 0F 00 00",
    "UP_ARROW": "01 80 80 7F 00 0F 00 00",
    "DOWN_ARROW": "01 80 80 7F FF 0F 00 00",
    "SELECT_KEY": "01 80 80 7F 7F 0F 10 00",
    "START_KEY": "01 80 80 7F 7F 0F 20 00",
    "X_KEY": "01 80 80 7F 7F 1F 00 00",
    "Y_KEY": "01 80 80 7F 7F 8F 00 00",
    "A_KEY": "01 80 80 7F 7F 2F 00 00",
    "B_KEY": "01 80 80 7F 7F 4F 00 00"
}


파이썬으로 구현해야 할 기능은 크게 2가지입니다.
1. USB HID 통신하기
2. 키 입력하기


1. USB HID 통신하기
HID 라이브러리를 이용했습니다. 간단히 함수를 호출해서 HID open -> read 하면 됩니다.

2. 키 입력하기
pyautogui를 이용했습니다. 이것도 함수를 이용하면 키 입력이 됩니다.


- 소스코드

import hid
import time
import pyautogui

VID = 0x0810
PID = 0xE501

key_values = {
    "default": "01 80 80 7E 7F 0F 00 00",
    "LEFT_BTN": "01 80 80 7E 7F 0F 01 00",
    "RIGHT_BTN": "01 80 80 7E 7F 0F 02 00",
    "LEFT_ARROW": "01 80 80 00 7F 0F 00 00",
    "RIGHT_ARROW": "01 80 80 FF 7F 0F 00 00",
    "UP_ARROW": "01 80 80 7F 00 0F 00 00",
    "DOWN_ARROW": "01 80 80 7F FF 0F 00 00",
    "SELECT_KEY": "01 80 80 7F 7F 0F 10 00",
    "START_KEY": "01 80 80 7F 7F 0F 20 00",
    "X_KEY": "01 80 80 7F 7F 1F 00 00",
    "Y_KEY": "01 80 80 7F 7F 8F 00 00",
    "A_KEY": "01 80 80 7F 7F 2F 00 00",
    "B_KEY": "01 80 80 7F 7F 4F 00 00"
}

def main():
    print("MAIN START")

    try:
        dev = hid.device()
        dev.open(VID,PID)
        print("device open")
        
        while True:
            data = dev.read(64)
            hex_numbers = " ".join([f"{num:02X}" for num in data])
            #print(hex_numbers)

            if hex_numbers == key_values["LEFT_ARROW"]:
                pyautogui.write(['left'])
            elif hex_numbers == key_values["RIGHT_ARROW"]:
                pyautogui.write(['right'])
            elif hex_numbers == key_values["DOWN_ARROW"]:
                pyautogui.write(['down'])
            elif hex_numbers == key_values["UP_ARROW"]:
                pyautogui.write(['up'])
            elif hex_numbers == key_values["X_KEY"]:
                pyautogui.write('x')
            elif hex_numbers == key_values["Y_KEY"]:
                pyautogui.write('y')
            elif hex_numbers == key_values["A_KEY"]:
                pyautogui.write('a')
            elif hex_numbers == key_values["B_KEY"]:
                pyautogui.write('b')
            elif hex_numbers == key_values["SELECT_KEY"]:
                break
            print("Running ... ")
            time.sleep(0.1)
        print("END")
    except Exception as e:
        print("error : ",e)
        return

main()

프로그램을 실행하면 무한루프를 돌고 SELECT 버튼을 클릭하면 프로그램 종료로 했습니다.
#print(hex_numbers) 주석을 해제하면 read하는 데이터가 보입니다.
time.sleep(0.1) 0.1초 딜레이는 딜레이가 없는경우에 여러번 키가 움직이는 경우가 있어서 넣어놨습니다.


소스코드 github
https://github.com/yhunterr/joystic_python