330 lines
15 KiB
Markdown
330 lines
15 KiB
Markdown
# 项目架构分析报告:Basic_Framework_MC02 (RoboMaster 云台机器人)
|
||
|
||
## 概览
|
||
|
||
这是一个基于 **STM32H723** (Cortex-M7) 的 RoboMaster 竞赛机器人控制项目。项目采用 FreeRTOS 实时操作系统,目前配置为**单板控制整车**(`ONE_BOARD` 模式),代码组织呈分层架构。项目由 **湖南大学岳麓电气 (HNU YueLu EC)** 开发。
|
||
|
||
---
|
||
|
||
## 一、硬件与通信总览
|
||
|
||
| 资源 | 用途 |
|
||
|------|------|
|
||
| **FDCAN1/2/3** | 电机控制总线(DJI 电机、达妙电机等) |
|
||
| **USART1** | 板间通信 (BoardComm) |
|
||
| **USART5** | 遥控器 (DBUS/DR16) |
|
||
| **USART7** | VoFA 调试输出 |
|
||
| **USART10** | 视觉/上位机 (OpenCV 通信) |
|
||
| **SPI1/2** | BMI088 IMU 传感器、OLED |
|
||
| **I2C2** | 通用 I2C |
|
||
| **OCTOSPI2** | 外部 Flash (W25Qxx) |
|
||
| **TIM1/2/3/12** | PWM 输出、编码器输入、DWT 时钟基准 |
|
||
| **USB Device** | 虚拟串口 (CDC) |
|
||
| **ADC1** | 模拟量采集 |
|
||
| **GPIO** | 电源控制、激光器等 |
|
||
|
||
---
|
||
|
||
## 二、分层架构
|
||
|
||
项目采用 **4 层架构**:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ application/ 应用层 │
|
||
│ robot.c → robot_cmd → gimbal / chassis / shoot │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ modules/ 模块层 │
|
||
│ motor, imu, referee, remote, vision, algorithm, ... │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ bsp/ 板级支持包 │
|
||
│ can, usart, spi, iic, pwm, dwt, log, gpio │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ Drivers/ HAL 驱动层 (CubeMX 生成) │
|
||
│ STM32H7xx_HAL, CMSIS, FreeRTOS, USB, SEGGER RTT │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 三、启动与初始化流程
|
||
|
||
### 3.1 main() 启动序列
|
||
|
||
```
|
||
HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_DMA_Init()
|
||
→ MX_ADC1_Init() → MX_USB_DEVICE_Init() → MX_TIM/SPI/USART/UART/FDCAN/..._Init()
|
||
→ RobotInit() ← 唯一的用户初始化入口
|
||
→ while(1) {} ← 空循环,所有逻辑在 RTOS 任务中
|
||
```
|
||
|
||
### 3.2 RobotInit() 初始化链
|
||
|
||
```
|
||
RobotInit()
|
||
├── __disable_irq() // 关中断,保证初始化原子性
|
||
├── BSPInit()
|
||
│ ├── DWT_Init(480) // 时钟周期计数器 (CPU=480MHz)
|
||
│ └── BSPLogInit() // 日志系统(SEGGER RTT + 串口)
|
||
├── RobotCMDInit() // 核心命令任务初始化
|
||
│ ├── RemoteControlInit(&huart5) // 遥控器 (DBUS)
|
||
│ ├── PubRegister() x6 // 注册 6 个消息话题:
|
||
│ │ gimbal_cmd / gimbal_feed // 云台控制/反馈
|
||
│ │ shoot_cmd / shoot_feed // 发射控制/反馈
|
||
│ │ chassis_cmd / chassis_feed // 底盘控制/反馈
|
||
│ ├── PIDInit() x2 (yaw + pitch 跟踪PID) // 视觉跟踪 PID 初始化
|
||
│ ├── VisionKalmanFilterInit() // 视觉误差卡尔曼滤波器
|
||
│ ├── Vision_Uart_Init(&huart10) // 视觉串口通信
|
||
│ └── BoardCommInit(&huart1) // 板间通信
|
||
├── GimbalInit() // 云台电机初始化
|
||
│ ├── INS_Init() → BMI088 SPI 初始化 // IMU 惯导
|
||
│ ├── PubRegister("gimbal_feed") / SubRegister("gimbal_cmd")
|
||
│ ├── DJIMotorInit(GM6020) → yaw 电机 // Yaw: GM6020 直驱
|
||
│ └── DMMotorInit() → pitch 电机 // Pitch: 达妙电机
|
||
├── OSTaskInit() // 创建 RTOS 任务
|
||
│ ├── INS Task (1kHz, AboveNormal) // 姿态解算最高优先级
|
||
│ ├── Motor Task (1kHz, Normal) // 电机控制
|
||
│ ├── Daemon Task (100Hz, Normal) // 看门狗/蜂鸣器
|
||
│ ├── Robot Task (500Hz, Normal) // 机器人核心控制
|
||
│ └── DMMotorControlInit() // 达妙大电机初始化
|
||
└── __enable_irq() // 开中断
|
||
```
|
||
|
||
---
|
||
|
||
## 四、FreeRTOS 任务架构
|
||
|
||
| 任务 | 频率 | 优先级 | 功能 |
|
||
|------|------|--------|------|
|
||
| **INS Task** | 1kHz | AboveNormal | 阻塞读取 BMI088,进行四元数 EKF 姿态解算 |
|
||
| **Motor Task** | 1kHz | Normal | DJI/LK/HT 电机 PID 闭环计算与 CAN 发送 |
|
||
| **Robot Task** | 500Hz | Normal | 调用 `RobotTask()` 串联各应用层任务 |
|
||
| **Daemon Task** | 100Hz | Normal | 模块看门狗喂狗检查 + 蜂鸣器控制 |
|
||
|
||
---
|
||
|
||
## 五、消息中心 (Pub-Sub)
|
||
|
||
位于 `modules/message_center/`,这是应用层内部的核心通信机制:
|
||
|
||
- **发布者 (Publisher)**:以**话题名 (topic name)** 标识,通过**链表**管理订阅者
|
||
- **订阅者 (Subscriber)**:每个订阅者维护一个长度为 1 的 **FIFO 队列**
|
||
- 支持最多 **12 个话题**,话题名最长 **32 字符**
|
||
|
||
### 当前消息流:
|
||
|
||
```
|
||
robot_cmd (CMD) ──→ gimbal_cmd ──→ gimbal 应用
|
||
├── chassis_cmd → chassis 应用
|
||
└── shoot_cmd ──→ shoot 应用
|
||
|
||
gimbal ──→ gimbal_feed ──→ robot_cmd (CMD)
|
||
chassis ──→ chassis_feed ──→ robot_cmd (CMD)
|
||
shoot ──→ shoot_feed ──→ robot_cmd (CMD)
|
||
```
|
||
|
||
---
|
||
|
||
## 六、应用层模块
|
||
|
||
### 6.1 RobotCMD (`application/cmd/`) — 机器人大脑
|
||
|
||
核心决策模块,集成以下功能:
|
||
|
||
| 功能 | 说明 |
|
||
|------|------|
|
||
| **遥控器解析** | DBUS 协议,摇杆/开关/键鼠 |
|
||
| **视觉跟踪** | OpenCV 视觉数据 → 卡尔曼滤波 → PID 跟踪 → 云台角度控制 |
|
||
| **画圆模式** | 遥控器拨轮控制画圆轨迹跟踪 |
|
||
| **题号状态机** | 竞赛自动任务状态机,支持 6 种题号,含转向/搜索/跟踪子状态 |
|
||
| **急停处理** | 遥控器右侧开关拨下 → 所有电机零力输出 |
|
||
| **激光控制** | GPIO 控制激光笔开关 |
|
||
|
||
`RobotCMDTask()` 执行流程(500Hz):
|
||
|
||
```
|
||
读取底盘/发射/云台反馈消息 → 判断控制模式(手动/自动/视觉)
|
||
→ EmergencyHandler(急停检测) → 推送控制消息给各应用
|
||
```
|
||
|
||
**题号状态机** (YunTaiState):
|
||
|
||
```
|
||
YUNT_IDLE
|
||
→ NO1: 零力模式
|
||
→ NO2: 视觉跟踪 + 激光 (等待1.5s后开启激光)
|
||
→ NO3: 转向0度 → 视觉跟踪/搜索 → 激光 (3.5s后)
|
||
→ NO4_1: 转向-45度 → 视觉跟踪 + 前馈
|
||
→ NO4_3: 转向-45度 → 视觉跟踪 (error=60) + 画圆前馈
|
||
```
|
||
|
||
### 6.2 Gimbal (`application/gimbal/`) — 云台控制
|
||
|
||
- **Yaw 轴**:GM6020 (DJI 直驱电机),CAN1 ID=0x01,IMU 反馈替代电机编码器
|
||
- **Pitch 轴**:达妙电机 (DM Motor),CAN1 ID=0x06/0x16,IMU 反馈
|
||
- **控制模式**:
|
||
- `GIMBAL_ZERO_FORCE`:零力
|
||
- `GIMBAL_GYRO_MODE`:陀螺仪姿态闭环 (使用 IMU Pitch + YawTotalAngle)
|
||
- **特点**:角度/角速度反馈均来自 IMU(替代电机编码器),带有速度和电流前馈
|
||
|
||
### 6.3 Chassis (`application/chassis/`) — 底盘控制
|
||
|
||
- 麦克纳姆轮底盘 (Mecanum),4x GM6020 电机
|
||
- 运动学解算:正逆运动学,云台→底盘坐标系变换
|
||
- 支持裁判系统功率限制和超级电容管理
|
||
|
||
### 6.4 Shoot (`application/shoot/`) — 发射控制
|
||
|
||
- **摩擦轮**:2x M3508 (CAN2 ID=1,2),速度串联电流闭环
|
||
- **拨盘电机**:M2006 (CAN2 ID=3),多模式:
|
||
- `LOAD_STOP`:停止
|
||
- `LOAD_1_BULLET`:单发(角度闭环,加减角度 = ONE_BULLET_DELTA_ANGLE)
|
||
- `LOAD_3_BULLET`:三连发
|
||
- `LOAD_BURSTFIRE`:连发(速度闭环,可调射频)
|
||
- `LOAD_REVERSE`:反转
|
||
- **弹速模式**:15m/s / 18m/s / 30m/s
|
||
- 弹舱盖开关控制
|
||
|
||
---
|
||
|
||
## 七、模块层 (modules/)
|
||
|
||
| 分类 | 模块 | 功能 |
|
||
|------|------|------|
|
||
| **电机** | `dji_motor` | DJI GM6020/M3508/M2006 标准电机驱动,串级 PID (角度→速度→电流) |
|
||
| | `DMMotor` | 达妙电机 (DM Motor) 驱动 |
|
||
| | `LKmotor` (LK9025) | LK 电机驱动 |
|
||
| | `HTmotor` (HT04) | HT04 电机驱动 |
|
||
| | `step_motor` | 步进电机 (含 X_V2 变体) |
|
||
| | `servo_motor` | 舵机控制 |
|
||
| | `motor_task` | 电机控制统一调度 (`MotorControlTask`) |
|
||
| **姿态** | `imu/ins_task` | 惯导解算:四元数 EKF,BMI088 传感器 |
|
||
| | `imu/BMI088driver` | BMI088 SPI 底层读取 |
|
||
| | `imu/BMI088Middleware` | BMI088 数据换算 |
|
||
| **算法** | `controller` | 通用 PID 控制器(支持变积分、梯形积分、微分先行、输出滤波等改进) |
|
||
| | `kalman_filter` | 标准卡尔曼滤波器 + 自适应 (`UseAutoAdjustment`) |
|
||
| | `QuaternionEKF` | 四元数扩展卡尔曼滤波 |
|
||
| | `crc8/crc16` | CRC 校验 |
|
||
| | `user_lib` | 通用数学/工具函数 |
|
||
| **通信** | `remote/remote_control` | DJI DBUS 遥控器解析 (位域优化) |
|
||
| | `master_machine` | 视觉上位机通信 (SeaSky 协议) |
|
||
| | `referee` | 裁判系统 (RM Referee Protocol, UI 绘制) |
|
||
| | `can_comm` | CAN 通信抽象层(双板情况下的数据转发) |
|
||
| | `board_comm` | 板间通信(固定帧格式: 帧头 + 2x int32 + 2x float + 校验) |
|
||
| | `bluetooth/HC05` | HC05 蓝牙模块 |
|
||
| | `opencv` | OpenCV 视觉数据处理 |
|
||
| **辅助** | `message_center` | Pub-Sub 消息中间件(伪发布订阅,仅做应用间隔离) |
|
||
| | `daemon` | 看门狗守护进程(在线检测 + 异常回调) |
|
||
| | `alarm/buzzer` | 蜂鸣器告警 |
|
||
| | `vofa` | 调试数据可视化 (VoFA+ FireWater) |
|
||
| | `oled` | OLED 显示屏 |
|
||
| | `super_cap` | 超级电容管理 |
|
||
|
||
---
|
||
|
||
## 八、BSP 驱动层
|
||
|
||
所有 BSP 驱动采用**实例化注册**模式(不注册不初始化):
|
||
|
||
| 模块 | 功能 |
|
||
|------|------|
|
||
| `bsp_dwt` | DWT 时钟周期计数器(精确延时 μs/ms,时间戳获取) |
|
||
| `bsp_can` | CAN 总线收发封装(FIFO+中断,实例化注册) |
|
||
| `bsp_usart` | 串口收发封装(DMA+环形缓冲区,实例化注册) |
|
||
| `bsp_spi` | SPI 通信封装 |
|
||
| `bsp_iic` | I2C 通信封装 |
|
||
| `bsp_pwm` | PWM 输出(支持 DMA 传输) |
|
||
| `bsp_gpio` | GPIO 管理 |
|
||
| `bsp_log` | SEGGER RTT + 串口日志输出(LOGINFO/LOGERROR/LOGWARNING) |
|
||
| `bsp_tools` | RTOS 任务创建工具 (`CreateCallbackTask`) |
|
||
|
||
---
|
||
|
||
## 九、数据流与控制流总结
|
||
|
||
```
|
||
┌─────────────┐
|
||
│ 遥控器DBUS │
|
||
│ (USART5) │
|
||
└──────┬──────┘
|
||
↓
|
||
┌────────────────────────┐
|
||
│ RobotCMD │
|
||
│ ┌─────────────────┐ │
|
||
│ │ RemoteControlSet│ │ ← 手动模式 (遥控器调试)
|
||
│ │ AutoSet (题号) │ │ ← 自动模式 (竞赛任务)
|
||
│ └───────┬─────────┘ │
|
||
│ ↓ │
|
||
│ 发布: gimbal_cmd │──→ Gimbal (云台 PID → IMU 反馈)
|
||
│ chassis_cmd │──→ Chassis (运动学 → 麦轮)
|
||
│ shoot_cmd │──→ Shoot (摩擦轮/拨盘)
|
||
└────────────────────────┘
|
||
↑
|
||
┌────────────┴───────────┐
|
||
│ 反馈: gimbal_feed │ ← 云台姿态 + 电机角度
|
||
│ chassis_feed │ ← 底盘速度 + 热量
|
||
│ shoot_feed │ ← 发射状态
|
||
└────────────────────────┘
|
||
|
||
视觉/OpenCV (USART10) ──→ 卡尔曼滤波 ──→ PID ──→ 云台角度控制
|
||
板间通信 (USART1) ──→ BoardComm ──→ 题号/坐标数据
|
||
裁判系统 ──→ 热量/弹速/UI 绘制
|
||
```
|
||
|
||
---
|
||
|
||
## 十、关键设计特点
|
||
|
||
1. **IMU 替代电机反馈**:云台 Yaw/Pitch 使用陀螺仪角度/角速度替代编码器,实现更高精度姿态闭环
|
||
2. **伪 Pub-Sub 模式**:应用间通过 `message_center` 解耦,支持单板/双板条件编译切换(`ONE_BOARD` / `GIMBAL_BOARD` / `CHASSIS_BOARD`)
|
||
3. **Daemon 看门狗**:每个外设模块注册独立的 `DaemonInstance`(重载计数 + 离线回调),模块离线时自动触发异常处理
|
||
4. **BSP 实例化注册**:CAN/串口等外设不注册不初始化,避免资源浪费
|
||
5. **竞赛状态机**:完整的题号自动任务流程(转向→搜索→跟踪→激光打击)
|
||
6. **卡尔曼滤波 + PID 级联**:视觉误差经过 KF 平滑后由 PID 计算输出,带前馈补偿
|
||
7. **位域优化**:遥控器键盘状态使用位域 (`Key_t`),空间减少 8 倍
|
||
8. **条件编译**:单板/双板/电机类型/视觉通信方式均通过宏定义切换
|
||
|
||
---
|
||
|
||
## 十一、项目规模统计
|
||
|
||
| 类别 | 数量 |
|
||
|------|------|
|
||
| C 源文件 | 115 个 |
|
||
| ASM 源文件 | 2 个 |
|
||
| 应用层模块 | 4 (robot_cmd, gimbal, chassis, shoot) |
|
||
| 模块层子模块 | 20+ (电机×6, 姿态×3, 算法×5, 通信×7, 辅助×5) |
|
||
| BSP 驱动模块 | 10 |
|
||
| FreeRTOS 任务 | 4 (默认) |
|
||
| 最高控制频率 | 1kHz |
|
||
| CPU 频率 | 480MHz (PLL = HSE 8MHz / 2 × 40 / 2) |
|
||
| FLASH 使用 | 161,556 B / 1 MB (15.41%) |
|
||
| DTCMRAM 使用 | 60,920 B / 128 KB (46.48%) |
|
||
|
||
---
|
||
|
||
## 十二、电机配置速查
|
||
|
||
| 电机 | 类型 | CAN 总线 | TX ID | 控制闭环 | PID 级联 |
|
||
|------|------|----------|-------|----------|----------|
|
||
| Yaw (云台) | GM6020 | CAN1 | 0x01 | 角度+速度 | Angle → Speed (IMU 反馈) |
|
||
| Pitch (云台) | DM Motor | CAN1 | 0x06/0x16 | 角度+速度 | Angle → Speed (IMU 反馈) |
|
||
| 摩擦轮 左 | M3508 | CAN2 | 0x01 | 速度+电流 | Speed → Current |
|
||
| 摩擦轮 右 | M3508 | CAN2 | 0x02 | 速度+电流 | Speed → Current (反转) |
|
||
| 拨盘 | M2006 | CAN2 | 0x03 | 角度/速度+电流 | Angle/Speed → Current |
|
||
|
||
---
|
||
|
||
## 十三、关键配置宏 (`robot_def.h`)
|
||
|
||
```c
|
||
#define ONE_BOARD // 单板控制整车
|
||
#define VISION_USE_UART // 使用串口发送视觉数据
|
||
#define YAW_CHASSIS_ALIGN_ECD 2711 // 云台底盘对齐编码器值
|
||
#define PITCH_HORIZON_ECD 3412 // 云台水平位置编码器值
|
||
#define ONE_BULLET_DELTA_ANGLE 36 // 单发弹丸拨盘转动角度
|
||
#define WHEEL_BASE 350 // 纵向轴距 (mm)
|
||
#define TRACK_WIDTH 300 // 横向轮距 (mm)
|
||
#define RADIUS_WHEEL 60 // 轮子半径 (mm)
|
||
```
|