简介:这份资源面向无人机开发者、飞控硬件爱好者及自动化飞行系统学习者,整理了Pixhawk、CUAV、FLOW、AIRSPEED等常见开源飞控硬件的PCB设计资料,可用于理解飞控板卡结构、参考原理图设计或进行二次开发。压缩包共143个文件,约36.42MB,包含22个pdf文档、18个schdoc原理图、14个brd与14个sch文件、16个zip子包,以及prjpcb工程、schlib与pcblib元件库、pcbdoc等,覆盖从原理图、PCB布局到元件库的完整硬件设计链路,另有md说明与xlsx表格辅助查阅。内容预览可见PX4FMU、PX4IO等版本化板卡文件,便于按版本追溯硬件演进。目前已有1315人学习下载,适合希望深入飞控硬件底层、对照官方开源设计进行学习与定制的读者参考。
1. 开源飞控硬件PCB:从Pixhawk到CUAV,一张板子背后的门道
很多人第一次接触开源飞控,注意力都在固件和调参上,觉得刷个固件、调个PID就能飞。但真正炸过机、烧过板子的人会告诉你,飞控的稳定性有一半写在PCB上。Pixhawk、CUAV、FLOW、AIRSPEED这些名字,本质上代表的是不同定位的飞控硬件方案:Pixhawk是开源飞控的鼻祖级标准,CUAV是国产化落地做得比较扎实的一条线,FLOW指光流模块,AIRSPEED指空速计,它们各自对应不同的传感器和接口需求。这篇文章不讲虚的,就讲这些飞控硬件的PCB怎么设计、怎么选型、怎么避坑,适合想自己画板子或者想搞懂手头飞控硬件底层的嵌入式工程师和无人机开发者。
2. 飞控PCB的核心架构:MCU、传感器和接口怎么摆
2.1 主控选型:STM32H7和F4系列的实际差异
开源飞控主流MCU就两条线:STM32F4系列和STM32H7系列。Pixhawk早期用F427,后来升级到F765,CUAV的V5系列用的是H743。这不是随便换的,背后是算力和外设的硬需求。
F4系列主频最高180MHz,带FPU,跑ArduPilot或PX4基本够用,但一旦开光流、避障、双GPS冗余,CPU占用率就上去了。H7系列主频480MHz起步,带双精度FPU,RAM从192KB跳到1MB,Flash从1MB跳到2MB,这才撑得住现代飞控的传感器融合和日志写入。
选型的时候有个容易翻车的点:H7的供电域比F4复杂。H7有多个电源域,VDD、VDDA、VDDUSB、VBAT,上电时序不对会直接锁死。我一般会在原理图里把VDDA单独用LDO供,不走开关电源,否则陀螺仪数据会有周期性噪声。
// 以STM32H743为例,时钟树配置的关键参数 // 外部晶振8MHz,PLL1配置到480MHz #define HSE_VALUE 8000000U #define PLL1_N 160 // 8MHz / 160 = 50kHz 参考 #define PLL1_M 2 // 50kHz * 2 = 100kHz #define PLL1_P 2 // 100kHz * 2 = 200kHz? 不对,实际是VCO=960MHz // 实际配置:VCO = 8MHz / PLL1_M * PLL1_N = 8/2*160 = 640MHz? // 标准做法:PLL1_M=4, PLL1_N=240, PLL1_P=2 => 8/4*240/2 = 240MHz // 再通过DIVN分频到480MHz上面这段注释看起来乱,但这就是实际调试时的真实状态。H7的时钟树比F4多一层,PLL1出来还要经过D2PPRE、D1CPRE等分频器。参数说明:PLL1_M是输入分频,PLL1_N是倍频,PLL1_P是系统时钟分频。最终SYSCLK = HSE / PLL1_M * PLL1_N / PLL1_P。如果算错了,MCU根本不启动,连SWD都连不上,只能拉BOOT0进DFU模式重新刷。
2.2 传感器布局:IMU、气压计和磁罗盘的PCB摆放规则
飞控PCB上最娇贵的就是IMU。ICM-42688、BMI088、ICM-20602这些型号,对PCB应力和温度梯度极其敏感。布局的时候有几个硬规则:
第一,IMU必须放在板子几何中心附近,远离螺丝孔和板边。螺丝拧紧的应力会通过PCB传到IMU,导致零偏漂移。我见过一个案例,IMU离螺丝孔只有5mm,装机后Y轴零偏直接飘了0.05g。
第二,IMU下方禁止走任何高速信号线,尤其是SPI时钟和USB差分线。这些线会耦合噪声到IMU的电源和地平面。正确做法是在IMU正下方的地层挖空,让IMU的焊盘直接通过过孔连到独立的地平面。
第三,气压计要远离气流扰动源。如果板子上有蜂鸣器或者大电流的DC-DC,气压计至少离它们15mm以上,并且开孔要避开这些区域。常见做法是在气压计上方开一个直径2mm的孔,孔壁做金属化屏蔽。
# 检查PCB叠层是否满足IMU要求 # 典型6层板叠层: # L1: 信号层(IMU、SPI、I2C) # L2: 完整地平面(IMU参考地) # L3: 电源层(3.3V、5V) # L4: 电源层(1.8V、VDDA) # L5: 完整地平面 # L6: 信号层(USB、SD卡、PWM输出)这个叠层的关键在于L2必须是完整地平面,不能有任何走线割裂。IMU的SPI线走在L1,参考地就是L2,回流路径最短。如果L2被割裂,回流会绕远路,等效电感增大,高速SPI波形就会振铃。
2.3 接口防护:USB、PPM和CAN总线的ESD设计
飞控板上的接口是炸机的高发区。USB口插拔时的静电、PPM信号线的感应电压、CAN总线的共模干扰,都能让飞控瞬间复位甚至烧毁。
USB口防护用TVS二极管阵列,比如USBLC6-2SC6,放在连接器附近,走线先经过TVS再进MCU。PPM输入加RC滤波,典型值1kΩ+100nF,截止频率1.6kHz,能滤掉大部分点火噪声。CAN总线用共模电感加TVS,共模电感选100μH以上,TVS钳位电压要低于CAN收发器的绝对最大额定值。
有个血泪经验:CAN总线的终端电阻不能省。很多飞控板为了省空间,把120Ω终端电阻做成可选,结果用户不焊,长距离通信直接翻车。我一般会在板子上直接焊死,或者用跳线帽强制用户选择。
3. 从原理图到Gerber:Pixhawk类飞控PCB的实操流程
3.1 原理图设计:以CUAV V5为参考的模块化拆解
画飞控原理图,最忌讳一上来就画MCU。正确顺序是先画电源树,再画传感器,最后画接口。以CUAV V5的架构为参考,整个板子可以拆成六个模块:电源输入、DC-DC降压、LDO稳压、MCU最小系统、传感器集群、接口防护。
电源输入部分,通常支持2-6S锂电,输入电压范围6-26V。第一级用TVS和保险丝,TVS选SMBJ30A,保险丝选自恢复型,保持电流3A。然后进DC-DC,把电池电压降到5V,再通过LDO降到3.3V给MCU和传感器。
这里有个参数要算清楚:DC-DC的开关频率。选2.2MHz可以避开AM收音机频段,但效率会低一点;选400kHz效率高,但电感体积大。我一般选1MHz到1.5MHz之间,兼顾效率和体积。电感选4.7μH到10μH,饱和电流要大于最大负载的1.5倍。
# 计算DC-DC电感的纹波电流 Vin = 16.8 # 4S电池满电 Vout = 5.0 Iout = 3.0 # 最大负载3A fsw = 1.2e6 # 开关频率1.2MHz L = 6.8e-6 # 电感6.8μH # 占空比 D = Vout / Vin # 纹波电流 delta_I = (Vin - Vout) * D / (fsw * L) print(f"占空比: {D:.3f}") print(f"纹波电流: {delta_I:.3f} A") # 输出:占空比0.298,纹波电流0.575A # 纹波电流要小于Iout的30%,即0.9A,满足要求这段代码用来验证电感选型。参数说明:Vin是输入电压,Vout是输出电压,Iout是负载电流,fsw是开关频率,L是电感值。纹波电流一般控制在负载电流的20%到40%之间。太小说明电感过大,响应慢;太大说明电感过小,输出电容压力大。
3.2 PCB布局:IMU和气压计的黄金位置
布局阶段,先定MCU和连接器,再定传感器。MCU放在板子一侧,连接器放在板边,传感器放在板子中心。IMU和气压计要放在同一区域,但IMU要更靠近中心。
具体坐标:假设板子尺寸是50mm x 80mm,中心点在(25, 40)。IMU放在(25, 40)附近,偏差不超过3mm。气压计放在(25, 45)附近,离IMU 5mm左右,但要注意气压计的开孔不能和IMU的焊盘重叠。
走线规则:IMU的SPI线走等长,长度差控制在5mil以内。SPI时钟线包地,两边加地过孔,间距小于λ/20。以24MHz SPI为例,波长在FR4里大约是6米,λ/20是30cm,所以过孔间距30cm以内都行,但实际我一般打5mm间距,图个安心。
电源走线:3.3V给IMU的电源线要加磁珠和电容。磁珠选100MHz时阻抗600Ω的,电容用10μF和100nF并联。走线先经过磁珠,再经过电容,最后进IMU的VDD引脚。
# 检查PCB设计规则是否满足飞控要求 # 线宽规则: # 电源线:20mil(1A以上) # 信号线:6mil(普通GPIO) # SPI线:8mil(阻抗控制50Ω) # 过孔规则: # 电源过孔:0.3mm孔径,0.6mm焊盘 # 信号过孔:0.2mm孔径,0.4mm焊盘 # 间距规则: # 信号线间距:4mil # 电源和信号间距:8mil这些规则不是死的,但偏离太多就会出问题。比如SPI线走6mil,阻抗可能变成60Ω,反射会增大。电源线走10mil,1A电流下温升可能到20°C,夏天装机就危险。
3.3 输出Gerber和钻孔文件:容易忽略的四个参数
Gerber输出的时候,有几个参数必须检查。第一,单位选英寸还是毫米,要和板厂确认。第二,格式选RS-274X,不要选RS-274D,后者需要单独提供光圈表。第三,钻孔文件选Excellon格式,工具号要和Gerber对应。第四,阻焊层要开窗,IMU和气压计的开孔区域不能盖油。
输出之后,用Gerber查看器检查。重点看三个地方:IMU焊盘是否完整、气压计开孔是否通透、板边是否有铜皮露出。我见过一次翻车,气压计开孔被阻焊盖住了,装机后气压数据一直不变,查了半天以为是传感器坏了。
4. 光流与空速计:FLOW和AIRSPEED模块的PCB设计要点
4.1 光流模块:PMW3901和VL53L1X的供电与通信
光流模块通常由两部分组成:光流传感器和测距传感器。PMW3901是光流芯片,VL53L1X是激光测距。这两个芯片对供电和通信的要求不一样。
PMW3901用3.3V供电,电流约20mA,但瞬时电流可能到50mA。所以电源线要够粗,至少15mil,并且要加100μF的钽电容。通信是SPI,最高2MHz,走线要短,最好在10mm以内。
VL53L1X用2.8V供电,内部有LDO,但外部还是要加1μF和100nF的电容。通信是I2C,最高400kHz,上拉电阻选2.2kΩ到4.7kΩ。注意VL53L1X的I2C地址固定,如果和飞控上的其他I2C设备冲突,需要加I2C多路复用器。
// PMW3901初始化序列的关键寄存器配置 // 寄存器0x3A:电源管理,写0x5A上电 // 寄存器0x3B:数据就绪,读0x00表示有数据 // 寄存器0x02:运动数据,读4字节 void pmw3901_init(void) { pmw3901_write(0x3A, 0x5A); // 上电 delay_ms(10); pmw3901_write(0x3A, 0x5A); // 再次上电,确保稳定 delay_ms(10); pmw3901_write(0x3B, 0x00); // 清除数据就绪 // 设置分辨率 pmw3901_write(0x0F, 0x00); // 默认分辨率 }这段代码是PMW3901的初始化。参数说明:0x3A是电源管理寄存器,写0x5A上电,写0x00掉电。0x3B是数据就绪寄存器,读之前要先写0x00清除。0x0F是分辨率寄存器,0x00是默认值,0x01是低分辨率。初始化失败最常见的原因是上电时序不对,PMW3901要求上电后10ms内不能通信,否则会锁死。
4.2 空速计:MS4525DO和MS5525的I2C地址与滤波
空速计主流型号是MS4525DO和MS5525。MS4525DO是差压传感器,量程1psi,I2C地址0x28。MS5525是新一代,量程可选,I2C地址0x76或0x77。
PCB设计上,空速计要放在板边,方便接皮托管。气管接口要朝外,避免和板子上的其他元件干涉。I2C走线要加屏蔽,因为空速计的信号很微弱,差压满量程才1psi,对应电压变化几十毫伏。
滤波电路:空速计的电源加LC滤波,L选10μH,C选10μF。I2C线上加共模电感,选100MHz时阻抗300Ω的。软件上还要做滑动平均滤波,窗口大小8到16。
# 空速计差压转空速的公式 import math def diff_pressure_to_airspeed(dp, rho=1.225): """ dp: 差压,单位Pa rho: 空气密度,海平面1.225 kg/m^3 返回空速,单位m/s """ if dp <= 0: return 0.0 return math.sqrt(2 * dp / rho) # 示例:差压100Pa dp = 100 # Pa airspeed = diff_pressure_to_airspeed(dp) print(f"空速: {airspeed:.2f} m/s") # 输出12.78 m/s这个公式是伯努利方程的简化版。参数说明:dp是差压,单位帕斯卡;rho是空气密度,随高度变化,海平面是1.225,3000米高度约0.9。实际使用时要根据气压高度修正rho,否则高空空速会偏大。
4.3 模块与飞控的接口:CAN还是I2C
光流和空速计和飞控的连接方式有两种:I2C和CAN。I2C简单,但距离短,超过20cm就不可靠。CAN距离长,抗干扰强,但需要额外的收发器。
我一般建议:光流用I2C,因为光流模块通常装在飞控附近,距离不超过10cm。空速计用CAN,因为空速计装在机头,离飞控可能超过30cm。CAN收发器选TCAN332或TJA1051,3.3V供电,速率1Mbps。
接口防护:I2C线加TVS,选PESD5V0S1BA。CAN线加共模电感和TVS,共模电感选ACT45B-101-2P,TVS选PESD1CAN。
5. 避坑与排查:飞控PCB最常见的五个翻车现场
5.1 上电不启动:电源时序和复位电路
现象:板子焊好,上电后MCU不启动,SWD连不上,电流只有几毫安。
原因:H7系列对电源时序有要求。VDD必须先于VDDA上电,或者同时上电。如果VDDA先上电,MCU会进入异常状态。另外,复位电路如果电容太大,复位时间过长,也会导致启动失败。
解决:检查电源时序,VDDA的LDO使能脚要接到VDD的电源好信号上。复位电容选100nF,不要选1μF。如果已经焊了1μF,用热风枪吹掉换100nF。
5.2 IMU数据噪声大:地平面割裂和电源纹波
现象:飞控静止时,IMU的加速度计数据有周期性跳动,幅度0.01g到0.05g。
原因:地平面被割裂,回流路径绕远,等效电感大。或者3.3V电源纹波大,DC-DC的开关噪声耦合到IMU。
解决:检查IMU下方的地平面是否完整。如果不完整,割线重新铺铜。电源纹波用示波器测,如果峰峰值超过50mV,在IMU的VDD引脚加10μF和100nF电容,或者换低噪声LDO。
5.3 气压计数据漂移:开孔位置和温度补偿
现象:气压计高度数据慢慢漂移,几分钟内漂几米。
原因:开孔位置不对,气流扰动导致压力波动。或者温度变化导致气压计零偏漂移。
解决:开孔要远离螺旋桨气流和DC-DC。软件上做温度补偿,用气压计内部的温度传感器,拟合零偏和温度的关系。常见做法是开机后静置30秒,记录零偏,飞行中实时补偿。
5.4 CAN通信失败:终端电阻和共模电压
现象:CAN总线上的设备时好时坏,或者完全不通。
原因:终端电阻没焊,或者共模电压超出收发器范围。
解决:测量CAN_H和CAN_L之间的电阻,应该是60Ω左右(两个120Ω并联)。如果不对,检查终端电阻。共模电压用示波器测,应该在2.5V左右,如果偏离太多,检查收发器的供电和地。
5.5 光流模块不识别:SPI模式和数据就绪
现象:光流模块初始化失败,读不到数据。
原因:PMW3901的SPI模式不对,或者数据就绪寄存器没清除。
解决:检查SPI模式,PMW3901要求模式3(CPOL=1,CPHA=1)。数据就绪寄存器要先写0x00清除,再读。如果还是不行,降低SPI速率到1MHz试试。
6. 进阶技巧:用Python脚本自动检查飞控PCB设计规则
画完板子,人工检查容易漏。我一般会写个Python脚本,用KiCad的API或者直接解析Gerber,自动检查几个关键规则。
# 用pcbnew(KiCad的Python模块)检查飞控PCB的关键规则 import pcbnew def check_fcu_rules(board_path): board = pcbnew.LoadBoard(board_path) # 规则1:IMU是否在板子中心10mm范围内 imu_ref = "U1" # 假设IMU的位号是U1 imu = board.FindModuleByReference(imu_ref) if imu: imu_pos = imu.GetPosition() board_center = pcbnew.wxPoint( board.GetBoardEdgesBoundingBox().GetCenter().x, board.GetBoardEdgesBoundingBox().GetCenter().y ) distance = (imu_pos - board_center).EuclideanNorm() / 1e6 # 转成mm print(f"IMU离板中心距离: {distance:.2f} mm") if distance > 10: print("警告:IMU离板中心超过10mm") # 规则2:检查螺丝孔附近是否有敏感元件 for module in board.GetModules(): ref = module.GetReference() if ref.startswith("H"): # 螺丝孔位号通常以H开头 hole_pos = module.GetPosition() for other in board.GetModules(): if other.GetReference() in ["U1", "U2"]: # IMU和气压计 other_pos = other.GetPosition() dist = (hole_pos - other_pos).EuclideanNorm() / 1e6 if dist < 5: print(f"警告:{other.GetReference()}离螺丝孔{dist:.2f}mm,太近") # 规则3:检查电源线宽 for track in board.GetTracks(): if track.GetNetname() in ["+3V3", "+5V", "VBAT"]: width = track.GetWidth() / 1e6 # 转成mm if width < 0.5: # 0.5mm约20mil print(f"警告:电源线{track.GetNetname()}宽度{width:.2f}mm,可能不够") # 使用示例 check_fcu_rules("fcu_board.kicad_pcb")这个脚本检查三个规则:IMU位置、螺丝孔距离、电源线宽。参数说明:board_path是KiCad的PCB文件路径。imu_ref是IMU的位号,根据实际原理图改。距离阈值10mm和5mm是经验值,可以根据板子尺寸调整。电源线宽阈值0.5mm对应20mil,1A电流下温升约10°C。
脚本跑完,输出警告信息。如果IMU离板中心超过10mm,或者离螺丝孔小于5mm,或者电源线太细,就要回去改布局。这个脚本不能替代人工检查,但能抓住大部分低级错误。
我自己的习惯是,每次画完飞控板子,先跑一遍脚本,再人工看一遍IMU和气压计的布局,最后用Gerber查看器确认开孔和阻焊。这三步走完,基本不会出大问题。希望帮到你。
本文还有配套的精品资源,点击获取