Files
Gimbal/ARCHITECTURE.md
T
SkyLiCoder 8763b25839 chore: upgrade FreeRTOS to v2 (CMSIS-RTOS_V2), update CubeMX project config
- Remove CMSIS-RTOS v1 (cmsis_os.h/cmsis_os.c), add CMSIS-RTOS v2 (cmsis_os2.c/freertos_os2.h/mpool.h)
- Update FreeRTOS kernel, port, and headers to match v2 integration
- Remove unused heap implementations, keep heap_4
- Update CubeMX project config (.mxproject, .ioc, CMakeLists.txt)
- Update FreeRTOSConfig.h, freertos.c, main.c, stm32h7xx_it.c
- Update application modules (master_machine, dmmotor)
- Add CMSIS-RTOS2 headers, mpu_syscall_numbers.h, newlib/picolibc support
2026-05-30 20:40:00 +08:00

13 KiB
Raw Blame History

项目架构:Basic_Framework_MC02 (DM 云台控制系统)

概览

基于 STM32H723 (Cortex-M7, 480MHz) 的达妙电机云台控制系统。采用 FreeRTOS,通过 IMU 反馈实现角度闭环,通过串口接收上位机指令实现视觉追踪。项目源自 HNU YueLu EC RoboMaster 项目,经重构精简为纯云台控制。


一、硬件与通信

资源 用途
FDCAN1 电机控制总线 (DM-G6220 yaw, DM-J4310-2EC pitch)
USART10 上位机通信 (master_machine 协议)
USART7 VoFA 调试输出
USART1 板间通信 (BoardComm)
SPI2 BMI088 IMU 传感器

二、分层架构

┌──────────────────────────────────────────────┐
│  application/  应用层                        │
│  robot.c → robot_cmd → gimbal               │
├──────────────────────────────────────────────┤
│  modules/      模块层                        │
│  motor, imu, master_machine, algorithm, ... │
├──────────────────────────────────────────────┤
│  bsp/          板级支持包                   │
│  can, usart, spi, dwt, log, gpio           │
├──────────────────────────────────────────────┤
│  Drivers/      HAL 驱动层 (CubeMX 生成)     │
│  STM32H7xx_HAL, CMSIS, FreeRTOS            │
└──────────────────────────────────────────────┘

三、启动流程

main()
  ├── HAL_Init() → SystemClock_Config() → MX_*_Init()  // CubeMX 外设初始化
  └── RobotInit()
        ├── BSPInit()                    // DWT + Log
        ├── RobotCMDInit()               // pub-sub, 视觉PID, 串口初始化
        ├── GimbalInit()                 // IMU + DM 电机初始化
        └── OSTaskInit()                 // 创建 4 个 RTOS 任务

FreeRTOS 任务

任务 频率 优先级 功能
INS Task 1kHz AboveNormal BMI088 读取 → 四元数 EKF 姿态解算
Motor Task 1kHz Normal DM 电机角度 PID → CAN 速度指令发送
Robot Task 500Hz Normal 上位机命令处理 + 模式切换 + 控制执行
Daemon Task 100Hz Normal 模块看门狗 + 蜂鸣器

四、PID 双环架构

┌──────────────────────────────────────────────────────┐
│  application/cmd/robot_cmd.c  (外环, 500Hz)         │
│                                                      │
│  上位机 0xA5 帧 → error_x/y → KF → vision PID      │
│                 → 角度增量 → 累计 angle ref          │
│  上位机 0xA6 帧 → yaw_ref/pitch_ref 直接设定        │
│                                                      │
│  ProcessCommand() 处理模式切换 / 激光控制            │
└──────────────────────┬───────────────────────────────┘
                       │ gimbal_cmd (pub-sub)
                       ▼
