ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32小四轴飞控与NRF24L01遥控链路:原理图、源码和调试全解析

STM32小四轴飞控与NRF24L01遥控链路:原理图、源码和调试全解析 简介面向STM32嵌入式开发者与无人机爱好者这份资源完整提供了基于STM32单片机设计的无线四轴飞行器与飞控遥控器方案分为飞行器和遥控器两套子系统通过NRF24L01无线模块通信并由MPU6050姿态传感器完成飞行姿态控制。整个rar压缩包共673个文件以C/H源代码为主包含原理图、PCB图、Keil工程文件、hex固件及txt说明文档整体约10.96MB目录按飞控和遥控器工程分开便于对照学习。目前已有172人学习下载。内容不仅包括可直接使用的源码和硬件设计文件还配有飞控操作说明涉及螺旋桨安装、IMU校准、油门解锁等关键步骤结合原理图与PCB可以直观理解NRF24L01无线通信、MPU6050姿态解算和电机驱动电路适合毕业设计、课程实训或四轴飞行器入门制作参考。1. 小四轴不是玩具STM32 飞控、NRF24L01 遥控链路和 PCB 一起看很多玩航模的朋友第一次接触四轴飞行器是买的成品飞坏了没法修原因在于飞控这块主控板对很多人来说是个黑盒。这套资料对应的正是 Crazepony 这类空心杯小四轴方案飞行器端用 STM32 作为主控配合 MPU6050 姿态传感器和 NRF24L01 无线模块遥控器则是另一块 STM32 板通道数据通过 2.4G 链路发给飞控。资料里四个东西是齐的飞控和遥控器各自的原理图、PCB、源代码以及操作说明。特别适合两种人想从 PCB 层面理解四轴硬件怎么布局的嵌入式工程师以及用 STM32 做毕设、需要完整软件加硬件参考的学生。下文先把硬件主线的瓜理清再进代码看姿态和 PID最后拆遥控器协议和排错方法。2. 原理图与 PCBSTM32 最小系统、MPU6050 与 NRF24L01 的排布逻辑拆过几块小四轴的人都知道飞控板通常不会很复杂但“不复杂”不等于随手画。拿到这套资料的原理图和 PCB第一件事不是导入 AD20 直接转而是先找出主控、传感器、无线模块、电源四块区域理清连接关系。2.1 先从大结构上分两块板子资料里有两个硬件工程飞行器主控板和遥控器板。飞行器主控板上的核心器件有 STM32 主控、MPU6050 姿态传感器、气压计、NRF24L01 无线模块、四个 MOS 管驱动的空心杯电机接口遥控器板上同样有 STM32 和 NRF24L01只是把姿态传感器换成了摇杆电位器。模块飞行器板遥控器板主控STM32 最小系统STM32 最小系统姿态检测MPU6050I2C无用摇杆输入高度检测气压计板底透气孔无遥控链路NRF24L01SPINRF24L01SPI执行机构4路NMOS驱动空心杯电机摇杆电位器AD采集用户输入按键/-校准摇杆加按键注意气压计透气孔在操作说明里被专门提到说明这块板设计时把气压计放在板底并且留了开孔。你在 PCB 上找气压计位置时不要把它用保护胶带贴死否则高度数据会飘后续定高也稳不住。2.2 原理图阅读顺序与 STM32 最小系统拿到原理图以后我习惯先把所有网络名过一遍重点看 3V3、GND、MOSI、MISO、SCK、SDA、SCL。看到这些网络名基本就能确定 SPI 和 I2C 总线归谁。然后顺着 STM32 的电源引脚、复位引脚、SWD 下载引脚往下走。复位脚 RC 电路、BOOT0 下拉、去耦电容这三样缺一不可。很多从网上下载的原理图在这几个地方省元件板子能跑但抗干扰差尤其 NRF24L01 发射瞬间电流变化大电源纹波会把陀螺仪数据带偏。STM32 的 SWD 四个引脚SWDIO、SWCLK、GND、3.3V在飞控板原理图上通常有标注。如果你拿到的 PCB 没有印丝印可以在 PCB 上顺着 STM32 的 PA13/PA14 引脚找。调试这类小四轴我一般会用 ST-Link 加四根杜邦线直接点到主控背面比焊插座还稳定。飞控源码里通常把调试串口映射到 PA9/PA10也就是 USART1烧录后接一个 USB 转 TTL 模块就能看数据。飞控板电源是典型的小四轴布局电池电压通过板载 LDO 降压后给 STM32、MPU6050、NRF24L01 供电。空心杯电机启动瞬间压降很厉害旧电池可能从 3.7V 掉到 3.0V此时 LDO 输出跟着跌落主控就复位了。遇到“飞控上电但遥控器连不上”或者“目标转速一高就重启”先不要怀疑 NRF24L01去查电池内阻和 LDO 输出波形。这一步在原理图里也能看出来LDO 输入输出电容是否足够正常至少要 1uF 和 0.1uF 双电容并联。2.3 MPU6050 与 NRF24L01 接口细节MPU6050 的 SCL/SDA 需要上拉电阻原理图上一般是两个 4.7kΩ 电阻接到 3.3V。如果你发现 I2C 不稳定优先测量这两个点电压而不是怀疑代码。MPU6050 的 I2C 地址由 AD0 引脚决定AD0 接地时地址为 0x68接高时是 0x69。在调试助手里打印出原始数据前先用万用表量 AD0 的电平避免地址写错导致读回全 0。NRF24L01 走的是 SPI控制引脚有 CE、CSN、SCK、MOSI、MISO、IRQ。我一般会把 CE 和 CSN 放在普通 GPIO 上SCK、MOSI、MISO 用在 SPI 引脚上。原理图里如果 CE 和 CSN 接到了 SPI 的 NSS 脚要特别注意源码里是不是做了软件控制 NSS。有些国产模块把 CSN 当普通 IO 用初始化时先拉高再配置 SPI 复用这样反而稳定。在 AD20 里检查 PCB 时可以先把 DRC 跑一遍重点看几项电源线宽至少 0.5mm 以上信号线 0.2 到 0.3mm空心杯电机驱动 MOS 管到电机焊盘的连线尽量短而粗导通瞬间电流能达到 1 到 2A晶振、NRF24L01、MPU6050 周围不要走开关电源或电机 PWM 样式的长线。PCB 布局上MPU6050 尽量放在板子几何中心因为姿态解算算的是机体质心的角速度和加速度传感器偏离中心会引入额外的向心加速度并减小小幅振动辨识度NRF24L01 则放在板边天线端伸出去避免被地平面遮挡。这两条比走线是否美观重要得多。2.4 用 Cross Select 反向找器件如果拿到的是源工程在 AD20 里打开原理图和 PCB按Tools - Cross Select Mode进入交叉选中模式。点击原理图里的 U2PCB 里对应器件会高亮这样能很快分清哪颗是 MPU6050、哪颗是 NRF24L01。对一张完全陌生的飞控板我一般会先高亮晶振、磁珠、LDO 这几个小件确认电源网络再高亮 MOS 管确认四个电机驱动最后高亮传感器和无线模块。提示在原理图里看到电池插座旁边有两个电阻分压通常就是电压采样网络。很多源码会把这个采样结果换算成电压并做低电量提醒。如果你想在现有板上加这个功能直接用 ADC 读取分压点即可。3. 飞控源码解析MPU6050 读取、四元数姿态解算和串级 PID拿到源代码后首要任务是分辨哪个 Keil 工程是飞控、哪个是遥控器。从文件结构里能看到Crazepony和Remote两个前缀Crazepony.uvproj是飞控端Remote.uvproj是遥控器端。在 MDK 里不要同时打开两个工程因为两个工程的输出文件都放在Objects目录下名称可能冲突。3.1 从启动流程看飞控主循环飞控上电后主函数大致顺序是系统时钟初始化、延时函数初始化、GPIO 初始化、SPI 和 I2C 初始化、NRF24L01 初始化、MPU6050 初始化、传感器校准、主循环。代码里最影响启动的是传感器校准部分常见实现是在主循环里等 MPU6050 数据稳定如果 IMU 未校准四组 LED 会出现 M1/M2 和 M3/M4 交替闪烁。// 飞控主循环简化流程 int main(void) { delay_init(); gpio_init(); spi1_init(); // NRF24L01 使用 SPI1 i2c2_init(); // MPU6050 使用 I2C2 mpu6050_init(); nrf24l01_init(); radio_set_rx_mode(); // 飞控默认处于接收状态 while (1) { mpu6050_read_raw(raw); // 读陀螺仪加速度计原始数据 attitude_estimate(raw); // 姿态解算 if (radio_receive(cmd)) { // 收到遥控器数据 pid_control(cmd); // 串级 PID 计算 } motor_output(); } }这段代码对应源码里最常见的飞控循环。MPU6050 挂 I2C2、NRF24L01 挂 SPI1 并不是绝对事实但多数小四轴源码都是这个分配因为 I2C1 经常被片上的其它外设占用。你要移植到自己的板子上时先把这套外设关系在原理图上核对一遍尤其是 CE/CSN 对应的 GPIO改错一个脚就全乱了。3.2 MPU6050 原始数据读取与校验MPU6050 初始化要做的事退出睡眠模式、设置陀螺仪量程常见 ±2000°/s、设置加速度计量程常见 ±16g、配置数字低通滤波器。读取原始数据的 I2C 代码特别容易在初学时写得拖沓实际上一次多字节读就够了。// 读取 MPU6050 加速度计和陀螺仪原始值 void mpu6050_read_raw(int16_t *acc, int16_t *gyro) { uint8_t buf[14]; // 从 ACCEL_XOUT_H 开始连续读 14 个字节 i2c_read_regs(MPU6050_ADDR, 0x3B, buf, 14); acc[0] (buf[0] 8) | buf[1]; // X 轴加速度 acc[1] (buf[2] 8) | buf[3]; // Y 轴加速度 acc[2] (buf[4] 8) | buf[5]; // Z 轴加速度 gyro[0] (buf[8] 8) | buf[9]; // X 轴角速度 gyro[1] (buf[10] 8) | buf[11]; // Y 轴角速度 gyro[2] (buf[12] 8) | buf[13]; // Z 轴角速度 }寄存器 0x3B 是加速度计数据的高字节首地址后面依次是 ACCEL_YOUT、ACCEL_ZOUT、TEMP_OUT、GYRO_XOUT、GYRO_YOUT、GYRO_ZOUT。连续读可以保证同一时刻的六轴数据完整如果分三次单独读可能因为寄存器刷新导致某一轴数据时刻不一致飞控换算出来的姿态角会带上毛刺。3.3 姿态解算从四元数到欧拉角拿到六轴原始数据后源码里通常有两个选择直接读 MPU6050 的 DMP 四元数或者用互补滤波在 MCU 上算。小四轴一般用 DMP因为 MPU6050 内部解算完四元数后主控只需把它转成欧拉角CPU 占用率很低。// 由四元数求横滚角 roll 和俯仰角 pitch q0 quat[0]; q1 quat[1]; q2 quat[2]; q3 quat[3]; roll atan2f(2.0f * (q0*q1 q2*q3), 1.0f - 2.0f * (q1*q1 q2*q2)) * 57.3f; pitch asinf(2.0f * (q0*q2 - q3*q1)) * 57.3f; yaw atan2f(2.0f * (q0*q3 q1*q2), 1.0f - 2.0f * (q2*q2 q3*q3)) * 57.3f;注意asinf的入参必须在 [-1,1] 区间内否则会因为四元数误差出现 NaN。所以实际工程里我一般先做限幅float v 2.0f * (q0*q2 - q3*q1); if (v 1.0f) v 1.0f; if (v -1.0f) v -1.0f; pitch asinf(v) * 57.3f;角度单位转为度后PID 控制量的比例系数可以按度直接调。如果源代码里姿态角是弧度系数往往需要缩小约 57 倍换工程时很容易踩这个坑。3.4 串级 PID角度环与角速度环四轴悬停时外环控制角度内环控制角速度是标准写法。外环输出目标角速度内环输出电机补偿量。// 外环角度环周期 5ms exptd (target_roll - roll) * kp_angle; // 内环角速度环周期 1ms pid_out (target_rate - gyro_rate) * kp_rate ki_rate * integral_rate kd_rate * derivative_rate;外环 Kp 通常取 3 到 5内环 Kp 取 20 到 40Ki 取 0.2 到 0.5Kd 取 0.1 到 0.3。调参时先把内环 Kp 从小往大加直到机架出现高频抖动再回调 70%然后加外环 Kp角度回中会更快。如果内环和外环同时调很难判断抖动的来源。首飞前一定不要用大 Kp 值否则推油门瞬间就会翻机。3.5 电机混控与 PWM 输出空心杯电机通过 N 沟道 MOS 管开关PWM 频率常见 1kHz 到 8kHz。频率太低电机噪声大且会堵转频率太高 MOS 开关损耗增加。STM32 定时器直接输出 4 路 PWM电机油门要限制在 0 到 999并做缓启动。// 四路电机输出ch 范围 -500 ~ 500 m1 throttle_base pid_out; m2 throttle_base - pid_out; m3 throttle_base pid_out; m4 throttle_base - pid_out;这里throttle_base是遥控器油门值pid_out是 PID 修正量哪个电机加、哪个电机减取决于机架的对角线方向。换电机方向时只要 M1/M3 和 M2/M4 接反起飞时会直接翻。操作说明里强调 L 桨装 M1、M3R 桨装 M2、M4也是为了让气流方向和混控方向一致。4. 遥控器与 NRF24L01从摇杆 ADC 到解锁指令看完了飞控端再看遥控器端。遥控器本质是另外一块 STM32 板它读摇杆电位器、按键组装数据包通过 NRF24L01 发给飞控。两部分代码里都有一份 nrf24l01.c不要弄混遥控器端是发送模式飞控端是接收模式。4.1 摇杆映射四通道 ADC左摇杆负责油门和偏航右摇杆负责横滚和俯仰这是美国手布局。每个摇杆有 X、Y 两路电位器STM32 的 ADC 采集后从 0 到 4095 映射到 1000 到 2000 的油门区间或者映射到 -500 到 500 的角度控制量。// 遥控器摇杆读取转换后放入数据包 ch[0] adc_read(LEFT_X); // 油门 ch[1] adc_read(LEFT_Y); // 偏航 ch[2] adc_read(RIGHT_X); // 横滚 ch[3] adc_read(RIGHT_Y); // 俯仰摇杆电位器长期不用会氧化ADC 值出现跳变。遥控器开机后可以在界面上看四个通道数是否平滑如果跳就在电位器引脚并联一个小电容或加死区处理。解锁条件是左手油门最低同时右手横滚最左代码里要识别通道临界标志不能只靠连续值判断。4.2 NRF24L01 数据包定义NRF24L01 用 Enhanced ShockBurst 时收发双方要设置一样的频道、地址、速率和 CRC 长度。有效数据载荷一般不超过 32 字节。这个小四轴的遥控数据包很紧凑通常是 8 到 16 字节包含摇杆数据和按键标志。偏移字段长度说明0header1固定 0xAA用于校验1channels[0]2油门3channels[1]2偏航5channels[2]2横滚7channels[3]2俯仰9flags1bit0 解锁bit1 校准10crc81校验和发送数据包的代码非常短但要注意 CE 引脚的操作顺序// 发送遥控数据包 void radio_send_packet(uint8_t *buf, uint8_t len) { nrf24l01_ce_low(); // 写 payload 前拉低 CE nrf24l01_write_tx_payload(buf, len); nrf24l01_ce_high(); // 拉高 CE进入发送状态 }CE 拉低是确保在写 payload 时不会误触发发送写完后再拉高NRF24L01 会在 130us 内进入发送状态。发送完成后MAX_RT或TX_DS标志位置位代码里要读 STATUS 寄存器并清除对应位否则中断无法被第二次触发。如果遥控器端一直发送失败优先检查地址是否设置一致其次是检查 CE 引脚电平。4.3 解锁、上锁和 IMU 校准协议操作说明里的三步和源码逻辑直接对应遥控器上电后左手油门打到最低、右手横滚拉到最左。飞控检测到足够低的油门和横滚后通过 NRF24L01 收到 flags 中的解锁位四个电机进入怠速旋转。如果飞控 LED 出现 M1、M2 和 M3、M4 交替闪烁说明 IMU 校准值不正确。此时按遥控器上的“-”键飞控进入校准模式把当前 MPU6050 读到的加速度计平均值作为零偏。“”键用于直接解锁、上锁。一个容易忽略的细节IMU 校准时必须把飞机放在水平面上校准期间不要去碰遥控器摇杆否则会把横滚通道的零位也一起校准错。代码里这一阶段短时占用了 I2C 总线NRF24L01 的数据接收可能丢包所以校准按键按下后要保持 2 秒以上再松开。5. 编译烧录与排错SPI 波形、I2C 数据和电机方向验证这一章重点放在从源代码到实际起飞之间的调试。很多项目最后不是飞不起来而是“数据看起来对但电机不转”或“一推油门就翻”。这里给出几个经常能用上的验证手段。5.1 在 MDK 里分开编译两个工程飞控和遥控器是两个独立的 Keil 工程打开Crazepony.uvproj和Remote.uvproj时不要搞混。在Options for Target - Debug里选择 ST-Link 或 DAP 下载器Flash 算法选择 STM32F10x 系列对应容量。如果编译报缺包先在 Pack Installer 里安装 STM32F1 系列器件支持包。烧录完成后不要急着上桨先接 USB 转串口到飞控的 USART1 打印口波特率 115200。源码里的printf会输出 MPU6050 原始值和姿态角。如果数值全为 0检查 I2C 地址和传感器供电如果角度静止时漂动检查 MPU6050 附近是否被螺丝压到或电源纹波过大。5.2 NRF24L01 通信排错NRF24L01 最容易出现“假通信”的问题。用逻辑分析仪抓 SPI 波形是最直接的排查方式把 5 个通道分别接 CE、CSN、SCK、MOSI、MISO观察遥控器发送时 CSN 拉低的时长和 MOSI 上的数据是否与代码一致。没有逻辑分析仪时可以在飞控端打印状态寄存器// 在 radio_receive() 失败时打印状态寄存器 if (status (1 6)) { // RX_DR 位置位表示收到数据 nrf24l01_read_rx_payload(rx_buf, 32); printf(rx ok: %02x %02x\n, rx_buf[0], rx_buf[10]); } else { printf(rx wait, status%02x fifo%02x\n, status, fifo_status); }status的低 4 位和fifo的值能看出来是数据未到还是数据包已读空。推油门时串口能看到遥控数据说明无线链路已经通了。如果 RX 正常但电机不转问题大概率不在无线链路而在 PID 输出方向或者解锁逻辑。5.3 电机转向与首飞前检查不带桨空转时逐个点动验证转向。四轴对角线上两个电机同向旋转相邻电机反向。M1 到 M4 对应原理图上的哪颗电机要以 PCB 丝印为准。用一张小纸条靠近电机底部从进风方向可以判断转向。装桨时按操作说明把 L 桨装到 M1、M3R 桨装到 M2、M4然后用扎带固定好。首飞时把 Kp 调低 30%推油门到怠速后观察机身是否往某一侧偏再逐步加大油门。调好的串级 PID 参数要及时记录到源码注释里这样升级固件后可以直接恢复。本文还有配套的精品资源点击获取
返回列表