wordpress 开发列表网,贵州灵溪seo整站优化,wordpress自动刷新2次,如何做网站美工本文简单介绍一下如何使用ESP32连接xbox的蓝牙手柄#xff0c;使之变成一个相对通用的遥控器。
硬件平台
XBOX ONE S手柄蓝牙版
EPS32-DOWN-V3#xff0c;需要注意Xbox One S手柄使用经典蓝牙#xff0c;ESP32有较多型号仅支持BLE#xff0c;需要选一个支持经典蓝牙BLE的…本文简单介绍一下如何使用ESP32连接xbox的蓝牙手柄使之变成一个相对通用的遥控器。
硬件平台
XBOX ONE S手柄蓝牙版
EPS32-DOWN-V3需要注意Xbox One S手柄使用经典蓝牙ESP32有较多型号仅支持BLE需要选一个支持经典蓝牙BLE的型号BLE模式下扫描不到Xbox 手柄
软件平台
使用espidf 5.2.1版本进行开发。
实现原理
输入解析
espidf打开example内的esp_hid_host工程基于这个demo进行修改工程首先将BLE关闭修改为经典蓝牙的配置。 例程配置为了扫描到的最后一个HID设备将被连接这个地方可以自己改一下识别蓝牙名称进行选择连接避免有多个设备的时候连到别的设备上去连接部分内容不多此处略过。 正常连接后主要需要处理的就是键值上报后的解析解析可以参考下面的结构体
#pragma pack(1)
typedef struct
{uint16_t left_x; /// 左0~右65535uint16_t left_y; /// 上0~下65535uint16_t right_x; /// 左0~右65535uint16_t right_y; /// 上0~下65535uint16_t triger_left; /// 不按0~按到底1023uint16_t triger_right; /// 不按0~按到底1023uint8_t key_dir; /// 1~8 垂直向上为1顺时针旋转递增不按为0struct{uint8_t key_a : 1;uint8_t key_b : 1;uint8_t key_x : 1;uint8_t key_y : 1;uint8_t key_lb : 1;uint8_t key_rb : 1;uint8_t key_page : 1;uint8_t key_menu : 1;};uint8_t reserve;
} xbox_message_t;
typedef struct
{uint8_t cap_level : 2; /// 电量等级 0马上没电1低电量2中电量2满电量uint8_t mode : 2; /// 供电模式 0 USB供电 1 干电池供电(或者非官方的充电电池) 2 官方可充电电池供电uint8_t charging : 1; /// 正在充电(官方电池)uint8_t error : 1; /// 出现异常uint8_t reserve : 1; /// 保留字段uint8_t online : 1; /// 在线始终是1
} xbox_bat_info_t;/* XBOX RUMBLE TYPE */
#define XBOX_RUMBLE_NONE 0x00
#define XBOX_RUMBLE_WEAK 0x01
#define XBOX_RUMBLE_STRONG 0x02
#define XBOX_RUMBLE_MAIN (XBOX_RUMBLE_WEAK | XBOX_RUMBLE_STRONG)
#define XBOX_RUMBLE_RIGHT 0x04
#define XBOX_RUMBLE_LEFT 0x08
#define XBOX_RUMBLE_TRIGGERS (XBOX_RUMBLE_RIGHT | XBOX_RUMBLE_LEFT)
#define XBOX_RUMBLE_ALL 0xfftypedef struct
{uint8_t enable; /// XBOX RUMBLE TYPE操作电机的maskuint8_t magnitude_left; /// 左triger电机的力度 0~100uint8_t magnitude_right; /// 右triger电机的力度 0~100uint8_t magnitude_strong; /// 机身高频电机的力度(位于右侧手柄)0~100uint8_t magnitude_weak; /// 机身低频电机的力度(位于左侧手柄)0~100uint8_t pulse_sustain_10ms; /// 振动使能时间单位msuint8_t pulse_release_10ms; /// 振动失能时间单位msuint8_t loop_count; /// 循环次数-1 周期为振动使能时间振动失能时间
} xbox_motor_cmd_t;
#pragma pack()
传过来的键值如代码所示在输入回调内进行解析并打印整个设备共有四个report其中三个为输入一个为输出(也就是控制振动)。输入的看下面代码即可 case ESP_HIDH_INPUT_EVENT:{/* HID消息 */if (param-input.report_id 1){xbox_message_t *message (xbox_message_t *)param-input.data;ESP_LOGI(TAG, map_index: %d, param-input.map_index);ESP_LOGI(TAG, left_x:%d left_y:%d right_x:%d right_y:%d triger_l:%d triger_r:%d,message-left_x, message-left_y,message-right_x, message-right_y,message-triger_left, message-triger_right);ESP_LOGI(TAG, key_dir:%d key_a:%d key_b:%d key_x:%d key_y:%d key_lb:%d key_rb:%d key_page:%d key_menu:%d,message-key_dir, message-key_a,message-key_b, message-key_x,message-key_y, message-key_lb, message-key_rb, message-key_page, message-key_menu);/* 利用键值测试振动控制 */xbox_motor_test(param-input.dev, *message);}/* 西瓜键 */else if (param-input.report_id 2){ESP_LOGI(TAG, key_xbox:%d, param-input.data[0]);}/* 电池信息 */if (param-input.report_id 4){xbox_bat_info_t *info (xbox_bat_info_t *)param-input.data;ESP_LOGI(TAG, cap_level:%d mode:%d charging:%d error:%d online:%d,info-cap_level, info-mode, info-charging, info-error, info-online);}break;}
由于手上只有一款手柄对于其他手柄的键值解析可能有偏差这个要实际测试确定但大概的结构是这样的。
输出控制
代码中还利用键值做了振动控制的测试测试相关代码如下
void xbox_motor_test(esp_hidh_dev_t *dev, xbox_message_t message)
{static xbox_message_t message_last {0};xbox_motor_cmd_t xbox_motor_cmd {0};if (message_last.key_x ! message.key_x){if (message.key_x){xbox_motor_cmd.enable XBOX_RUMBLE_LEFT; // 仅修改左triger按键xbox_motor_cmd.magnitude_left message.left_x / 700; // 根据左摇杆键值调整力度xbox_motor_cmd.pulse_sustain_10ms 20; // 200ms}esp_hidh_dev_output_set(dev, 0, 3, (uint8_t *)xbox_motor_cmd, sizeof(xbox_motor_cmd));}if (message_last.key_b ! message.key_b){if (message.key_b){xbox_motor_cmd.enable XBOX_RUMBLE_RIGHT;xbox_motor_cmd.magnitude_right message.left_x / 700;xbox_motor_cmd.pulse_sustain_10ms 20;}esp_hidh_dev_output_set(dev, 0, 3, (uint8_t *)xbox_motor_cmd, sizeof(xbox_motor_cmd));}if (message_last.key_a ! message.key_a){if (message.key_a){xbox_motor_cmd.enable XBOX_RUMBLE_WEAK;xbox_motor_cmd.magnitude_weak message.left_x / 700;xbox_motor_cmd.pulse_sustain_10ms 20;}esp_hidh_dev_output_set(dev, 0, 3, (uint8_t *)xbox_motor_cmd, sizeof(xbox_motor_cmd));}if (message_last.key_y ! message.key_y){if (message.key_y){xbox_motor_cmd.enable XBOX_RUMBLE_STRONG;xbox_motor_cmd.magnitude_strong message.left_x / 700;xbox_motor_cmd.pulse_sustain_10ms 20;}esp_hidh_dev_output_set(dev, 0, 3, (uint8_t *)xbox_motor_cmd, sizeof(xbox_motor_cmd));}if (message_last.key_lb ! message.key_lb){if (message.key_lb){xbox_motor_cmd.enable XBOX_RUMBLE_MAIN;xbox_motor_cmd.magnitude_strong message.left_x / 700;xbox_motor_cmd.magnitude_weak message.left_x / 700;xbox_motor_cmd.pulse_sustain_10ms 20;}esp_hidh_dev_output_set(dev, 0, 3, (uint8_t *)xbox_motor_cmd, sizeof(xbox_motor_cmd));}if (message_last.key_rb ! message.key_rb){if (message.key_rb){xbox_motor_cmd.enable XBOX_RUMBLE_TRIGGERS;xbox_motor_cmd.magnitude_left message.left_x / 700;xbox_motor_cmd.magnitude_right message.left_x / 700;xbox_motor_cmd.pulse_sustain_10ms 20;}esp_hidh_dev_output_set(dev, 0, 3, (uint8_t *)xbox_motor_cmd, sizeof(xbox_motor_cmd));}if (message_last.key_page ! message.key_page){if (message.key_page){xbox_motor_cmd.enable XBOX_RUMBLE_ALL;xbox_motor_cmd.magnitude_left message.left_x / 700;xbox_motor_cmd.pulse_sustain_10ms 20;xbox_motor_cmd.pulse_release_10ms 10;xbox_motor_cmd.loop_count 1; // 振两次}esp_hidh_dev_output_set(dev, 0, 3, (uint8_t *)xbox_motor_cmd, sizeof(xbox_motor_cmd));}memcpy(message_last, message, sizeof(message_last));
} 关于振动电机控制的部分看控制的结构体就能看明白了代码里面利用不同的键按下事件测试了不同的震动效果。
实际测试
I (12119) ESP_HID_GAP: BT GAP MODE_CHG_EVT mode:2
I (12139) XBOX : ec:83:50:de:44:5a OPEN:
BDA:ec:83:50:de:44:5a, Status: OK, Connected: YES, Handle: 0, Usage: GAMEPAD
Name: , Manufacturer: , Serial Number:
PID: 0x02e0, VID: 0x045e, VERSION: 0x0903
Report Map Length: 306GENERIC INPUT REPORT, ID: 4, Length: 1GENERIC OUTPUT REPORT, ID: 3, Length: 8GENERIC INPUT REPORT, ID: 2, Length: 1GAMEPAD INPUT REPORT, ID: 1, Length: 15
I (14919) XBOX : cap_level:2 mode:1 charging:0 error:0 online:1
I (23219) XBOX : left_x:34757 left_y:33821 right_x:32584 right_y:34502 triger_l:0 triger_r:0
I (23219) XBOX : key_dir:0 key_a:1 key_b:0 key_x:0 key_y:0 key_lb:0 key_rb:0 key_page:0 key_menu:0
I (23219) XBOX : left_x:34757 left_y:33821 right_x:32584 right_y:34502 triger_l:0 triger_r:0
I (23229) XBOX : key_dir:0 key_a:1 key_b:0 key_x:0 key_y:0 key_lb:0 key_rb:0 key_page:0 key_menu:0
I (23239) XBOX : left_x:34757 left_y:33821 right_x:32584 right_y:34502 triger_l:0 triger_r:0
I (23249) XBOX : key_dir:0 key_a:1 key_b:0 key_x:0 key_y:0 key_lb:0 key_rb:0 key_page:0 key_menu:0
I (23339) XBOX : left_x:34757 left_y:33821 right_x:32584 right_y:34502 triger_l:0 triger_r:0
I (23339) XBOX : key_dir:0 key_a:0 key_b:0 key_x:0 key_y:0 key_lb:0 key_rb:0 key_page:0 key_menu:0
I (23339) XBOX : left_x:34757 left_y:33821 right_x:32584 right_y:34502 triger_l:0 triger_r:0
I (23349) XBOX : key_dir:0 key_a:0 key_b:0 key_x:0 key_y:0 key_lb:0 key_rb:0 key_page:0 key_menu:0
I (23359) XBOX : left_x:34757 left_y:33821 right_x:32584 right_y:34502 triger_l:0 triger_r:0
I (23369) XBOX : key_dir:0 key_a:0 key_b:0 key_x:0 key_y:0 key_lb:0 key_rb:0 key_page:0 key_menu:0
可以看打印的LOG可以看到可以正常的进行xbox的连接并输出对应的键值情况。需要注意的是xbox手柄输入是事件型的也就是只有键值改变的时候才会进行键值的上报这样可以极大的降低功耗。电量信息则是定时上报。并且在对应的按键按下时可以接收到震动反馈。
结语
到此整个工程的实现就已经结束了。对于不同型号的xbox手柄(比如精英手柄)可以使用类似的方式进行解析不过需要自己进行额外键值的分析和解析或许可以参考下面的代码。
https://github.com/atar-axis/xpadneo/blob/master/hid-xpadneo/src/hid-xpadneo.c