02 / 2026 / 开发中
ziFly:自研四轴无人机飞控系统
从 STM32F103 驱动、传感器采集、姿态解算和串级 PID 控制,到 ROS2/PX4 仿真适配的个人长期项目。
系统结构图暂不可用
问题
如何把 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图片

开发环境
嵌入式固件
- 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. 编译飞控固件
- 使用 Keil µVision 打开
代码/光流定位程序/mini.uvprojx。 - 确认目标为
Target 1,器件为STM32F103C8。 - 执行
Project -> Rebuild all target files,或按F7。 - 编译成功后,固件位于:
text
代码/光流定位程序/Output/mini.hex
5. 拆下全部螺旋桨,通过 SWD 连接飞控板与 ST-Link/J-Link。
6. 在 Keil 中选择正确的调试器,然后执行 Flash -> Download,或按 F8。
7. 断电后重新上电,并让飞控保持静止、水平,等待传感器和气压计稳定。
飞控的主要调参入口:
- PID 初值:
代码/光流定位程序/USER/INIT.c - 任务周期:
代码/光流定位程序/USER/scheduler.c - 姿态、定高、光流与电机混控:
代码/光流定位程序/HAL/control.c
2. 编译遥控器固件
- 使用 Keil µVision 打开
代码/遥控左手油门程序(keil MDK)/remote.uvprojx。 - 确认目标器件为
STM32F103C8。 - 执行
Rebuild。 - 编译成功后,固件位于:
text
代码/遥控左手油门程序(keil MDK)/Objects/remote.hex
5. 拆下飞行器螺旋桨后,再分别给遥控板和飞控板烧录、上电测试。
[!NOTE] 当前
USER/main.c的有效main()是串口收发测试程序,正常遥控初始化代码暂时被注释。需要遥控飞行前,应恢复其中调用cycleCounterInit()、SysTick_Config()、_g_Init_sys()和NVIC_Configuration()的正常入口,再重新编译烧录。
首次上电检查
请全程拆下螺旋桨,并按以下顺序检查:
- 检查飞控板与遥控板是否有短路,确认供电电压和极性正确。
- 确认 MPU6050、SPL06、nRF24L01 和光流模块接线与原理图一致。
- 确认飞控与遥控器使用相同的 nRF24L01 地址、频道和速率。
- 飞控上电后保持水平静止至少数秒,不要在初始化期间移动机体。
- 检查四路 PWM 在锁定状态下是否均为 0。
- 逐个测试电机编号和旋转方向,再安装与方向匹配的螺旋桨。
- 首飞前将机体固定或使用测试架,以低油门验证横滚、俯仰和偏航补偿方向。
电机编号
当前 X 型混控中的电机位置如下:
机头
PWM3 PWM2
\ /
\ /
\ /
\ /
\ /
/ \
/ \
/ \
/ \
PWM4 PWM1
对应 STM32 输出:
| 电机 | 定时器通道 | 引脚 |
|---|---|---|
| PWM1 | TIM2 CH1 | PA0 |
| PWM2 | TIM2 CH2 | PA1 |
| PWM3 | TIM2 CH3 | PA2 |
| PWM4 | TIM2 CH4 | PA3 |
若机架布局、电机驱动板或安装方向不同,需要同步修改 MotorControl() 中的混控符号,不能只交换螺旋桨。
遥控与飞行模式
本项目为左手油门:
| 摇杆 | 方向 | 功能 |
|---|---|---|
| 左摇杆 | 上 / 下 | 油门或定高模式下的升降指令 |
| 左摇杆 | 左 / 右 | 偏航 |
| 右摇杆 | 上 / 下 | 俯仰 |
| 右摇杆 | 左 / 右 | 横滚 |
解锁
当前源码采用三步油门解锁:
- 油门拉到最低。
- 油门推到较高位置。
- 再将油门拉回最低。
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、坐标方向和混控参数;
- 可复现步骤、串口日志以及测试时是否拆下螺旋桨。
免责声明
本项目主要用于学习、研究和实验。使用者应自行确认硬件、电气、软件、无线电和飞行环境的安全性,并遵守所在地法律法规。因使用、修改或部署本项目造成的设备损坏、人身伤害或其他损失,项目贡献者不承担责任。