# 项目架构分析报告: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) ```