增加手柄震动功能,右扳机按下时,触发震动,连接时震动,断开时震动,跳跃落地时震动

This commit is contained in:
myperworld committed 2025-10-17 15:37:41 +08:00
1 parent e33a6b894d
commit 0ef2bb0d7f
6 files changed
+439 -251

No files matched your search

+112 -21
View File
@@ -1,46 +1,137 @@
/* ---------------------------------
* 蓝牙手柄(Xbox)模块
* 包含:蓝牙实体、状态变量、连接处理函数
* 不包含:手柄数据解析逻辑(processControllerData)
------------------------------------- */
#ifndef XBOX_BLUETOOTH_H
#define XBOX_BLUETOOTH_H
#include <Arduino.h>
#include <XboxSeriesXControllerESP32_asukiaaa.hpp> // Xbox手柄库
#include <XboxSeriesXControllerESP32_asukiaaa.hpp>
/************ Xbox手柄全局实体 *************/
// 连接目标手柄的MAC地址(保持原地址不变)
/************ 全局实体与状态变量 *************/
XboxSeriesXControllerESP32_asukiaaa::Core xboxController("0a:27:12:5c:71:79");
XboxSeriesXHIDReportBuilder_asukiaaa::ReportBase repo;
// 跟踪手柄连接状态(用于检测首次连接和断开)
bool wasConnected = 0; // 是否链接
// 震动状态机(关键:记录当前处于震动的哪个阶段)
enum VibrateState {
VIBRATE_OFF, // 未震动
VIBRATE_STARTED, // 已发送开启指令,等待关闭
VIBRATE_TRIGGER // 扳机键震动状态(单独管理)
};
VibrateState vibrateState = VIBRATE_OFF;
unsigned long vibrateStartMs = 0; // 震动开始的时间戳
const unsigned long KEY_VIBRATE_DURATION = 200; // 按键震动持续时间
const unsigned long TRIGGER_VIBRATE_DURATION = 300; // 扳机震动持续时间
/************ 外部函数声明 *************/
// 声明主文件中的数据处理函数(在主文件中实现)
extern void processControllerData(const XboxControllerNotificationParser& data);
/************ 蓝牙手柄核心函数 *************/
/************ 核心函数 *************/
// 初始化蓝牙手柄(供主文件setup()调用)
void xboxControllerInit() {
// 启动蓝牙连接
xboxController.begin();
vibrateState = VIBRATE_OFF; // 初始化状态
}
// 处理蓝牙手柄通知(循环调用,保持连接并接收数据)
void process_xbox_notif() {
xboxController.onLoop(); // 维持蓝牙连接状态
// 非阻塞震动状态更新(必须在主循环中调用)
void updateXboxVibration() {
unsigned long currentMs = millis();
if (xboxController.isConnected()) {
if (xboxController.isWaitingForFirstNotification()) {
// 可添加调试信息(如"等待手柄数据...")
} else {
// 接收数据后,调用主文件的解析函数
processControllerData(xboxController.xboxNotif);
// 处理按键震动的"开启→等待→关闭"流程
if (vibrateState == VIBRATE_STARTED) {
// 检查是否达到震动持续时间
if (currentMs - vibrateStartMs >= KEY_VIBRATE_DURATION) {
// 执行原函数中delay后的关闭逻辑
repo.v.power.center = 0;
repo.v.power.shake = 0;
xboxController.writeHIDReport(repo);
vibrateState = VIBRATE_OFF; // 回到未震动状态
}
}
// 处理扳机键震动的关闭逻辑
else if (vibrateState == VIBRATE_TRIGGER) {
if (currentMs - vibrateStartMs >= TRIGGER_VIBRATE_DURATION) {
repo.v.power.center = 0;
repo.v.power.shake = 0;
xboxController.writeHIDReport(repo);
vibrateState = VIBRATE_OFF;
}
} else {
// 可添加调试信息(如"手柄未连接")
}
}
#endif // XBOX_BLUETOOTH_H
// 按键震动(完整复现原逻辑的非阻塞版本)
void XboxKeyVibration() {
// 若正在震动,先重置状态(避免重复触发导致混乱)
if (vibrateState != VIBRATE_OFF) {
repo.v.power.center = 0;
repo.v.power.shake = 0;
xboxController.writeHIDReport(repo);
}
// 执行原函数中delay前的开启逻辑
repo.setAllOff();
repo.v.select.center = true;
repo.v.select.left = true;
repo.v.select.right = true;
repo.v.select.shake = true;
repo.v.power.center = 20; // 30% power
repo.v.power.shake = 20;
repo.v.timeActive = 10; // x/100 second
xboxController.writeHIDReport(repo);
// 记录开始时间,进入"等待关闭"状态(替代delay(250))
vibrateState = VIBRATE_STARTED;
vibrateStartMs = millis();
}
// 扳机键震动(同样保留完整时序)
void XboxtrigRTVibration() {
static uint16_t TrigMax = XboxControllerNotificationParser::maxTrig;
uint8_t power = (uint8_t)((float)xboxController.xboxNotif.trigRT / TrigMax * 100) * 0.5;
// 若扳机键松开,直接关闭震动
if (power == 0) {
repo.v.power.center = 0;
repo.v.power.shake = 0;
xboxController.writeHIDReport(repo);
vibrateState = VIBRATE_OFF;
return;
}
// 执行开启震动逻辑
repo.setAllOff();
repo.v.select.center = true;
repo.v.select.left = true;
repo.v.select.right = true;
repo.v.select.shake = true;
repo.v.power.center = power;
repo.v.power.shake = power;
repo.v.timeActive = 10;
xboxController.writeHIDReport(repo);
// 进入扳机震动状态,等待关闭
vibrateState = VIBRATE_TRIGGER;
vibrateStartMs = millis();
}
void process_xbox_notif() {
xboxController.onLoop();
if (xboxController.isConnected() && !xboxController.isWaitingForFirstNotification()) {
if(!wasConnected){ // 原来未链接,现在链接成功
XboxKeyVibration();
wasConnected = 1;
}
processControllerData(xboxController.xboxNotif);
}else{
if(wasConnected){ // 原来是链接成功的,说明断了
XboxKeyVibration();
wasConnected = 0;
}
}
}
#endif // XBOX_BLUETOOTH_H
+9 -2
View File
@@ -292,10 +292,10 @@ void setup()
void loop()
{
handleLEDBlink(); // 处理LED闪烁
process_xbox_notif(); // 处理xbox手柄通知
updateXboxVibration(); // 手柄震动状态
bat_check(); // 电压检测
delayMicroseconds(1500);
@@ -485,6 +485,8 @@ void lqr_balance_loop()
// Serial.print(",jump_flag:");
// Serial.println(jump_flag); // 120左右
XboxKeyVibration(); // 落地手柄震动
if( jump_flag ){ // 落地点作为新的位移零点
resetZeroPoint();
}
@@ -709,7 +711,7 @@ void yaw_loop()
wrobot.height = lpf_height(wrobot.height);
// 增加rgb效果
if(abs(wrobot.joyx) > 30){
if(abs(wrobot.joyx) > 50){
if(!isBlinking){ // 防止重复启动闪烁
isBlinking = true;
blinkCount = 0; // 重置闪烁计数
@@ -911,6 +913,11 @@ void processControllerData(const XboxControllerNotificationParser& remoteData) {
}
last_btnA = remoteData.btnA;
// trigRT 根据扳机键按压力度调整振动力度
if (xboxController.xboxNotif.trigRT > 0) {
XboxtrigRTVibration();
}
}
// 执行连续动作的函数