三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

从零开始:用STM32F103C8T6和HAL库打造你的第一台四轴无人机飞控(附完整原理图与代码)

从零开始:用STM32F103C8T6和HAL库打造你的第一台四轴无人机飞控(附完整原理图与代码)

从零开始:用STM32F103C8T6和HAL库打造你的第一台四轴无人机飞控(附完整原理图与代码)

在创客圈子里,四轴无人机始终是令人着迷的项目——它融合了嵌入式开发、自动控制理论和硬件设计三大领域。但大多数教程要么停留在理论层面,要么直接给出成品代码让人无从下手。本文将用一台基于STM32F103C8T6的飞控,带你完整走通从元器件选型到PID调参的全流程。不同于市面上常见的F4系列方案,这个"蓝色药丸"(STM32F103的昵称)方案成本更低,更能锻炼底层开发能力。

1. 硬件选型与成本控制

1.1 为什么选择STM32F103C8T6?

这款被戏称为"中国芯"的MCU有着令人惊讶的性价比优势:

参数STM32F103C8T6STM32F405RG对比分析
主频72MHz168MHz飞控算法不需要超高主频
Flash64KB1MB精简代码足够存放
SRAM20KB192KB需注意内存优化
单价(2023)¥12-15¥35-40成本降低60%以上

实战建议:购买时注意区分"正品丝印"和国产兼容芯片,后者可能出现ADC精度不足的问题。实测发现某些国产型号的MPU6050数据读取会有±0.5°的偏差。

1.2 关键外设配置清单

// HAL库外设初始化优先级配置示例 HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0); // MPU6050中断 HAL_NVIC_SetPriority(TIM1_UP_IRQn, 4, 0); // PWM生成 HAL_NVIC_SetPriority(USART1_IRQn, 3, 0); // 调试串口

必备元器件清单:

  • 动力系统:8520空心杯电机 ×4(带正反桨)
  • 传感单元:MPU6050六轴传感器(务必选择带AUX_CLK引脚的版本)
  • 驱动电路:SI2302 MOS管 + FR107二极管组成H桥
  • 电源模块:BL8530升压芯片 + XC6206稳压芯片

2. 开发环境搭建与HAL库魔改

2.1 CubeMX工程配置技巧

在Clock Configuration中开启PLL倍频时,建议采用8MHz外部晶振→PLL×9→72MHz的方案。这个配置下ADC采样时钟不要超过14MHz,否则会出现数据抖动。

关键配置步骤

  1. 在Pinout视图启用I2C1(MPU6050通信)
  2. 配置TIM1为PWM Generation模式
  3. 开启USART1异步通信(115200bps)

2.2 内存优化实战

由于F103的20KB内存限制,需要修改HAL库的默认配置:

// 修改stm32f1xx_hal_conf.h #define HAL_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED // 仅启用必要模块

注意:禁用不用的HAL模块可节省约8KB Flash空间。建议使用-Os优化等级编译。

3. 传感器驱动与姿态解算

3.1 MPU6050的硬件陷阱

市面上常见的MPU6050模块存在两个版本:

  • 标准版:仅支持I2C通信
  • 增强版:额外引出AUX_CLK(可用于同步采样)

接线时特别注意:

VCC → 3.3V SCL → PB6 SDA → PB7 INT → PB5(配置为下降沿触发)

3.2 卡尔曼滤波实现

简化版的姿态解算算法:

void Kalman_Update(float *angle, float *bias, float rate, float accel, float dt) { float Pdot[4] = {0}; Pdot[0] = Q_angle - P[0][1] - P[1][0]; Pdot[1] = -P[1][1]; Pdot[2] = -P[1][1]; Pdot[3] = Q_bias; // 预测协方差 P[0][0] += Pdot[0] * dt; P[0][1] += Pdot[1] * dt; P[1][0] += Pdot[2] * dt; P[1][1] += Pdot[3] * dt; // 更新卡尔曼增益 float S = R_measure + P[0][0]; float K[2] = {P[0][0]/S, P[1][0]/S}; // 更新状态估计 float y = accel - *angle; *angle += K[0] * y; *bias += K[1] * y; // 更新协方差 float P00_temp = P[0][0]; P[0][0] -= K[0] * P00_temp; P[0][1] -= K[0] * P[0][1]; P[1][0] -= K[1] * P00_temp; P[1][1] -= K[1] * P[0][1]; }

4. 电机控制与PID调参

4.1 PWM驱动电路设计

采用N沟道MOS管SI2302搭建的驱动电路需要注意:

  • 栅极电阻选用100Ω(过大导致开关损耗,过小引起振荡)
  • 续流二极管FR107的反向恢复时间要<50ns
  • 电机两端并联104瓷片电容吸收尖峰

实测PWM频率建议设置在8-12kHz:

// TIM1 PWM初始化代码片段 htim1.Instance = TIM1; htim1.Init.Prescaler = 72-1; // 1MHz计数频率 htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 100-1; // 10kHz PWM htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

4.2 PID参数整定经验

采用试凑法时的起调参数建议:

控制环PID说明
角度环3.50.0218先调P至轻微振荡
角速度0.804.5再调D抑制超调
高度环1.20.010最后微调I消除静差

调试时务必先断开电机,用串口打印实时曲线。我在实验室摔坏过三套桨叶才找到这组黄金参数。

5. 飞行测试与故障排查

5.1 校准流程清单

  1. 水平校准:将飞控平放在桌面,持续发送CALIB_ACC命令
  2. 陀螺校准:保持静止发送CALIB_GYRO约5秒
  3. 磁力计校准(如有):在空中画"8"字

5.2 常见故障代码表

现象可能原因解决方案
起飞后剧烈抖动PID参数过冲降低D值,增加I值
向一侧倾斜电机推力不平衡重新校准ESC或更换电机
高度无法保持气压计受气流干扰加装海绵减震,优化算法
遥控信号丢失NRF24L01天线接触不良改用IPEX外接天线

最后分享一个血泪教训:永远在第一次室外试飞时系上安全绳。我的第一台原型机就是因为没做这个防护,现在还在小区梧桐树上挂着。

← 返回列表