02 / 2026 / 开发中

ziFly:自研四轴无人机飞控系统

从 STM32F103 驱动、传感器采集、姿态解算和串级 PID 控制,到 ROS2/PX4 仿真适配的个人长期项目。

ziFly:自研四轴无人机飞控系统

问题

如何把 MCU 底层驱动、姿态控制、遥控链路与 ROS2/PX4 仿真组织成可持续迭代的四轴飞控实验系统?

角色

个人长期项目;负责硬件接口、MCU 驱动、姿态解算、串级 PID、控制逻辑与仿真适配。

方法

STM32F103;MPU6050;SPL06;nRF24L01;四元数姿态解算;角度外环与角速度内环串级 PID;气压定高、光流与 ROS2/PX4 仿真。

结果

仓库包含飞控与遥控器固件、飞控 PCB、遥控器 PCB、3D 模型和 ROS2/PX4 仿真代码骨架。当前状态为开发中、仿真验证与控制算法实验,未宣称稳定自主飞行。

ziFly 四轴无人机飞控

一套基于 STM32F103C8 的四轴无人机学习与实验项目,包含飞控固件、左手油门遥控器固件、PCB 工程、SolidWorks 机架模型,以及用于连接 ROS 2 / PX4 的仿真代码骨架。

[!WARNING] 无人机高速旋转的螺旋桨可能造成严重伤害。首次编译、烧录、调参和检查电机转向时,请务必拆下螺旋桨;仅在远离人群、动物和易损物品的空旷区域试飞。本文档不构成对飞行安全或可靠性的保证。

项目功能

  • MPU6050 六轴 IMU 数据采集与四元数姿态解算
  • 角度外环 + 角速度内环的串级 PID 姿态控制
  • SPL06 气压计高度估计与定高控制
  • Mini 光流数据解析、姿态补偿和水平定点控制
  • nRF24L01 2.4 GHz 遥控通信及 32 字节遥控数据帧
  • 四路电机 PWM 输出与 X 型四轴混控
  • 2 ms~1 s 多周期任务调度
  • 遥控失联锁定、过度倾斜保护和手动锁定
  • ROS 2 节点接收 PX4 IMU 数据并发布四路电机控制量
  • 飞控板、遥控板 PCB 工程与四轴机架三维模型

系统组成

flowchart LR
    A[遥控摇杆与按键] --> B[STM32F103C8 遥控器]
    B -->|nRF24L01 / 2.4 GHz| C[STM32F103C8 飞控]
    D[MPU6050] --> C
    E[SPL06] --> C
    F[Mini 光流模块] --> C
    C --> G[姿态与位置控制]
    G --> H[4 路 PWM]
    H --> I[电调或空心杯电机驱动]
    J[PX4 SITL] <-->|ROS 2 / uXRCE-DDS| K[仿真适配器]

目录结构

.
├─ PCB/
│  ├─ ProPrj_飞控3_2026-08-08.epro2
│  └─ ProPrj_遥控板_USB无线串口_原理图已修正_2026-08-08.epro2
├─ 代码/
│  ├─ 光流定位程序/                    # 飞控 Keil MDK 工程
│  │  ├─ USER/                        # 入口、初始化和任务调度
│  │  ├─ HAL/                         # 飞行控制、遥控协议、上位机通信
│  │  ├─ HARDWARE/                    # MPU6050、SPL06、光流、nRF24L01 等
│  │  ├─ MATH/                        # 姿态解算、PID、滤波和数学函数
│  │  ├─ CONFIG/                      # GPIO、I2C、SPI、USART、TIM 等
│  │  └─ mini.uvprojx                 # 飞控 Keil 工程入口
│  └─ 遥控左手油门程序(keil MDK)/
│     ├─ USER/                        # 遥控器入口与系统节拍
│     ├─ HAL/                         # 摇杆、按键与遥控数据帧
│     ├─ CONFIG/                      # ADC、DMA、SPI、定时器等
│     ├─ HARDWARE/                    # nRF24L01 驱动
│     └─ remote.uvprojx               # 遥控器 Keil 工程入口
├─ 仿真/
│  ├─ px4_ros_ws/
│  │  ├─ px4_msgs/                    # 按下文命令获取,使用 release/1.17
│  │  └─ src/my_flight_controller/    # 飞控核心接口与 ROS 2 适配器
│  ├─ PX4-Autopilot/                  # 预留的 PX4 源码目录
│  └─ tools/                          # Micro XRCE-DDS Agent 预留目录
└─ 无人机3D模型/                       # SolidWorks 零件与装配体

