尝试通过wifi和蓝牙分别将mpu6050的数据传输至上位机

mpu6050的I2C 要两个空闲脚。先把 RA 板子的 IIC 引脚扒了一遍:
引脚对用的板子通道
| P400 / P401 | ek_ra4m2、ek_ra4m3、ek_ra6m1… | iic0 |
| P511 / P512 | ek_ra6m2/3/4/5、ek_ra8d1… | iic1 |
| P100 / P101 | ek_ra4l1、ek_ra4m1 | |
| P407 / P408 | ek_ra2l1、ek_ra4w1 |
P511/P512不在任何 pmod 映射里。但那些都是 LQFP144 的板子,我这块是 LQFP100,不一定引出来了。板子上有个专门的 I2C 排针,P408(SCL)/P409(SDA),自带 R14/R15 两个 1.5K 上拉,跟谁都不冲突,就它了。
原理图上这俩脚标 SCL3/SDA3,是 SCI3 的简单 I2C 模式。但 RA 的引脚复用表分封装,这张表不在 Zephyr 仓库里,硬绑 SCI3 就是赌这个封装上 P408/P409 真能复用到 SCI3。软件 I2C 不用赌,脚存在能拉高拉低就行,已经实测 USABLE 了。用 gpio-i2c bitbang,一行 overlay:
i2c_sw: i2c-gpio {
compatible = "gpio-i2c";
scl-gpios = <&ioport4 8 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_HIGH)>;
sda-gpios = <&ioport4 9 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_HIGH)>;
clock-frequency = <I2C_BITRATE_STANDARD>;
...
};板上有 1.5K 上拉,GPIO_OPEN_DRAIN 是对的,不用开内部上拉。烧进去:
ATT,1157,24344,-36500,-1 ATT,1177,24345,-36499,-3 ATT,1197,24346,-36500,-4
mpu6050读到了,然后处理两路数据传输
一开始想的是包里带 MCU 时间戳,电脑收到记本地时间,相减就是延迟。但 MCU 的时钟和电脑的时钟没对齐,算出来的延迟里混着一个未知的常数偏移还会漂,要修正就得搞 NTP 那套,很麻烦。
后来想通,我要的不是绝对延迟,是两条链路的差。同一个包同时走两条路,对任意序号 seq:
BLE 到达时间 - WiFi 到达时间 = (BLE绝对到达 - MCU发出) - (WiFi绝对到达 - MCU发出) = BLE延迟 - WiFi延迟
MCU 那个未知偏移相减就消了,两个到达时间都用电脑本地时钟测、同一个时钟相减天然干净,不用同步不用 NTP。包格式就很简单:
S,<seq>,<t_ms>,<ax>,<ay>,<az>\n
seq 断了就是丢包,到达时间差是延迟,到达间隔是抖动。MCU 一次采样喂两条路,BLE 先发——它是窄的那条,先让它起跑,免得 WiFi 的 ESC 封装抢走时间反过来污染正在测的数。
/* BLE first - narrower pipe, give it the head start. */ emit(ble, line); /* WiFi uplink per UM-WI-003 p.43: * <ESC>S<cid><len>,<ip>,<port>,<data> */ uart_poll_out(wifi, 0x1b); snprintf(esc, sizeof(esc), "S1%d,0,0,", len); emit(wifi, esc); emit(wifi, line);
在三个采样率下测试
采样率链路收包丢包实际速率BLE−WiFi 中位数p95max
| 10 Hz ~300 B/s | WiFi | 587 | 0 (0.00%) | 10.92 pkt/s | +46.3 ms | +69.5 | +74.7 |
| BLE | 409 | 0 (0.00%) | 10.92 pkt/s | ||||
| 20 Hz ~600 B/s | WiFi | 1168 | 0 (0.00%) | 21.78 pkt/s | +83.2 ms | +492.2 | +908.6 |
| BLE | 968 | 101 (9.45%) | 19.76 pkt/s | ||||
| 50 Hz ~1.5 KB/s | WiFi | 2916 | 0 (0.00%) | 54.06 pkt/s | — | — | — |
| BLE | 0 | 完全失效 | — |
WiFi 三档下来一个包没掉,包间隔 p95 才 22.1ms,54 包/秒、1.6 KB/s,看样子离上限还远。
10Hz 两条都零丢包,界面上两条曲线基本贴在一起:
到 20Hz,BLE 开始掉包,橙线一顿一顿追不上蓝线:
9.45% 的丢包,先查是空口质量差还是模块转发不过来,这俩处理方式完全相反:前者要调功率换信道,后者只要降速或者改批量发。我看了三个数,都指向后者。
一是降速丢包归零,10Hz 一个不丢、20Hz 丢 9.45%,唯一变量是负载。二是包间隔中位数 0.0 ms:
ble rx=968 lost=101 (9.45%) 19.76 pkt/s gap med 0.0 ms p95 111.0 ms
包不是均匀来的,是一批一批涌出来的,中位数 0ms 说明大量包挤在同一瞬间到达,缓冲积压然后集中吐出的形态。真要是空口丢包间隔会是均匀的,只是偶尔少一个。三是延迟中位数 +83ms、p95 +492ms、最差 +909ms,中位数和尾部差一个数量级,是排队不是链路损伤——链路差是整体变慢,排队是大部分正常、少数被堵死。
UART 灌进去 600 B/s → CodeLess 转发缓冲吃不下 → 包在模块里排队 → 一部分延迟暴涨到 900ms → 缓冲满了后面的直接丢 → 9.45% 丢包 + 极大的延迟尾部
50Hz 那一轮 BLE 一个包都没收到,日志里连 "BLE connected" 都没有,连接都建不起来。扫了一下空口:
$ bluetoothctl --timeout 18 scan le | grep superfly (什么都没有)
连广播都停了。第一反应是模块挂了,但刚被 LPR 骗过两次,先烧回低负载的固件再扫一次:
[NEW] Device E0:E8:F6:3F:A4:C1 superflyBLE
立刻恢复广播。不是硬件坏,可能是被 1.5 KB/s 的 UART 输入彻底打爆、连维持广播的余力都没了,负载一撤就活过来。
WiFi (DA16200) 这条链路在这个量级上基本没脾气,54 包/秒零丢包还有余量
BLE (DA14531) 的实用上限大概在 10Hz / 300 B/s(可能?)
我要赚赏金