┌──────────────────────────────────────────────────────┐
│  application/gimbal/gimbal.c  (传递, 500Hz)         │
│                                                      │
│  DMMotorSetRef(yaw, cmd.yaw)                        │
│  DMMotorSetRef(pitch, cmd.pitch)                    │
│  反馈: gimbal_feed → gimbal_IMU_data 指针           │
└──────────────────────┬───────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────┐
│  modules/motor/DMmotor/  (内环, 1kHz)                │
│                                                      │
│  IMU 角度反馈 → angle PID → velocity output         │
│  → DMMotorSendVelocity() → CAN 速度模式             │
│  output_reverse 控制输出方向                         │
└──────────────────────────────────────────────────────┘

五、上位机串口协议

位于 modules/master_machine/。三种帧类型,通过帧头区分。

自动/视觉追踪数据帧 0xA5 (10 字节)

字节 0 1-4 5-8 9
内容 0xA5 error_x (float) error_y (float) checksum

手动控制数据帧 0xA6 (11 字节)

字节 0 1 2-5 6-9 10
内容 0xA6 zero_force yaw_ref (float) pitch_ref (float) checksum

命令帧 0xA7 (3 字节)

字节 0 1 2
内容 0xA7 cmd checksum

命令码:0x01 切换到自动模式, 0x02 切换到手动模式, 0x03 激光开, 0x04 激光关

数据流

上位机 USART10 → DecodeVision() → vision_data (全局结构体)
  ├── 0xA5 → auto_updated=1, error_x/y
  ├── 0xA6 → manual_updated=1, zero_force, yaw_ref/pitch_ref
  └── 0xA7 → cmd_pending=1, cmd

robot_cmd 每轮:
  ProcessCommand() → 模式切换 / 激光
  AUTO:  vision_data.error_x/y → KF → vision PID → 角度增量
  MANUAL: vision_data.yaw_ref/pitch_ref → 直接设定
  PubPushMessage(gimbal_cmd) → gimbal 执行

六、DM 电机驱动

位于 modules/motor/DMmotor/。基于 DM_6220 参考协议。

速度模式 (当前默认)

CAN ID = motor_id + 0x200,发送 float velocity (4 bytes)。

DMMotorControl() @ 1kHz:
  PIDCalculate(angle_PID, IMU_angle, pid_ref) → velocity
  output_reverse? → DMMotorSendVelocity() → CAN

电机配置

电机 CAN ID 反馈 ID 模式 MIT KP/KD
DM-G6220 (Yaw) 0x01 0xF1 Velocity —
DM-J4310-2EC (Pitch) 0x02 0xF2 Velocity —

API

函数 说明
DMMotorInit() 初始化电机实例 (CAN 注册, PID 初始化, daemon)
DMMotorSetRef() 设定角度参考值 (degrees)
DMMotorControl() 1kHz 控制循环 (所有电机)
DMMotorSetMode() 发送命令 (使能/停止/清零/清除错误)
DMMotorSendVelocity() 速度模式 CAN 发送
DMMotorSendMIT() MIT 模式 CAN 发送
DMMotorSendPosVel() 位置-速度模式 CAN 发送

七、模块层

分类 模块 功能
电机 motor/DMmotor 达妙电机驱动 (MIT/PosVel/Velocity 三模式)
motor/motor_task 电机控制统一调度 (DMMotorControl)
姿态 imu/ins_task 惯导解算 (四元数 EKF, 返回 INS_t 指针)
imu/BMI088driver BMI088 SPI 读取
imu/BMI088Middleware BMI088 数据换算
算法 algorithm/controller PID 控制器 (梯形积分/变速积分/微分先行/输出滤波)
algorithm/kalman_filter 卡尔曼滤波器 (自适应)
algorithm/QuaternionEKF 四元数 EKF (陀螺零偏估计/卡方检验)
algorithm/crc8/crc16 CRC 校验
algorithm/user_lib 数学/工具函数
通信 master_machine 上位机通信 (0xA5/0xA6/0xA7 协议, 接收+解析)
timachine/board_comm 板间通信
message_center Pub-Sub 消息中间件 (链表, FIFO)
系统 daemon 看门狗 (重载计数+离线回调)
alarm/buzzer 蜂鸣器
vofa VoFA+ 调试输出

八、BSP 驱动层

实例化注册模式 (不注册不初始化):