硬件与接口

以下内容依据当前源码配置整理,实际制作时请以 PCB/ 中的原理图和自己的板卡版本为准。

模块 当前配置 说明
飞控 MCU STM32F103C8 Keil 目标器件为 STM32F103C8
遥控 MCU STM32F103C8 使用内部时钟经 PLL 配置为 48 MHz
姿态传感器 MPU6050 软件 I2C,当前寄存器配置为陀螺仪 ±1000 °/s、加速度计 ±4 g
气压计 SPL06-001 I2C 地址默认使用0x77
光流模块 Mini 光流 USART1,19200 baud,8N1
遥控链路 nRF24L01 频道 40、2 Mbps、32 字节载荷
电机输出 TIM2 CH1~CH4 PA0~PA3,源码配置约 8 kHz PWM
调试串口 USART3 PB10/PB11,115200 baud
遥控摇杆 ADC1 + DMA PA0~PA3:油门、偏航、横滚、俯仰
遥控校准存储 AT24C02 保存横滚与俯仰微调值

飞控和遥控器的 nRF24L01 地址必须一致。当前两端默认地址均为:

{0xE1, 0xE2, 0xE3, 0xE4, 0xE5}

飞控PCB图片

ziFly 四轴无人机

开发环境

嵌入式固件

  • Windows
  • Keil MDK-ARM 5 / µVision 5
  • ARM Compiler 5(ARMCC)
  • Keil STM32F1xx Device Family Pack
  • ST-Link 或 J-Link 下载器

已有构建记录使用过 MDK 5.14 + ARMCC 5.05 和 MDK 5.43 + ARMCC 5.06。若新版 Keil 提示找不到 ARM Compiler 5,请在 Manage Project Items / Options for Target 中选择已安装的 ARMCC 5 工具链。

PCB 与结构件

  • PCB:嘉立创 EDA 专业版,可打开 .epro2 工程
  • 结构件:SolidWorks,可打开 .SLDPRT 与 .SLDASM

仿真

  • Linux 或 WSL 2
  • ROS 2
  • colcon
  • PX4 Autopilot
  • Micro XRCE-DDS Agent
  • 与 PX4 版本匹配的 px4_msgs;仓库内当前为 release/1.17

编译与烧录

1. 编译飞控固件

  1. 使用 Keil µVision 打开 代码/光流定位程序/mini.uvprojx。
  2. 确认目标为 Target 1,器件为 STM32F103C8。
  3. 执行 Project -> Rebuild all target files,或按 F7。
  4. 编译成功后,固件位于:

text 代码/光流定位程序/Output/mini.hex 5. 拆下全部螺旋桨,通过 SWD 连接飞控板与 ST-Link/J-Link。 6. 在 Keil 中选择正确的调试器,然后执行 Flash -> Download,或按 F8。 7. 断电后重新上电,并让飞控保持静止、水平,等待传感器和气压计稳定。

飞控的主要调参入口:

2. 编译遥控器固件

  1. 使用 Keil µVision 打开 代码/遥控左手油门程序(keil MDK)/remote.uvprojx。
  2. 确认目标器件为 STM32F103C8。
  3. 执行 Rebuild。
  4. 编译成功后,固件位于:

text 代码/遥控左手油门程序(keil MDK)/Objects/remote.hex 5. 拆下飞行器螺旋桨后,再分别给遥控板和飞控板烧录、上电测试。

