마음 속 하늘은 항상 맑음~!

아두이노로 XInput호환 조이스틱 구성하기. 본문

카테고리 없음

아두이노로 XInput호환 조이스틱 구성하기.

파르셀수스 2021. 7. 4. 10:53

 이전에 만들었단 게임패드를 개선한 것으로 보통 조이스틱으로는 무한으로 방향이 눌리는 현상이 있어서 보통 조이스틱이 아닌 XInput 호환 조이패드를 만들었다.

 

 Pro Micro보드에 먼저 XInput호환이 되는 하드웨어 설정파일을 설치해야 한다. 이는 아두이노 설치 폴더에 있는걸로 그냥 압축을 풀면 쉽게 설치할 수 있다.

 XInput 보드 : https://github.com/dmadison/ArduinoXInput_AVR

 저기 보드를 설정할 수 있는 파일들을 압축을 아두이노 하드웨어 폴더에 설치하면 된다.

 

 그리고 XInput라는 아두이노 라이브러리가 추가적으로 필요하다. 이게 실제적으로 아두이노가 XInput를 구현하는데 사용하는 라이브러리이다. 이는 아두이노 라이브러리 매니져에서 XInput로 검색하면 쉽게 나온다.

 

 업로드에는 주의가 필요한다. 처음 한번은 문제없이 업로드된다. 하지만 다음 펌웨어 업데이트 부터는 GND와 RESET핀을 2번 빠르게 연결해줘야 한다. 그렇게 빠른 속도는 아니고 RESET핀을 연결할 때 Pro Micro의 LED가 깜박하는데 2번 꺼졌다켜졌다 하도록 빠르게 연결해주면 된다.

 펌웨어 "업로딩..." 메시지가 나타나면 얼른 이 RESET을 빠르게 2번 연결해주면 펌웨어 업로딩이 문제없이 진행된다.

 

 이전의 조이스틱 코드에서 약간 변경을 해서 XInput를 다시 구성하면 다음과 같다.

#include <XInput.h>
#include <wiring_private.h>

#define MAX_BUTTON 8
#define FASTADC

#define XCV 511
#define YCV 511
#define AX_MIN -511
#define AX_MAX 511

#define NOISE_X 28
#define NOISE_Y 28


int jbutton[MAX_BUTTON]={5,6,7,8,14,16,4,9};
int xbv, ybv;

void setup() {
  for (int index = 0; index < MAX_BUTTON; index++) {
    pinMode(jbutton[index], INPUT_PULLUP);    
  }

#ifdef FASTADC
 // set prescale to 16
 sbi(ADCSRA,ADPS2);
 cbi(ADCSRA,ADPS1);
 cbi(ADCSRA,ADPS0);
#endif

  xbv=analogRead(A0);
  ybv=analogRead(A1);

  XInput.setAutoSend(false);
  XInput.setJoystickRange(0, 1023);
  XInput.begin();

}

/*
BUTTON_LOGO
BUTTON_A
BUTTON_B
BUTTON_X
BUTTON_Y
BUTTON_LB
BUTTON_RB
BUTTON_BACK
BUTTON_START
BUTTON_L3
BUTTON_R3

DPAD_UP
DPAD_DOWN
DPAD_LEFT
DPAD_RIGHT
*/

int ButtonMap[MAX_BUTTON] = {BUTTON_A,   BUTTON_B,   BUTTON_X,     BUTTON_Y,
                             BUTTON_LB,  BUTTON_RB,  BUTTON_BACK,  BUTTON_START};
int lastButtonState[MAX_BUTTON] = {0,0,0,0,0,0,0,0};
int xv, yv;

void loop() {
  xv=analogRead(A0);
  yv=analogRead(A1);

  if((xv>XCV-NOISE_X) && (xv<XCV+NOISE_X))
    xv=XCV;

  yv=1023-yv;
  if((yv>YCV-NOISE_Y) && (yv<YCV+NOISE_Y))
    yv=YCV;

  XInput.setJoystickX(JOY_LEFT, xv);
  XInput.setJoystickY(JOY_LEFT, yv);

  // Read pin values
  for (int index = 0; index < MAX_BUTTON; index++)
  {
    int currentButtonState = !digitalRead(jbutton[index]);
    if (currentButtonState != lastButtonState[index])
    {
      XInput.setButton(ButtonMap[index], currentButtonState);
      lastButtonState[index] = currentButtonState;
    }
  }
  XInput.send();
}

 특별히 크게 다른 점은 없고 Y축의 값이 반전으로 나와서 ADC 최대값 1023에서 현재값을 빼주는 방식으로 반전 상태를 만들었다.

 

 버튼은 기능맵핑이 필요해서 추가적인 배열이 들어갔고, 중립일 때 값이 흔들리는 것을 방지하기 위해 약간의 검사값을 넣었다.

 

 이렇게 다 구성하면 엑박 360과 호환되는 컨트롤러를 에뮬레이션하는 기능으로 만들 수 있다. 단, 자체 인증을 위한 기능이 없어서 완벽한 호환성을 보장하기는 어렵다. 하지만 간단한 XInput입력으론 문제없이 쓸 수 있다.

 

 자신의 조이스틱 구성이 문제가 없는지 디버깅을 하고 싶다면 "XInput" 보드를 선택하지 말고 "Pro Micro"로 설정해서 아두이노의 시리얼 모니터로 확인해보면 각각 값들이 시리얼 모니터에 나타나니 먼저 "XInput"보드 설정으로 펌웨어를 업로드 하지 말고 먼저 디버깅을 충분히 하고 "XInput" 보드 설정으로 펌웨어 업데이트를 하는 것을 추천한다.