尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

机载电脑与飞控通信:UART串口读取IMU数据实战指南

机载电脑与飞控通信:UART串口读取IMU数据实战指南 先说结论机载电脑和飞控之间的通信99%的场景下UART串口就是最稳的那条路。我最近把香橙派5max、allspark1和一台Orin NX载板分别接到Pixhawk 6C上目标很一致——把飞控的IMU数据实时读回机载电脑做后续的位姿解算和传感器融合。三条路全部打通中间踩了不少坑比如FT231X这类USB转UART芯片的驱动、飞控TELEM口接线、系统串口被console占用之类的老问题今天一篇讲清楚。这篇东西适合三类人看一是刚接触机载电脑和飞控通信的无人机开发者二是想把Pixhawk 6C的IMU数据接进自己算法框架的机器人方向朋友三是已经调通基本通信、但想系统排查UART稳定性问题的老手。我会按三个真实项目来拆香橙派5max直连飞控、allspark1与PIX6C的踩坑全过程、Orin NX载板的串口配置与实测最后附一份通用排查清单。1. 通信方案设计为什么机载电脑和飞控之间走UART1.1 UART与MAVLink机载通信的“普通话”先回答一个很多人问过我的问题机载电脑和飞控之间为什么几乎都用UART而不是USB、I2C或者SPI这得从飞控和机载电脑的定位说起。飞控本身就是一套实时性要求极高的嵌入式系统Pixhawk 6C用的是STM32H743它的UART外设天然就是为这种低延迟、点对点的传感器通信设计的。而机载电脑跑的是Linux底层要接管串口非常容易一个/dev/ttyS*或者/dev/ttyUSB*设备节点就能搞定不用写复杂的驱动。另一个关键点是协议层。飞控和机载电脑之间跑的不是裸串口数据而是MAVLink协议。MAVLink就像串口链路里的“普通话”它把IMU原始数据、姿态四元数、GPS位置这些信息封装成带消息ID和校验位的帧结构。为什么不用自定义协议因为MAVLink是ArduPilot和PX4共同的默认协议飞控固件里早就把IMU数据按标准消息发出来了你只需要在机载电脑端接住解析就行。与其自己造轮子不如用现成的协议栈这也是我做三个项目时统一选择UARTMAVLink的根本原因。1.2 三块机载电脑的串口资源盘点本次实测涉及三块机载电脑串口资源差异不小。香橙派5max基于瑞芯微RK3588方案片上有多组UART通过40pin排针引出还支持通过设备树overlay灵活启用不同串口这是它最方便的一点。allspark1是另一块常见AI开发板串口数量够用但设备名和引脚复用规则比较隐蔽我后面会细讲。Orin NX这边模组本身没有直接引出的UART全靠载板设计常见的载板会在40pin排座或者板边排针上引出1到2路UART设备名通常是/dev/ttyTHS*而Jetson官方系统又默认把部分串口交给nvgetty占用这也是一个经典坑。三块板子的共同点是都能通过USB转串口模块扩展串口。比如CP2102N、FT231X、FT232R这些芯片Linux内核都自带了驱动插上就能识别成/dev/ttyUSB0。USB转串口的好处是隔离了电平风险坏处是多了一层USB桥接延迟而且驱动芯片质量参差不齐我自己就遇到过山寨FT232R在高速率下丢字节的问题。如果你对实时性要求高优先用板载UART如果只是快速验证USB转串口完全够用。1.3 一条链路打通的整体思路机载电脑和飞控的串口通信链路从物理层到应用层可以拆成四段物理连接、串口设备、MAVLink字节流、业务数据解析。物理连接就看三点TX接RX、RX接TX、GND共地电平要匹配。串口设备层要确认系统里出现了正确的设备节点并且没有被其他进程占用。MAVLink字节流层要确认波特率一致、消息帧能连续收到。最后才是业务数据解析层也就是从MAVLink消息里提取IMU加速度、角速度和姿态。我这里给一个重要经验不要一上来就直接读IMU。先把链路层层验证第一步在机载电脑上做串口回环测试第二步接上飞控看HEARTBEAT心跳消息第三步再解析RAW_IMU。强行走捷径的结果就是出了问题根本分不清是接线错了、波特率不对、还是飞控参数没改我早期因为这个浪费了整整一天。所以后面每个项目我都会按这个顺序来记录。2. 香橙派5max串口实操从启用串口到读回IMU2.1 确认串口资源与物理引脚香橙派5max的40pin排针上有多路串口但默认系统并不会把所有UART都启用需要先确认哪些引脚对应哪一路串口。我手上的系统跑的是Armbian内核开机后第一步就是查设备树和原理图。网上能找到香橙派5max的引脚功能图重点看标注了UART_TX、UART_RX的那几个脚然后把板子的header编号和系统里的/dev/ttyS*对应起来。这里有个技巧在/sys/kernel/debug/gpio或者/proc/device-tree下面翻一翻能看到当前哪些引脚被配置成了UART功能。也可以直接看dmesg | grep tty系统启动时会把所有已注册的串口列出来。我自己常用的命令是ls -l /dev/ttyS* cat /proc/tty/driver/serial | head如果某一路串口显示uart:unknown说明它还没有被启用需要走下一步的设备树配置。这一步最费时间的不是改配置而是确认引脚号我建议操作前把原理图和40pin排针图打印出来用标签标记好别靠记忆接线。2.2 启用板载串口overlay配置和设备树调整香橙派5max的串口启用方式跟树莓派有点像都是通过设备树overlay在启动时把某个引脚组复用成UART功能。在我的Armbian系统上配置文件是/boot/orangepiEnv.txt里面有一个overlays字段可以追加要启用的串口编号。例如要启用UART2就在overlays后面加上overlaysuart2不同系统版本对overlay名称的命名不一定相同有的叫uart2有的叫uart2-m0保险的做法是先在/boot/dtb/目录下看有哪些*uart*相关的dtbo文件ls /boot/dtb/ | grep uart看到哪个就写哪个写完保存重启。重启后再次执行ls -l /dev/ttyS*如果出现了新设备节点比如/dev/ttyS2说明overlay生效了。如果还是没有可以查一下/sys/class/misc/gpio或者重新编译设备树但这种概率比较小。改完设备树后建议先用串口回环法验证一下把该路UART的TX引脚和RX引脚直接用杜邦线短接然后在串口设备上随便发几个字节能收到就说明系统层链路是通的。命令很简单stty -F /dev/ttyS2 115200 raw echo hello uart /dev/ttyS2再用另一个终端执行cat /dev/ttyS2如果能看到hello uart那就说明通信链路完全没问题。这一步能省掉后面很多排查时间强烈建议不要跳过。2.3 接通Pixhawk 6C并设置飞控端香橙派5max的板载UART一般是3.3V TTL电平Pixhawk 6C的TELEM口也是3.3V TTL电平两者可以直接对接不用做电平转换。接线就三根线香橙派TX接Pixhawk TELEM口的RX香橙派RX接Pixhawk TELEM口的TXGND接GND。注意千万别把电源线接错TELEM口上的VCC是用来给外部数传模块供电的机载电脑不需要从飞控取电一旦接错可能造成两个板子之间电流倒灌轻则通信异常重则烧接口。飞控端要改两个参数。以Pixhawk 6C跑ArduPilot固件为例如果你用的是TELEM1口对应参数是SERIAL1_PROTOCOL和SERIAL1_BAUD。SERIAL1_PROTOCOL要设置成2也就是MAVLink2SERIAL1_BAUD设置成115对应115200波特率。如果你用的是TELEM2口就改成SERIAL2_PROTOCOL和SERIAL2_BAUD。设置步骤一般是通过Mission Planner或QGroundControl连接飞控在参数列表里搜索并修改写完后重启飞控生效。这里有个容易踩的细节飞控默认的TELEM口波特率可能是5757600而机载电脑往往按115200去打开串口两边对不上结果就是一点数据都没有或者数据全是乱码。所以改完飞控参数后机载电脑端的波特率一定要跟着设置成一样的值两端要严格一致。2.4 用Python读取IMU数据从HEARTBEAT到RAW_IMU链路通了以后最爽的一刻就是看到IMU数据刷屏。我习惯用pymavlink这个库来做MAVLink解析它是MAVLink社区的标准工具安装也方便pip install pymavlink然后写一个极简脚本第一步先建立串口连接并等待心跳from pymavlink import mavutil master mavutil.mavlink_connection(/dev/ttyS2, baud115200) master.wait_heartbeat() print(收到飞控心跳系统ID: %u组件ID: %u % (master.target_system, master.target_component))能收到心跳说明机载电脑和飞控之间的MAVLink链路已经打通。接下来接收IMU数据ArduPilot和PX4都会周期性发RAW_IMU消息里面包含了三轴加速度计、陀螺仪的原始测量值while True: msg master.recv_match(type[RAW_IMU, SCALED_IMU], blockingTrue) if msg: print(accel: %8.4f %8.4f %8.4f gyro: %8.4f %8.4f %8.4f % ( msg.xacc, msg.yacc, msg.zacc, msg.xgyro, msg.ygyro, msg.zgyro))跑起来以后把飞控拿在手里转一下屏幕上加速度和角速度数值会跟着变化那一刻就说明整个链路全部打通了。如果要做位姿解算建议直接用ATTITUDE消息里的四元数或者自己拿RAW_IMU做积分滤波。这里提醒一句原始IMU数据噪声比较大直接积分出来的yaw角必然会有慢漂移这不是通信问题是IMU数据本身需要标定和融合后续再用视觉或者磁力计去修正。3. allspark1与PIX6C通信踩坑出坑实录3.1 第一坑串口设备名与权限反直觉allspark1这块板子我一开始以为会跟香橙派差不多结果一上来就被设备名坑了一把。系统里/dev/ttyS*列表出来一堆但对应引脚关系跟资料上的标注对不上试了好几组才找到真正可用的那路。后来查了内核日志才发现它板载的某个UART在设备树里被映射成了不同的别名所以不能想当然地按ttyS0就是第一路串口来猜。解决方法是开机后先执行dmesg | grep tty看看内核为每个串口注册了什么样的别名信息再结合板级原理图去对照。还有一种更直接的办法把TX和RX都接入逻辑分析仪或示波器然后给不同设备节点写入数据看哪个引脚上出现了波形用排除法确定设备名。效率虽然不高但不会错。权限问题也是新手必踩。默认情况普通用户可能没有权限打开串口设备现象是open()报Permission denied。解决办法是把当前用户加入dialout组或者直接chmod 666 /dev/ttyS*临时放权。我建议同时把两步都做了否则拨号组配置在某些精简系统上不一定生效sudo usermod -aG dialout $USER sudo chmod 666 /dev/ttyS*allspark1上的系统重启后chmod权限会被重新初始化所以如果只用临时改权限的方法重启后又要重新操作。最稳妥的还是加入dialout组并重新登录。3.2 第二坑TTL电平与供电共地问题allspark1和PIX6C通信第二个让我折腾了半天的坑是电平问题。Pixhawk 6C的串口是3.3V TTL但allspark1的某个排针接口标称电平是1.8V我一开始没有仔细看手册直接接了结果就是怎么调都没数据。电平不匹配的时候飞控端可能会收到错误的信号电平表现为完全无响应、偶发乱码或者一个字节都读不到。这里要说清楚一个设计问题很多AI开发板的GPIO电平不是标准的3.3V有的为了低功耗把IO电平做成了1.8V。所以接线前一定要确认两边的UART电平标准一致如果不一致中间要加电平转换模块。最简单可靠的方案是放弃板载UART改用USB转串口模块连接飞控CP2102N或者FT231X都行。USB转串口模块的输出电平大多是3.3V TTL跟Pixhawk 6C天然匹配接线也简单USB转串口的TX接飞控RX、RX接飞控TX、GND共地。供电共地这个问题我每次都要强调串口通信的GND必须连在一起否则两个板子的地电位不一致信号根本没法正确判断。我见过有人只接TX和RX不接GND然后用USB供电结果数据乱码。这种情况多半就是共地没做好。3.3 第三坑飞控串口协议与波特率没有对齐当硬件接线看着没问题、设备节点也能打开但还是收不到数据时问题基本就出在协议和波特率上。allspark1那次我调完电平后依然没有数据最后检查发现Pixhawk 6C的TELEM1口参数还是出厂默认的SERIAL1_PROTOCOL1也就是MAVLink1而机载电脑端的pymavlink按MAVLink2去解析。虽然MAVLink1和MAVLink2有很多消息是兼容的但两边不一致会导致部分消息解析失败进而让上层逻辑误以为链路不通。解决方式还是去飞控参数里把SERIAL1_PROTOCOL改成2SERIAL1_BAUD改成115然后机载电脑端也用115200打开串口。这一步完成后再执行wait_heartbeat()脚本基本都能收到心跳。如果你换过TELEM口记得参数索引也要跟着换TELEM2对应的是SERIAL2_PROTOCOL和SERIAL2_BAUD别改错了地方。我还遇到过一种比较隐蔽的情况飞控端的波特率设置成921600机载电脑端也设置成921600但用的USB转串口模块是劣质芯片高波特率下频繁丢帧表现为心跳时有时无、IMU数据经常断。后来把波特率降到115200就稳定了。所以我的建议很明确除非你已经验证过整套链路在高波特率下稳定否则老老实实用115200IMU频率和延迟完全够用。3.4 出坑验证回环测试与MAVLink心跳allspark1踩完坑之后我总结了一套“出坑验证”的标准流程虽然简单但每次都能快速定位问题。第一步是USB转串口模块自测把模块的TX和RX短接在机载电脑上往/dev/ttyUSB0写数据然后马上读回来能读到就说明USB转串口模块本身没问题。第二步接上飞控后先看HEARTBEAT心跳能持续输出就说明物理链路和MAVLink协议层都通了。第三步才是把RAW_IMU消息解析出来。这套流程最值钱的地方在于它把问题分层隔离了。如果第一步失败问题在模块或系统驱动如果第二步失败问题在接线、电平、波特率或飞控参数如果第三步失败问题基本就在上层消息过滤和解析逻辑。allspark1最后就是这么一步步定位到电平问题的而不是靠猜。4. Orin NX载板与飞控通信实录4.1 Orin NX载板的串口资源与系统配置Orin NX的串口通信对我来说算是最有挑战的因为模组本身不直接引出UART全靠第三方载板。我手上的载板在40pin排座上引出了一路UART系统里对应/dev/ttyTHS1同时还板载了一个USB转串口芯片对应/dev/ttyUSB0。如果你发现系统里没有这两个设备先查一下载板手册看是不是需要跳线或者通过设备树把串口打开。Jetson平台跟香橙派、allspark1还有一个很大的区别默认系统会把一部分UART分配给nvgetty也就是NVIDIA的串口控制台服务。如果这路UART恰好是你想用的那路你打开设备时会冲突现象是程序能打开串口但收不到数据或者干脆open()失败。解决方法是先把这个服务停掉sudo systemctl stop nvgetty sudo systemctl disable nvgetty sudo udevadm trigger执行完再检查一下/dev/ttyTHS1是否还在重新插拔或重启后一般就能正常使用了。这里提醒一句必须把disable和udevadm trigger都执行只stop不disable的话系统重启后nvgetty会再次起来串口又会被占用。4.2 实测中遇到的console输出干扰问题Orin NX载板第二次让我头疼的问题是kernel console输出。载板上那路UART如果被系统当成console那么开机时会不断往里打印内核日志这些日志会直接混进MAVLink数据流里导致pymavlink解析时大量报CRC错误或消息长度错误。我第一次运行时只见bad CRC刷屏根本不像飞控数据通了的样子。排查方法是用cat直接看裸数据流。先断开飞控单独用串口工具读这个设备节点如果能看到内核的启动日志或者shell提示符那就说明console还在占用。解决方式是在/boot/extlinux/extlinux.conf里找到内核启动参数那行把consolettyTHS1,115200这部分去掉然后重启。注意不同载板的UART设备名不一样有的可能是consolettyTCU0需要先看当前启动参数里写的是哪个。处理完console再配合nvgetty禁用Orin NX那路串口就能真正变成纯数据口。然后接上Pixhawk 6C用115200波特率跑pymavlinkIMU数据就能稳定读回来。如果你觉得每次开机都要执行systemctl太麻烦可以把禁用命令写成一个systemd服务开机自动执行我在项目里就是这么干的省心很多。4.3 Orin NX上跑通IMU数据的最终方案Orin NX载板跑通之后我用的设备和配置如下供参考载板40pin排座上的UART设备节点/dev/ttyTHS1已禁用nvgetty已从extlinux.conf中移除consolettyTHS1启动参数飞控接TELEM1口飞控端设置SERIAL1_PROTOCOL2SERIAL1_BAUD115代码跟香橙派5max用的是一样的pymavlink脚本只是把串口设备改成了/dev/ttyTHS1。我在板子上同时跑了两个进程一个进程负责从飞控读RAW_IMU另一个进程接收帧数据做IMU与相机的联合标定。全程跑了接近一小时数据流稳定说明只要系统配置干净Orin NX的串口通信完全能扛住长时间高频率读取。如果载板上没有引出的板载UART用USB转串口也完全可以设备名会变成/dev/ttyUSB0并且不需要处理nvgetty和console问题因为USB转串口芯片是独立注册的设备。这其实是一个更省事的选择尤其适合快速原型验证。5. 通用排查清单与经验工具5.1 五位排查法从物理层到应用层三块板子全部调通后我把整个排查思路沉淀成了一套“五位排查法”每次通信出问题都按这个顺序走基本能在五分钟内锁定问题。第一位是物理层检查TX接RX、RX接TX、GND共地是否都正确电平是否匹配飞控不供电只共地。第二位是系统层确认设备节点存在、权限可写、没有别的进程占用用ls -l /dev/tty*和sudo lsof /dev/tty*来查。第三位是串口参数层波特率、数据位、停止位、校验位是否一致我固定用115200 8N1。第四位是协议层能收到数据但不认识就用hexdump或cat看裸数据确认是不是MAVLink帧结构是否需要改飞控的协议参数。第五位才是应用层pymavlink消息过滤条件对不对、消息类型是否写错、目标系统ID是否匹配。这套方法最核心的思想是把问题分段隔离避免把所有可能出错的环节混在一起猜。我每次帮别人排查串口问题第一句话都是先别急着看代码先确认前四位。5.2 接线与参数速查表我做了个速查表每次换平台直接对着查省去翻文档的时间平台接入方式设备节点飞控参数备注香橙派5max板载UART / 40pin/dev/ttyS2SERIAL1_PROTOCOL2、SERIAL1_BAUD115先启用overlay再做回环测试allspark1USB转串口推荐/dev/ttyUSB0同上需要将用户加入dialout组Orin NX载板板载UART 或 USB转串口/dev/ttyTHS1或/dev/ttyUSB0同上禁用nvgetty、移除console启动参数表里有个通用原则飞控端优先用TELEM1口参数索引跟物理串口号对应。如果你用了别的飞控比如Pixhawk 6X或者CUAV V5思路完全一样只是参数序号和物理排针位置有差异。5.3 常用工具与驱动FT231X、FT232R、CP2102N日常调试串口工具选对能省一半时间。Linux下我最常用的是minicom、screen和sttysudo apt install minicom minicom -D /dev/ttyUSB0 -b 115200 screen /dev/ttyUSB0 115200 stty -F /dev/ttyUSB0 115200 raw这三个工具的使用场景不太一样minicom适合交互式调试能直观看到收发内容screen适合快速临时连接stty适合在脚本里设置串口参数不进入交互界面。如果你需要看字节级别的数据hexdump或者xxd配合cat也能凑合但严谨的项目还是建议用逻辑分析仪抓波形能看到每一个 bit 的电平变化排查物理层问题特别有用。驱动方面CP2102N、FT231X、FT232R这几种芯片在Linux内核里都自带驱动插上以后一般不需要额外装驱动。如果系统没自动识别先执行dmesg | tail看内核日志再检查模块是否加载lsmod | grep cp210x sudo modprobe cp210xWindows平台就需要安装对应厂商的驱动CP210x官网驱动和FTDI的VCP驱动都可以直接搜索找到。我遇到过一些山寨FT232R芯片在Linux下也能识别只是序列号全是0而且高负载下会丢数据建议大批量采购前先小批量测试稳定性。5.4 我总结的几条串口通信铁律调过这么多板子和飞控之后有些规律已经变成条件反射了这里直接分享几条“铁律”。第一条是接线顺序。先接GND再接TX和RX最后才考虑接其他信号线。别小看这个顺序如果先接TX/RX再接GND在共地建立瞬间可能产生地电位差极端情况下会损坏芯片。第二条是波特率两端必须严格一致而且优先用115200除非你有明确的高带宽需求否则别追求921600稳定性比峰值速率重要得多。第三条是串口问题80%出在物理层所以排查时一定要先确认接线、电平、GND不要一上来就在代码里翻找。第四条是关于MAVLink消息的HEARTBEAT是链路状态的风向标RAW_IMU是数据是否真正流动的验证手段。如果一个系统能稳定收到心跳但IMU消息时有时无问题多半在波特率过高或者USB转串口芯片性能不达标而不是飞控没发IMU。第五条是给长时间运行的项目如果打算让机载电脑长时间读取IMU建议在应用层做断线重连和看门狗逻辑因为物理层偶尔的干扰或USB枚举问题很难完全避免重连机制能省很多重启时间。6. 最后一次实际调试后的一点想法三块板子全部调通后我最大的感受是机载电脑和飞控的串口通信本身并不难难点全在“细节”二字。电平是否匹配、设备节点是否被console占用、飞控参数是不是改对了、波特率两端是否一致这些细节单独拎出来都简单但堆在一起就容易让人抓狂。我也是在allspark1上踩完TTL电平的坑、在Orin NX上处理完nvgetty之后才真正形成了一套稳定的排查流程。最后分享一个我一直在用的小技巧把验证脚本精简成一个固定模板专门打印HEARTBEAT和RAW_IMU两个消息。每换一块新板子先跑这个模板确认链路通再开始做上层业务逻辑。这个习惯帮我省掉了无数重复排查时间也让我有信心说一句——串口通信这件事只要你按顺序排查真的可以一次打通。
返回列表