更新V1.4,并增加玩车说明。

This commit is contained in:
myperworld committed 2026-02-05 09:36:10 +08:00
1 parent 1a74f5d323
commit e866a74c9c
13 files changed
+109 -74647

No files matched your search

@@ -119,4 +119,13 @@ ActionStep step_forward[] = {
RobotAction action_step_forward = CREATE_ACTION("action_step_forward", step_forward);
#endif
#endif
// 增加rgb效果
// if (remoteData.btnShare && !last_btnShare && robot_enabled && !isExecutingAction) {
// isExecutingAction = true; // 标记开始执行动作
// currentAction = &action_say_hello; // 指定执行的动作
// stepStartTime = millis(); // 记录第一步开始时间
// currentStepIndex = 0; // 从第一步开始
// }
@@ -6,7 +6,6 @@ char serial_buf[32]; // 存储串口接收数据
uint8_t buf_idx = 0; // 缓冲区索引
// -------------------------- 串口接收处理函数--------------------------
// 修改 serialReceiveProcess 函数以支持两种结束符
void serialReceiveProcess() {
while (Serial.available()) {
char c = Serial.read();
@@ -16,6 +15,8 @@ void serialReceiveProcess() {
// 判断是哪种指令格式
if (strchr(serial_buf, '=') != NULL) {
parseSingleParam(serial_buf); // 处理原格式指令
} else if (strstr(serial_buf, "MODE:") != NULL) {
parseSetRobotMode(serial_buf); // 通过串口设置小车模式
} else if (strstr(serial_buf, "S1:") != NULL && strstr(serial_buf, "S2:") != NULL) {
parseServoAngleCommand(serial_buf); // 处理舵机角度控制指令 S1:90,S2:90;
} else if (strstr(serial_buf, "DX:") != NULL && strstr(serial_buf, "DY:") != NULL) {
@@ -68,6 +69,16 @@ void parseCameraDeviationCommand(char* cmd) {
}
// 添加踢球模式设置函数
void parseSetRobotMode(char* cmd) {
char* modestr = strstr(cmd, "MODE:");
if (modestr == NULL) {
Serial.println("小车模式指令格式错误!请使用\"MODE:模式;\"格式(例如\"MODE:1\")");
return;
}
int mode_id = atoi(modestr + 5); // "MODE:"占5个字符,跳过它们取数值
setRobotMode(mode_id);
}
// -------------------------- 参数解析函数(原逻辑不变)--------------------------
void parseSingleParam(char* cmd) {
@@ -177,6 +188,9 @@ void parseSingleParam(char* cmd) {
} else if (strcmp(param_name, "pitch_adjust") == 0) {
pitch_adjust = param_val;
} else if (strcmp(param_name, "wrobot_height") == 0) {
wrobot_height = param_val;
// } else if (strcmp(param_name, "step_joyx") == 0) {
// step_joyx = param_val;
@@ -20,6 +20,8 @@ extern PIDController pid_yaw_align;
extern float pid_cam_p;
extern float pid_cam_d;
extern int wrobot_height;
extern int chase_ball_s2;
extern int kick_back_s2;
extern int ob_ball_dy;
@@ -69,6 +71,8 @@ void parseServoAngleCommand(char* cmd);
void parseCameraDeviationCommand(char* cmd);
// 踢球相关函数声明
void setRobotMode(int mode_id);
void parseSetRobotMode(char* cmd);
void kick_ball_loop();
void SetKickMode(String mode);
@@ -137,6 +137,8 @@ float original_leg_height_base = leg_height_base ;
#define SERVO0_SPEED 400 // 舵机1速度,不能太快,否则影响其他动作平衡
#define SERVO1_SPEED 400 // 舵机2速度
int wrobot_height_origin = 40;
int wrobot_height = 9999;
int left_height;
int right_height;
float leg_position_add = 0; // roll轴平衡控制量
@@ -252,7 +254,7 @@ float dragon_joyx_factor = 0.8f;
typedef struct
{
int height = 30;
int height = wrobot_height_origin;// 40
int roll;
int jump = 0; // 0=不跳跃 1=跳跃
int joyy;
@@ -421,7 +423,8 @@ void setup()
void loop()
{
serialReceiveProcess(); // 调用串口接收函数(核心修改)
serialReceiveProcess(); // 调用串口接收函数(核心修改)
handleLEDBlink(); // 处理LED闪烁
process_xbox_notif(); // 处理xbox手柄通知
@@ -831,6 +834,9 @@ void leg_loop()
leg_position_add = pid_roll_angle(lpf_roll(roll_angle));
// 左后腿默认等于 wrobot.height
if(wrobot_height != 9999){
wrobot.height = wrobot_height;
}
left_height = wrobot.height;
right_height = wrobot.height;
LegHeightDiff = 0; // 初始化 roll 角度补偿值
@@ -858,7 +864,7 @@ void leg_loop()
// id[0] 正面看右手,id[1] 正面看左手
// 2047是舵机中间位置,8.4是系数,32是默认高度,最高80,最低32
// const int LEG_HEIGHT_BASE 这值越小,机身越高,实测范围 0(最高),52(最低)
Position[0] = 2047 + 8.4 * (left_height - leg_height_base ) - leg_position_add;
Position[0] = 2047 + 8.4 * (left_height - leg_height_base ) + leg_position_add;
Position[1] = 2047 - 8.4 * (right_height - leg_height_base ) - leg_position_add;
// 舵机1:限制在 SERVO0_MIN(下限)~ SERVO0_MAX(上限),和原逻辑一致
@@ -1057,7 +1063,7 @@ void resetZeroPoint() {
* xbox 手柄控制
* ========================================*/
void processControllerData(const XboxControllerNotificationParser& remoteData) {
// String str = String(xboxController.xboxNotif.btnY) + "," + // Y键
// String(xboxController.xboxNotif.btnX) + "," + // X键
// String(xboxController.xboxNotif.btnB) + "," + // B键
@@ -1295,9 +1301,9 @@ void processControllerData(const XboxControllerNotificationParser& remoteData) {
}
// 追逐并转向踢会球模式 @@@@@@
if (remoteData.btnY && !last_btnY && robot_enabled && trace_mode) {
if(kick_mode != "kick_back_mode"){
SetKickMode("kick_back_mode");
}else if(kick_mode == "kick_back_mode"){
if(kick_mode != "kick_run_mode"){
SetKickMode("kick_run_mode");
}else if(kick_mode == "kick_run_mode"){
SetKickMode("kick_place_mode");
}
}
@@ -1568,37 +1574,28 @@ void obstacle_cancel()
void kick_ball_loop(){
if(trace_mode){
if (kick_mode == "kick_run_mode") { // 运动追踪模式
setLEDColor(CRGB::Blue);
}else if(kick_mode == "kick_back_mode") { // 追逐并转向踢会球模式
if(kick_mode == "kick_run_mode") { // 追逐并转向踢会球模式
setLEDColor(CRGB::Red);
}else if(kick_mode == "kick_place_mode"){ // 原地踢球模式
}else if(kick_mode == "kick_place_mode"){ // 原地踢球模式(守门模式)
setLEDColor(CRGB::Green);
}
}else{
// 非踢球模式下,动态调整高度
if(wrobot.joyy == 0 ){
if(current_s1 > 90){ // 打开挡板
leg_height_base = 30.0f;
}else if(current_s1 > 10){
leg_height_base = constrain(current_s1, 15.0f, 30.0f);
}else{
leg_height_base = original_leg_height_base;
}
}
}
// else{
// // 非踢球模式下,动态调整高度
// if(wrobot.joyy == 0 ){
// if(current_s1 > 90){ // 打开挡板
// leg_height_base = 30.0f;
// }else if(current_s1 > 10){
// leg_height_base = constrain(current_s1, 15.0f, 30.0f);
// }else{
// leg_height_base = original_leg_height_base;
// }
// }
// }
}
// 通过偏差deviation 控制摄像头上下左右运动
void kick_ball_main(int dx, int dy) {
// 在运动踢球时,踢好球,需要有一段停止前进时间
// if(kick_over_count > 0 && kick_over_count < kick_over_count_max){
// kick_over_count ++;
// }else{
// kick_over_count = 0;
// }
// Serial.println("kick_over_count: " + String(kick_over_count) );
// 不是追踪模式
if(!trace_mode){
@@ -1641,7 +1638,7 @@ void kick_ball_main(int dx, int dy) {
if(kick_mode == "kick_run_mode"){
cam_aim_ball(dy); // 相机瞄准
if(kick_over_count){ // 踢好球之后阶段
if(kick_over_count){ // 踢好球之后阶段,转到对齐偏航角
if(kick_over_count > 0 && kick_over_count < kick_over_count_max){
kick_over_count ++;
@@ -1727,7 +1724,7 @@ void kick_ball_core(){
void ready_kick_ball(){
if( abs(current_s1 - ready_kick_angel) > 5){
setFrontierServoAngles(ready_kick_angel); // 打开挡板,收到后方
leg_height_base = ready_leg_height_base; // 下降
// leg_height_base = ready_leg_height_base; // 下降
}
}
@@ -1840,17 +1837,65 @@ void cancel_kick_mode(){
setLEDColor(CRGB::Black);
leg_height_base = original_leg_height_base; // 上升
setFrontierServoAngles(0); // s1 前档舵
}
void SetKickMode(String mode){
trace_mode = true;
kick_mode = mode;
yaw_to_joyx = 9999;
// 进入kick_back_mode时,记录当前偏航角作为基准0度
if(mode == "kick_run_mode" || mode == "kick_back_mode"){
// 进入kick_run_mode时,记录当前偏航角作为基准0度
if(mode == "kick_run_mode"){
kick_yaw_zero = mpu6050.getAngleZ(); // 读取当前偏航角(Z轴角度)作为基准
pid_yaw_align.error_prev = 0.0f; // 重置偏航对齐PID状态
}
}
void setRobotMode(int mode_id){
if(mode_id == 11){ // 站起来
robot_enabled = true;
sitting_down = 0; // 清除坐下动作标记
stand_up_count ++; // 站立标志位
pid_trace_joyx.P = 0.25; // 追踪模式
// wrobot_height = 40;
Serial.println("站起来");
}else if(mode_id == 10){ // 坐下
robot_enabled = false;
sitting_down = 1; // 标记开始坐下动作保存当前的角度零点
pid_trace_joyx.P = 0.5; // 追踪模式
sms_sts.EnableTorque(ID[0], 0); // 第一个舵机失能 0 失能,1 使能
sms_sts.EnableTorque(ID[1], 0); // 第二个舵机失能
cancel_kick_mode();
Serial.println("坐下");
}else if(mode_id == 12){ // 还原
roll_adjust = original_roll_adjust;
pitch_adjust = 0.0f;
leg_height_base = original_leg_height_base;
pitch_zeropoint = original_pitch_zeropoint;
Serial.println("还原");
}else if(mode_id == 20){ // 取消踢球
cancel_kick_mode();
Serial.println("取消踢球");
}else if(mode_id == 21){ // 守门模式
SetKickMode("kick_place_mode");
Serial.println("守门模式");
}else if(mode_id == 22){ // 运动踢球模式
SetKickMode("kick_run_mode");
Serial.println("运动踢球模式");
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
Binary file not shown.
Binary file not shown.