模块 功能
bsp_dwt DWT 周期计数器 (μs/ms 延时, 时间戳)
bsp_can FDCAN 收发 (FIFO+中断)
bsp_usart 串口收发 (DMA+环形缓冲区)
bsp_spi SPI 通信
bsp_log SEGGER RTT + 串口日志
bsp_pwm PWM 输出

九、数据流

                    ┌──────────────┐
                    │   上位机      │
                    │  (USART10)   │
                    └──────┬───────┘
                           │ 0xA5 / 0xA6 / 0xA7
                           ▼
              ┌────────────────────────┐
              │      RobotCMD          │
              │   ProcessCommand()     │ ← 模式切换/激光
              │   VisionTrackingSet()  │ ← KF → vision PID → 角度增量
              │   ManualModeSet()      │ ← 直接角度参考
              │   PubPushMessage()     │
              └───────────┬────────────┘
                          │ gimbal_cmd
                          ▼
              ┌────────────────────────┐
              │      Gimbal            │
              │   DMMotorSetRef()      │
              │   反馈: gimbal_feed    │ ← INS_t* 指针
              └───────────┬────────────┘
                          │ angle ref
                          ▼
              ┌────────────────────────┐
              │      DMMotor           │  (1kHz Motor Task)
              │   IMU angle → PID     │
              │   → Velocity mode CAN │
              └────────────────────────┘
                          │
              ┌───────────┴────────────┐
              │  DM-G6220    DM-J4310  │
              │  (Yaw)       (Pitch)   │
              └────────────────────────┘

十、关键设计

  1. IMU 反馈替代编码器 — 云台 Yaw/Pitch 使用 INS_t 中的 YawTotalAngle/Pitch 和 Gyro[]
  2. 速度模式控制 — MCU 跑角度 PID,电机内部处理速度闭环
  3. 伪 Pub-Sub — 应用间通过 message_center 解耦
  4. Daemon 看门狗 — 每个外设模块独立 DaemonInstance,离线自动回调
  5. BSP 实例化注册 — CAN/串口不注册不初始化
  6. KF + PID 级联 — 视觉误差经 KF 平滑 → vision PID → 角度增量 → 内环角度 PID
  7. 模式切换重置 — 切换到自动模式时重置 KF 状态 (x=0, P=diag(5,5)) 和 PID 积分项
  8. 串口命令控制 — 模式切换、激光控制均通过 0xA7 命令帧触发
  9. output_reverse — PID 输出方向统一通过单标志位控制

十一、项目规模

类别 数量
C 源文件 96
ASM 源文件 2
应用层模块 3 (robot, robot_cmd, gimbal)
模块层子模块 10 (motor, imu, algorithm, master_machine, message_center, daemon, buzzer, vofa, board_comm)
BSP 驱动模块 8
FreeRTOS 任务 4
最高控制频率 1kHz
CPU 频率 480MHz
FLASH 使用 ~133 KB / 1 MB (13%)
DTCMRAM 使用 ~59 KB / 128 KB (46%)

十二、核心数据类型

// INS 惯导实例 (ins_task.h)
typedef struct {
    float q[4];            // 四元数
    float Gyro[3];         // 角速度 (rad/s)
    float Accel[3];        // 加速度 (m/s²)
    float Roll, Pitch, Yaw;
    float YawTotalAngle;   // 多圈 yaw (degrees)
} INS_t;

// 云台控制指令 (robot_def.h)
typedef struct {
    float yaw;             // yaw 目标角度 (degrees)
    float pitch;           // pitch 目标角度 (degrees)
} Gimbal_Ctrl_Cmd_s;

// 上位机数据 (master_machine.h)
typedef struct {
    float error_x, error_y;       // 自动模式: 归一化误差
    uint8_t auto_updated;
    uint8_t zero_force;           // 手动模式: 零力标志
    float yaw_ref, pitch_ref;     // 手动模式: 角度参考
    uint8_t manual_updated;
    uint8_t cmd, cmd_pending;     // 命令
    float frequency;
} VisionData_t;