[!NOTE] 当前 USER/main.c 的有效 main() 是串口收发测试程序,正常遥控初始化代码暂时被注释。需要遥控飞行前,应恢复其中调用 cycleCounterInit()、SysTick_Config()、_g_Init_sys() 和 NVIC_Configuration() 的正常入口,再重新编译烧录。

首次上电检查

请全程拆下螺旋桨,并按以下顺序检查:

  1. 检查飞控板与遥控板是否有短路,确认供电电压和极性正确。
  2. 确认 MPU6050、SPL06、nRF24L01 和光流模块接线与原理图一致。
  3. 确认飞控与遥控器使用相同的 nRF24L01 地址、频道和速率。
  4. 飞控上电后保持水平静止至少数秒,不要在初始化期间移动机体。
  5. 检查四路 PWM 在锁定状态下是否均为 0。
  6. 逐个测试电机编号和旋转方向,再安装与方向匹配的螺旋桨。
  7. 首飞前将机体固定或使用测试架,以低油门验证横滚、俯仰和偏航补偿方向。

电机编号

当前 X 型混控中的电机位置如下:

                 机头

          PWM3           PWM2
              \         /
               \       /
                \     /
                 \   /
                  \ /
                  / \
                 /   \
                /     \
               /       \
          PWM4           PWM1

对应 STM32 输出:

电机 定时器通道 引脚
PWM1 TIM2 CH1 PA0
PWM2 TIM2 CH2 PA1
PWM3 TIM2 CH3 PA2
PWM4 TIM2 CH4 PA3

若机架布局、电机驱动板或安装方向不同,需要同步修改 MotorControl() 中的混控符号,不能只交换螺旋桨。

遥控与飞行模式

本项目为左手油门:

摇杆 方向 功能
左摇杆 上 / 下 油门或定高模式下的升降指令
左摇杆 左 / 右 偏航
右摇杆 上 / 下 俯仰
右摇杆 左 / 右 横滚

解锁

当前源码采用三步油门解锁:

  1. 油门拉到最低。
  2. 油门推到较高位置。
  3. 再将油门拉回最低。

LED 进入常亮状态后表示完成解锁。第一次验证必须拆下螺旋桨。

锁定

将油门保持在低位,同时将偏航摇杆打到左侧,可触发锁定。遥控信号持续丢失或机体横滚/俯仰角超过保护阈值时,飞控也会停止电机输出。

模式切换

AUX2 模式 行为
低位 姿态模式 摇杆直接给出期望横滚角和俯仰角
高位(大于约 1700) 定高 + 光流模式 SPL06 参与定高,光流有效时参与水平定点

光流定点需要满足以下条件:

  • 光流数据帧正常,质量值不低于源码阈值;
  • 飞行高度进入有效范围;
  • 地面具有足够纹理,光照稳定;
  • 光流模块方向、机体坐标系和姿态方向一致;
  • 油门、姿态和光流 PID 已针对实际机体调好。

ROS 2 / PX4 仿真

仿真部分将飞控算法与 ROS 2 通信层分离:

  • core/:与 ROS 2 无关的 C 接口,可逐步移植嵌入式控制算法;
  • src/px4_sensor_adapter.cpp:订阅 PX4 IMU,调用控制器,再发布电机量;
  • 输入话题:/fmu/out/sensor_combined;
  • 输出话题:/fmu/in/offboard_control_mode、/fmu/in/actuator_motors。

编译 ROS 2 工作区

在已经安装并加载 ROS 2 环境的 Linux / WSL 终端中执行:

git clone --branch release/1.17 --depth 1 \
  https://github.com/PX4/px4_msgs.git \
  仿真/px4_ros_ws/px4_msgs

cd 仿真/px4_ros_ws
export ZIFLY_ROS_DISTRO=humble  # 改为本机已安装且与 PX4 匹配的发行版
source "/opt/ros/${ZIFLY_ROS_DISTRO}/setup.bash"
colcon build --symlink-install --packages-select px4_msgs my_flight_controller
source install/setup.bash

