蓝牙 Arduino 游戏手柄

Posted

技术标签:

【中文标题】蓝牙 Arduino 游戏手柄【英文标题】:Bluetooth Arduino Gamepad 【发布时间】:2018-08-18 16:46:50 【问题描述】:

我正在尝试使用 RN-42XV 蓝牙芯片和 arduino 制作一个带有 2 个模拟摇杆和 16 个按钮的自定义蓝牙控制器,我可以在 android 和我的 windows pc 上使用它。到目前为止,我已经成功地将 arduino leonardo 编码为具有 2 个模拟摇杆和 16 个按钮的游戏手柄,但我无法让 arduino 与我的 RN-42XV 蓝牙一起使用。 RN-42XV 连接到我的电脑并显示为带有 2 个模拟摇杆和 16 个按钮的游戏手柄,但是当我按下 arduino 上的按钮时,它不会注册到 RN-42。我正在使用的代码如下,请帮助。

#include "Joystick2.h"
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#define BLUETOOTH_SERIAL_RATE 9600

//Buttons defined according to https://www.w3.org/TR/gamepad/
#define BUTTON_0        0
#define BUTTON_1        1
#define BUTTON_2        2
#define BUTTON_3        3
#define SHOULDER_LEFT   4
#define SHOULDER_RIGHT  5
#define TRIGGER_LEFT    6
#define TRIGGER_RIGHT   7
#define START           8
#define SELECT          9
#define THUMB_LEFT      10
#define THUMB_RIGHT     11
#define HAT_UP          12
#define HAT_DOWN        13
#define HAT_LEFT        14
#define HAT_RIGHT       15
#define HOME            16

#define x1   A1
#define y1  A0
#define x2      A3 // Pin 20
#define y2      A2 // Pin 19



void setup() 

Serial.begin(BLUETOOTH_SERIAL_RATE);
  delay(500);
  // Initialize Button Pins - comment out  any unused
//   pinMode(0, INPUT_PULLUP); 
//   pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
//   pinMode(14, INPUT_PULLUP);
//   pinMode(15, INPUT_PULLUP);
//   pinMode(16, INPUT_PULLUP);
//   pinMode(18, INPUT_PULLUP);
//   pinMode(19, INPUT_PULLUP);
//   pinMode(20, INPUT_PULLUP);
//   pinMode(21, INPUT_PULLUP);

  // Initialize Joystick Library
  Joystick[0].begin();

  Joystick[1].begin();



//Edit button to pin mapping according to your hardware - use -1 if unused
int pinToButtonMap[20][2] =  BUTTON_0,        9,
                              BUTTON_1,        8,
                              BUTTON_2,        7,
                              BUTTON_3,        6,
                              SHOULDER_LEFT,   4,
                              SHOULDER_RIGHT,  5,
                              TRIGGER_LEFT,    -1,
                              TRIGGER_RIGHT,   -1,
                              START,           3,
                              SELECT,          2,
                              THUMB_LEFT,      10,
                              THUMB_RIGHT,     -1,
                              HAT_UP,          -1,
                              THUMB_LEFT,      -1,
                              HAT_UP,          -1,
                              HAT_DOWN,        -1,
                              HAT_LEFT,        -1,
                              HAT_RIGHT,       -1,
                              HOME,            -1;

int btnState[20][2] =  BUTTON_0, 0,
                              BUTTON_1, 0,
                              BUTTON_2, 0,
                              BUTTON_3, 0,
                              SHOULDER_LEFT, 0,
                              SHOULDER_RIGHT, 0,
                              TRIGGER_LEFT, 0,
                              TRIGGER_RIGHT, 0,
                              START, 0,
                              SELECT, 0,
                              THUMB_LEFT, 0,
                              THUMB_RIGHT, 0,
                              HAT_UP, 0,
                              THUMB_LEFT, 0,
                              HAT_UP, 0,
                              HAT_DOWN, 0,
                              HAT_LEFT, 0,
                              HAT_RIGHT, 0,
                              HOME, 0;

void loop() 
  for (int i = 0; i < 20; i++)  
    if(pinToButtonMap[i][1] > -1) 
      int currentState = !digitalRead(pinToButtonMap[i][1]);
      if (currentState != btnState[i][1])  // Detect button state change
        Joystick[0].setButton(i, currentState);
        Joystick[1].setButton(i, currentState);
        btnState[i][1] = currentState;
      
    
  
  Joystick[0].setXAxis(analogRead(x1));
  Joystick[0].setYAxis(analogRead(y1));
  Joystick[1].setXAxis(analogRead(x2));
  Joystick[1].setYAxis(analogRead(y2));


   delay(50);


void currentState(uint32_t btnState, int8_t x1, int8_t y1, int8_t x2, int8_t 
y2)

  //write the header part for RN42
  Serial.write((uint8_t)0xFD); //start byte
  Serial.write((uint8_t)0x06); //length of the descriptor
  //gampad positions and buttons
  //on a gamepad there typically is two analog joysticks one is typically 
used to
  //indicate x/y position and one is for z/rotation. 
  Serial.write((uint8_t)x1 & 0xFF); //value between -127 to 127 indicating 
the x postition
  Serial.write((uint8_t)y1 & 0xFF); //value between -127 to 127 indicating 
the y postition
  Serial.write((uint8_t)x2 & 0xFF); //value between -127 to 127 indicating 
the z postition
  Serial.write((uint8_t)y2 & 0xFF); //value between -127 to 127 indicating 
the rotation postition
  //one bit for each button pressed there can be a total of 16 buttons one 
byte in each
  //set the bit to show a button pressed and clear the bit to indicate not 
pressed
  uint8_t btnState1 = btnState & 0xFF;
  uint8_t btnState2 = (btnState >> 8) & 0xFF;
  Serial.write((uint8_t)btnState1); 
  Serial.write((uint8_t)btnState2);

【问题讨论】:

【参考方案1】:

您与 RN-42XV 用于 HID 操纵杆报告的报告描述符格式不匹配。蓝牙数据模块命令参考和高级信息用户指南中描述了支持的 HID 报告的格式:

http://ww1.microchip.com/downloads/en/DeviceDoc/bluetooth_cr_UG-v1.0r.pdf

第 5.3.3 节描述了操纵杆数据的原始报告格式:

字节 0:0xFD(指示要遵循的原始 HID 报告) 字节 1:0x06(报告长度) 字节 2:按钮 0-7 的状态 字节 3:按钮 8-15 的状态 字节 4:轴 X1 字节 5:轴 Y1 字节 6:轴 X2 字节 7:轴 Y2

你的 currentState 方法正在写:

字节 0:0xFD(好) 字节 1:0x06(好) 字节 2:x1 & 0xFF(应该是按钮 0-7) 字节 3:y1 和 0xFF(应该是按钮 8-15) 字节 4:x2 & 0xFF(应为 X1 轴) 字节 5:y2 & 0xFF(应为 Y1 轴) 字节 6:btnState & 0xFF(应为 X2 轴) 字节 7: (btnState >> 8) & 0xFF (应该是 Axis Y2)

我认为如果你重新安排在轴状态之前写按钮状态的方法,它会起作用。

【讨论】:

以上是关于蓝牙 Arduino 游戏手柄的主要内容,如果未能解决你的问题,请参考以下文章

Arduino 操纵杆到网络游戏手柄

如何将 Xinput 添加到游戏手柄 arduino 项目?

HID 游戏手柄报告描述符问题

arduino 操纵杆库,不要停止操纵杆

蜗牛蓝牙板可以连接arduino吗

使用arduino ps2无线遥控手柄实现 遥控小车