ARTICLE DETAIL

资讯详情

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

机载电脑与飞控串口通信实战:UART读取IMU数据踩坑全记录

机载电脑与飞控串口通信实战:UART读取IMU数据踩坑全记录 如果你试过把树莓派、香橙派、Jetson这类机载电脑接到飞控上大概率遇到过这种场景飞控在QGroundControl里一切正常指示灯双闪姿态数据刷刷走但一接上机载电脑的串口就什么都读不到。最近我正好把手头三套设备——香橙派5max、地平线旭日X3派allspark1、Orin NX载板——逐一和Pixhawk 6C飞控做了串口通信实测目标就一个稳定读到飞控的IMU数据。三套平台踩的坑完全不同但底层套路是一致的串口配置、接线电平、协议波特率、系统权限四关缺一不可。这篇文章把整个过程的完整命令、参数和踩坑记录都放出来新手可以直接照着抄老手也能看看有没有自己没注意到的细节。1. 通信方案整体拆解为什么机载电脑和飞控都得靠UART1.1 UART在飞控通信里的地位很多人一上手就想着用USB直连飞控或者干脆用网络图传把数据推下来这当然能跑通但在真实整机项目里UART串口仍然是机载电脑和飞控之间最皮实、最可控的物理链路。原因不复杂UART协议简单到了极致一根TX一根RX一根GND就能工作不需要握手协议不依赖网络栈线序对了、电平对了、波特率对了剩下就是数据流的事。飞控预留的TELEM口、机载电脑预留的GPIO排针串口都是为这条链路准备的。MAVLink协议本身也不挑物理层不管是UART、UDP还是TCP它都可以跑但机载电脑和飞控在大多数装机场景里物理距离不到半米用串口几乎零延迟、零丢包、不占带宽。尤其是读取IMU这类高频数据姿态消息一秒钟能刷几十上百条串口完全扛得住。相比之下走USB转串口当然也可以但多一道转换就多一个驱动坑后面我会专门讲这个。1.2 MAVLink里的IMU数据藏在哪儿搞清楚数据从哪来排查问题才有方向。飞控里的IMU传感器加速度计、陀螺仪、磁力计由飞控固件轮询经过姿态解算之后通过MAVLink消息发出去。跟IMU直接相关的消息主要有这么几条RAW_IMU包含加速度计、陀螺仪、磁力计的原始测量值频率一般比较高适合做数据记录和传感器级调试。SCALED_IMU / SCALED_IMU2 / SCALED_IMU3经过量程归一化后的IMU数据适合直接做计算。ATTITUDE已经解算出来的欧拉角roll / pitch / yaw这是大多数人真正关心的数据。IMU_STATUS个别固件会带状态信息用得少。拿Pixhawk 6C举例默认配置下TELEM口往外发的不仅仅是IMU数据而是一整路的MAVLink数据流包含心跳、姿态、GPS、电池等。机载电脑通过串口收到这些字节流之后用pymavlink库做协议解析再从里面筛选出你关心的消息类型即可。1.3 三套平台各有各的脾气这次实测的三套机载电脑代表了目前DIY无人机、机器人和自动驾驶小车领域最常见的三类平台平台芯片典型串口设备节点主要坑点香橙派5max瑞芯微RK3588S/dev/ttyS5, /dev/ttyS740pin排针UART需要手动改overlay启用allspark1旭日X3派地平线旭日X3/dev/ttyS0, /dev/ttyUSB0飞控TELEM口流控、USB转串口驱动被系统抢占Orin NX载板NVIDIA Jetson Orin NX/dev/ttyTHS1, /dev/ttyTHS2默认UART被系统console占用改pinmux麻烦三套平台虽然硬件完全不同但串口通信的底层原理一致。我建议任何新手在开始接线之前先把这三条核心规则刻在脑子里第一GND必须共地所有信号的电平参考地必须是同一个第二飞控的TELEM口电平是3.3V不能拿5V的串口直接怼第三波特率不匹配时串口不会报错只会给你乱码或者干脆没反应。这几条后面会反复出现。2. 香橙派5max启动UART串口改overlay、接线、读IMU一次跑通2.1 先搞清楚香橙派5max的串口资源香橙派5max用的是瑞芯微RK3588S这颗芯片的串口资源非常丰富硬件上引出到40pin排针的UART有好几组。但是默认系统镜像加载的时候大部分UART引脚并不是作为串口功能工作的它们可能被复用为GPIO、I2C、SPI或者PWM。这就是很多新手卡住的第一道门槛板子上明明印着UART字样打开系统却根本找不到对应的串口设备节点。以我手上这块板子为例40pin排针上我最终用的是UART5的引脚对应的设备节点是/dev/ttyS5。系统默认并不会自动生成这个节点需要在启动配置里告诉设备树把某几个引脚复用为UART功能。香橙派用的是overlay机制跟树莓派的config.txt思路类似。2.2 修改overlay启用UART5先把系统更新到最新避免镜像自带的overlay文件太老导致兼容问题sudo apt update sudo apt upgrade -y然后打开/boot/orangepiEnv.txt这个文件里控制启动时加载哪些设备树overlaysudo nano /boot/orangepiEnv.txt找到overlays这一行把需要的UART加进去。以我的板子为例我要启用UART5对应40pin上的物理引脚最终配置是这样overlaysuart5-m0有些版本的镜像里UART5还有uart5-m1、uart5-m2等不同引脚映射组具体用哪个要看40pin排针的丝印和原理图。我的经验是先查板子的原理图确认你要用的物理引脚属于第几组mux再决定overlay名字而不是随便猜。改完之后更新内核启动配置并重启sudo update-initramfs -c -k $(uname -r) sudo reboot重启后检查设备节点是否出现ls -l /dev/ttyS*正常的话应该能看到/dev/ttyS5同时可以用下面的命令确认引脚复用是否生效cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep uart52.3 接线和loopback自测在接飞控之前强烈建议先做一次串口回环测试。所谓回环测试就是把板子自己的TX和RX短接然后往串口发数据看能不能原样收回来。这一步能帮你排除引脚复用配置错误、设备节点异常、线材损坏等基础问题避免后面接了飞控排查半天分不清是飞控的问题还是板子的问题。飞控端我用的是Pixhawk 6C的TELEM2口引脚定义是标准的六针1-VCC、2-TX、3-RX、4-CTS、5-RTS、6-GND。注意TELEM口的TX要接香橙派5max的RXTELEM口的RX要接香橙派5max的TX别接成同向了。香橙派5max的UART5引脚在另一侧排针上TX和RX我分别接到了40pin的第33脚和第35脚具体以你用的overlay组和原理图为准。GND必须接这是串口通信的生命线。接线确认无误后用Python快速验证回环import serial import time ser serial.Serial(/dev/ttyS5, baudrate921600, timeout1) ser.write(bkakaxi) time.sleep(0.1) data ser.read(6) print(received:, data) ser.close()如果打印出来的received: bkakaxi说明串口通路完全正常可以接飞控了。如果收不到数据先查共地再查线序最后再回去查overlay。注意串口回环测试通过只能说明机载电脑这一端的串口是好的并不代表飞控那边一定能通。飞控的TELEM口默认可能开着硬件流控这是一个大坑下一节我细讲。2.4 实测读取Pixhawk 6C的IMU数据飞控端我提前在QGroundControl里把SER_TEL2_BAUD参数设置为921600这是TELEM2口的波特率默认值是57记得改成921单位是Baud*1000所以写921就代表921600。同时把SER_TEL2_MAV确保是MAVLink2。这两个参数不设对后面所有数据都是乱码。机载电脑端用pymavlink读取姿态数据pip install pymavlink pyserial然后写一段最简读取脚本from pymavlink import mavutil master mavutil.mavlink_connection(/dev/ttyS5, baud921600) master.wait_heartbeat() print(Heartbeat received, system connected) while True: msg master.recv_match(type[ATTITUDE, RAW_IMU], blockingTrue) if msg.get_type() ATTITUDE: print(froll:{msg.roll:.3f} pitch:{msg.pitch:.3f} yaw:{msg.yaw:.3f}) elif msg.get_type() RAW_IMU: print(faccel: {msg.xacc} {msg.yacc} {msg.zacc})第一次跑通的时候终端里刷刷刷地滚出姿态数据那种感觉还是很爽的。这里有个小提示recv_match()的type参数传的是list它会在内部做消息匹配比手动写if msg.get_type() ATTITUDE再过滤要高效一些。我上面两种方式都写了跑起来效果一样新手可以先用前者感受一下完整的消息流。实际过程中还发现一个细节香橙派5max的串口默认流控是关闭的但飞控TELEM口的硬件流控根据飞控型号和固件版本不同可能是开启的。如果接上后能收到心跳但收不到正常的MAVLink消息流或者消息断断续续大概率就是流控问题。解决办法是把TELEM2口的RTS和CTS两根线短接或者把飞控参数里的流控关掉。3. allspark1与Pixhawk 6C通信踩坑、出坑全过程3.1 看似简单的接线隐藏着最深的坑allspark1是地平线旭日X3派的开发板产品名它自带40pin排针也有原生UART可用。我最初的计划是直接复用香橙派5max的经验选一组UART配上波特率读IMU数据。结果实践告诉我换一块板子坑的位置完全不一样。第一个坑出现在接线阶段。Pixhawk 6C的TELEM口引脚里除了TX、RX、GND还有CTS和RTS两根流控线。我自己焊的转接线根本没有接这两根线以为没用结果飞控那边死活不往外发数据。后来查了Pixhawk 6C的硬件文档才知道TELEM口的硬件流控默认是开启的飞控在检测到CTS有效之前不会把数据往外吐。这个设计是为了防止高速通信时缓冲区溢出但对DIY玩家来说就是赤裸裸的坑。出坑方案如果你用的转接线没有接CTS/RTS最简单的办法是把TELEM口上RTS和CTS两根针用杜邦线直接短接。短接之后飞控会认为“对端准备好了”数据就会正常往外发。如果你用USB转串口模块可以买那种引出了CTS/RTS的模块或者直接在飞控参数里把流控关掉。以Pixhawk 6C为例TELEM2对应的是SER_TEL2_OPTIONS参数里的“Flow Control”位默认是启用的把它关掉并重启飞控即可。3.2 USB转串口的驱动和ModemManager问题我第二轮尝试图省事直接用了一根CP2102的USB转串口线接飞控插到allspark1的USB口上。结果设备节点倒是出来了/dev/ttyUSB0但一打开就收到一堆东西然后马上断掉再打开就开不了。排查了半天发现是经典的ModemManager占用问题。Linux桌面版系统会自动启动ModemManager服务这个服务会主动探测USB串口设备一旦发现设备有响应就把它当成调制解调器接管导致你的程序无法绑定串口。Allspark1官方系统默认装了ModemManager很多人在树莓派上也遇到过。出坑方式很暴力直接停掉并禁用服务sudo systemctl stop ModemManager sudo systemctl disable ModemManager如果你是Ubuntu Server系统大概率没有这个服务那就跳过这一步。事实上服务器版本没有桌面环境这种“串口被抢”的问题会少很多。我做自动驾驶小车项目时强烈推荐直接用Server版系统少很多幺蛾子。另外如果你的USB转串口芯片是FT232、FT231X、CP2102这类Linux内核通常自带驱动插上就能识别。但个别芯片型号比如FT231X在老内核上可能识别成未知设备建议先把内核升到5.10以上或者用lsusb查看芯片ID再手动加载驱动模块。3.3 波特率乱码的真相不是波特率本身是飞控固件的默认值把流控和ModemManager两个坑填完之后我以为就大功告成了。结果一跑脚本收到的全是乱码。这个问题看起来像波特率不对但我明明在QGC里把SER_TEL2_BAUD设成了921。这里就涉及Pixhawk固件一个容易忽略的细节TELEM口的“默认波特率”由固件参数决定但飞控重新上电后参数一定生效问题往往出在“你以为你保存了但没实际写入”。在QGC里修改参数后必须点击右上角的“写入”整个参数列表右下角有红色高亮“未写入修改”才算改成功。另外TELEM1和TELEM2口默认波特率不一样TELEM1通常默认57600TELEM2通常默认921600。如果你插的是TELEM1却在代码里用921600去连一样会产生乱码。我用逻辑分析仪抓了一下波形确认飞控实际输出的波特率确实是921600但pymavlink那边收到乱码。最后发现是我自己的问题——在脚本里把baud参数写成了921600之外的数字。对就是这么低级。allspark1的Python串口库对波特率参数有校验非法值会静默降级到9600而飞控那边还在拼命按921600往外发自然全是乱码。心得调试串口乱码的时候别一上来就怀疑硬件。先在飞控上用地面站看实际波特率参数再到机载电脑端用python3 -c import serial; print(serial.Serial(/dev/ttyS0, 921600))确认串口能正常打开最后才考虑接线和干扰问题。顺序反了容易把简单问题复杂化。4. Orin NX载板与飞控通信从默认不可用到改到位4.1 Orin NX的串口资源分布Orin NX是NVIDIA Jetson家族里性能很猛的一款核心模组但它本身不带任何排针所有IO都从底部金手指引出具体能用到哪些口完全取决于你的载板设计。所以“Orin NX与飞控通信”这个事真正要面对的不是核心模组而是载板。市面上的Orin NX载板通常会引出一排40pin或26pin的扩展接口里面包含UART、I2C、SPI、GPIO。不同载板的串口引脚定义差异很大甚至同样标着UART1在不同载板上对应的SoC内部uart_id都可能不一样。我手上的载板引出的UART对应的设备节点是/dev/ttyTHS1。4.2 解决默认UART被系统console占用Jetson平台的坑和香橙派5max完全不同。香橙派是“串口设备节点不生成”Jetson是“设备节点生成了但被系统占用”。Jetson的Linux系统默认会把/dev/ttyTHS0用作调试串口也就是你通过USB转串口连到电脑看到启动日志用的那个口。如果你把飞控接到/dev/ttyTHS0上开机会输出一堆内核日志而且你打开这个串口时会收到序列化器调试信息根本没法作正常业务通信。出坑思路有几个换一个没有被console占用的UART这是最简单最推荐的做法。如果要强行用被占用的UART需要修改内核启动参数console把console从对应串口移除再更新默认的/etc/nv_tegra_release环境配置操作比较麻烦而且容易导致以后想连调试串口都连不上。我选择了换口把飞控接到载板另一组UART上对应/dev/ttyTHS1。同时确认这个口没有被/etc/systemd/system/serial-getty.service占用——Jetson的系统默认会对调试串口跑一个getty服务如果你打开的正是这个口系统会让你先输账号密码然后才能输入串口数据流会被完全破坏。检查方法sudo systemctl list-units | grep serial如果有serial-gettyttyTHS0.service之类的东西在跑只影响对应的ttyTHS0不影响同一UART控制器的其他线路。但保险起见用ttyTHS1这种非默认口才是最舒心的选择。4.3 使用device tree overlay配置UART引脚换了/dev/ttyTHS1之后还发现一个问题系统里能看到设备节点但引脚没有正确复用成UART功能TX/RX没有输出GPIO也读不到。Jetson平台管这套东西叫pinmux默认配置在设备树里。NVIDIA官方提供了pins工具可以临时修改但重启就失效。我最终采用的方法是直接修改设备树overlay# 查看当前pinmux状态 sudo busybox devmem 0x0242901c 32 # 使用opensdboot工具链重新编译设备树或者手动写一个新的overlay这个过程比较繁琐不同载板的设备树源文件也不一样没法给出一个通用命令。但有几个经验可以分享优先查载板的用户手册正规厂商的载板都会明确写清楚每个UART引脚对应的设备节点名和pinmux配置方法比自己去破译地垫片快得多。如果载板自带pins配置脚本优先用官方工具例如sudo /opt/nvidia/jetson-io/config-by-pin.py可以交互式把某个引脚切换成UART功能。改完设备树后需要sudo update-initramfs -u并重启让新的pinmux配置加载。一切配置好之后用Python验证import serial ser serial.Serial(/dev/ttyTHS1, baudrate115200, timeout1) ser.write(btest\n) data ser.readline() print(data)这边要注意Jetson平台的serial模块打开串口后如果TX和RX没有接对或者引脚没有正确复用write()操作不会报错但你收不到任何数据。所以我在这里也同样建议先做loopback自测不要一上来就接飞控。4.4 Orin NX读飞控IMU数据的最终流程Orin NX上读IMU数据的代码和香橙派5max几乎一模一样只是设备节点和波特率不同from pymavlink import mavutil master mavutil.mavlink_connection(/dev/ttyTHS1, baud921600) master.wait_heartbeat() print(link ok) while True: msg master.recv_match(typeRAW_IMU, blockingTrue) if msg: print(faccel(x,y,z): {msg.xacc}, {msg.yacc}, {msg.zacc}) print(fgyro(x,y,z): {msg.xgyro}, {msg.ygyro}, {msg.zgyro})跑通之后Orin NX能稳定收到IMU原始数据后续无论是做SLAM、VIO还是做简单的姿态控制数据源都有了。这里还有一个额外经验Orin NX的USB口供电能力比香橙派强不少但如果飞控和机载电脑的电源地不是同一套串口信号会漂移严重时可能烧毁接口。强烈建议在接线时用万用表先测一下两边的GND电位差理想情况应该是0V最多不要超过0.3V超过这个值说明电源隔离有问题先解决供电再做通信。5. 串口通信问题速查表与常用排查思路5.1 常见问题排查速查表把这次实测中遇到的问题整理成一张表方便大家直接联查现象可能原因快速排查方法解决办法打开串口报Permission denied当前用户不在dialout组id查看用户组sudo usermod -aG dialout $USER重新登录能打开串口但一片空白波特率不匹配用逻辑分析仪抓波形或看飞控参数确认SER_TELx_BAUD与代码里一致收到乱码波特率错、接地不良、TX/RX接反缩小数据范围测试检查线序检查共地核对波特率飞控不往外发数据TELEM口硬件流控开启且CTS无效短接CTS/RTS或用示波器看TX波形短接RTS/CTS或把流控参数关掉串口设备节点不存在引脚没有复用成UART功能ls /dev/ttyS*修改overlay或device tree串口被系统getty占用打开了默认console串口systemctl list-unitsgrep serialUSB转串口插上没节点ModemManager占用或驱动缺失dmesggrep usb收到数据但不全波特率过高线材太长查看飞控端丢包统计降低波特率到57600或缩短线长一接上飞控飞控就重启两边电源不隔离串口线带电万用表测两板GND用独立电源或光耦隔离5.2 通吃三种平台的串口排查SOP这次实测下来我整理了一套适用于任何机载电脑和飞控通信排查的标准流程照着走一遍90%的问题都能暴露第一步物理层检查。确认GND相连确认TX和RX没有接反确认没有用5V电平怼飞控。用万用表导通档测每一根杜邦线确保不是线材内部断了。很多“串口不工作”的问题最终都出在杜邦线上特别是手工压的杜邦头特别容易接触不良。第二步回环测试。把机载电脑的TX直接短接到自己的RX用serial库发一串固定字符比如kakaxi看能不能收回来。这一步就能把“机载电脑串口是否正常”这个问题彻底排除。回环测试必须用短接线直接怼在排针上不要通过飞控去做回环那会引入飞控的状态干扰判断。第三步参数核对。打开QGroundControl确认飞控TELEM口的波特率参数和代码里一致。重点看SER_TEL1_BAUD、SER_TEL2_BAUD以及对应的SER_TELx_MAV是否为MAVLink2。如果飞控已经刷过别的固件这些参数可能和你想象的不一样必须实际点进去看。第四步收发链路独立验证。如果机载电脑能打开串口但收不到数据用一个USB转串口调试器直接接到飞控的TX线上用PC上的串口助手看飞控是否往外发数据。如果飞控往外发了问题在机载电脑的串口配置如果飞控也没发大概率是流控问题或飞控固件配置问题。第五步协议层验证。串口收到数据但pymavlink解析不了。先用hexdump或xxd看原始字节流MAVLink帧的结构是有明显特征的起始字节0xFDMAVLink2或0xFEMAVLink1如果开头不是这些值说明你收到的不是MAVLink数据检查飞控端口配置是不是选择成了MAVLink之外的协议比如FrSky协议。5.3 从“能通信”到“稳定通信”的调优建议三套平台全部跑通之后我开始考虑稳定性和工程化的问题。在normal的调试阶段波特率用921600没问题但在实际飞行或车辆运行环境中高频串口数据很容易受电磁干扰影响。我的经验是如果只是图像建图、路径规划这类任务把波特率降到57600完全可以接受。IMU数据在飞控内部已经做了姿态解算机载电脑拿到的是高频姿态信息57600波特率下ATTITUDE消息约28字节一秒至少能传100条够用了。唯一影响比较大的是下载日志或刷固件这类批量传输场景那确实需要高波特率。线材方面双绞线比平行线抗干扰能力强很多串口线尽量短能10cm搞定就不要拖1米。无人机上电机和电调的干扰非常严重我之前遇到过两套设备单独测试都正常装到机架上之后数据就开始乱最后排查是串口线靠近了电调电源线把线重新走位之后问题消失。电源隔离也是稳定通信的关键。飞控和机载电脑建议各自使用独立的稳压电源在信号层保证GND相连但电源回路不共用这样可以避免机载电脑瞬时大电流造成飞控电压跌落。6. 写在最后的几个小经验这次一口气把香橙派5max、allspark1、Orin NX载板三套平台全部跑通我心里最大的感触是串口通信不是什么高深技术但它是整个机器人和无人机系统里最容易被忽视的“水电煤”。很多项目卡住不是因为什么AI算法不是因为什么视觉识别而是连最基本的飞控IMU数据都读不到。根据我个人经验给新手几条实实在在的建议别一上来就直接接飞控一定先做回环测试。一次回环测试花不了两分钟但能帮你砍掉一半的排查方向。飞控参数改了一定要点“写入”改完再读一遍确认。这个坑我在allspark1上浪费了整整一下午。先把数据打通再谈代码架构。很多人喜欢直接写一个完整的通信类动不动封装成类结果跑不通的时候分不清是硬件问题还是自己代码问题。先拿三行脚本做通再慢慢加封装。有条件的话备一个USB转TTL调试器和逻辑分析仪总共不到一百块排查串口问题神器。示波器更好没示波器用逻辑分析仪抓波形也完全够用。最后也是最重要的接线图一定要画。即使是临时的桌面测试花两分钟画一张简单的接线示意写上引脚编号和颜色能避免你之后无数次对着排针数来数去。串口通信这门手艺说到底就是把电压信号变成数据再把数据变成控制指令和状态反馈。底层的坑踩过一遍之后你会发现所有平台都长得差不多无非是设备节点名不同、复用方式不同、参数位不同。以后你再换一块新的机载电脑顺着这套排查思路走一遍很快就能跑通。最后再分享一个小技巧如果你以后要用到多路串口同时工作比如同时接飞控、数传模块、激光雷达建议提前梳理一下板子上的UART资源分配别到最后发现两个设备默认引脚冲突。香橙派5max和Orin NX这类高性能平台虽然UART很多但引脚复用是有限的提前规划好映射关系能省掉后面非常多的事情。
返回列表