启动 PX4 SITL 和 Micro XRCE-DDS Agent,并确认 /fmu/ 话题已经出现后,运行适配器:

ros2 run my_flight_controller px4_sensor_adapter

可用下面的命令检查通信:

ros2 topic list | grep /fmu
ros2 topic echo /fmu/out/sensor_combined

[!IMPORTANT] 当前 flight_controller.c 只是接口骨架,四路电机输出固定为 0.0f。它用于先验证 PX4 → ROS 2 → 控制核心 → 电机话题的数据链路,尚未接入嵌入式飞控中的姿态与 PID 控制逻辑。

控制任务周期

飞控使用 SysTick 触发的软件时间片调度:

周期 主要任务
2 ms MPU6050 读取、姿态 PID、电机混控
4 ms 遥控数据解析、飞行模式选择
6 ms 四元数姿态更新
10 ms 光流融合、水平控制、高度估计、定高 PID
20 ms 预留上位机数据交换
50 ms LED 状态刷新
1000 ms 光流状态检测与任务耗时统计

遥控数据帧

遥控器每次发送 32 字节,飞控端检查帧头和累加校验:

Byte 0      0xAA
Byte 1      0xAF
Byte 2      0x03
Byte 3      数据长度
Byte 4..19  Roll / Pitch / Throttle / Yaw / AUX1..AUX4,高字节在前
Byte 20..30 预留
Byte 31     Byte 0..30 的 8 位累加和

通信参数和配对地址分别位于飞控与遥控器的 nrf24l01.c 中;修改时必须保持两端一致。

常见问题

Keil 提示缺少编译器

两个工程使用 ARM Compiler 5。安装 ARMCC 5 后,在 Keil 的工具链设置中选择对应版本,并安装 STM32F1xx DFP。

烧录后遥控器没有发送数据

检查遥控器 USER/main.c。当前有效入口为串口测试程序,正常遥控入口仍在同一文件的注释代码中。

飞控始终没有电机输出

依次检查遥控数据是否接收成功、是否完成解锁、油门是否超过启动阈值、是否触发倾角保护,以及 nRF24L01 地址和频道是否一致。

光流模式无法定点

确认 USART1 为 19200 baud,检查光流质量、高度、安装方向、地面纹理和光照;然后观察 mini.ok、Flow_Err 与 pixel_flow 数据,再逐级调节位置环、速度环和姿态环 PID。

中文注释显示乱码

部分历史源码使用本地 ANSI/GBK 编码。可先在 Keil 中选择相应编码查看;批量转换为 UTF-8 前请做好备份,避免改变源码内容。

仿真能收到 IMU,但电机一直为零

这是当前骨架的预期行为。请把嵌入式姿态解算、PID 状态和混控逻辑逐步迁移到 core/flight_controller.c,并统一单位、坐标系和控制周期。

后续计划

  • [ ] 恢复并验证遥控器正常入口
  • [ ] 整理构建产物与工程用户配置文件
  • [ ] 补充飞控板和遥控板的实物照片、接线图与 BOM
  • [ ] 完成各传感器校准流程和参数保存
  • [ ] 补充台架测试、首飞检查和 PID 调参记录
  • [ ] 将嵌入式控制核心接入 ROS 2 / PX4 仿真
  • [ ] 增加单元测试、SITL 测试与自动构建
  • [ ] 明确项目及第三方组件的开源许可证

贡献

欢迎通过 Issue 或 Pull Request 提交改进。为了便于复现,请在问题中说明:

  • 使用的飞控板与遥控板版本;
  • Keil、编译器和芯片包版本;
  • 传感器、电机、电调与电池配置;
  • 修改过的 PID、坐标方向和混控参数;
  • 可复现步骤、串口日志以及测试时是否拆下螺旋桨。

免责声明

本项目主要用于学习、研究和实验。使用者应自行确认硬件、电气、软件、无线电和飞行环境的安全性,并遵守所在地法律法规。因使用、修改或部署本项目造成的设备损坏、人身伤害或其他损失,项目贡献者不承担责任。