使用pyserial读取TI IWR1843BOOST雷达时的FPS不匹配问题
TI IWR1843BOOST雷达 pyserial 接收帧率异常问题
通过pyserial读取TI IWR1843BOOST雷达模块的原始十六进制数据时,雷达配置为35 fps的测量速率,理论上每29 ms应接收一个数据包。但实际pyserial每隔约60 ms会一次性接收2个(偶尔3个)数据包,导致数据处理帧率仅17 fps。目前无法确定是雷达芯片硬编码的数据包缓存发送问题,还是数据读取等待逻辑存在错误。
所用代码
def read_data_from_sensor(port, baudrate): try: with serial.Serial(port, baudrate, timeout=0.1) as ser: print(f"[INFO] Listening to {port}...") while True: data = ser.read(ser.in_waiting) # 查找数据包起始位置 magic_indices = find_magic_indices(data) packets = [] for i in range(len(magic_indices)): start = magic_indices[i] end = magic_indices[i+1] if i+1 < len(magic_indices) else len(data) packet = data[start:end] parsed = decode_packet(packet) packets.append(parsed) for i, pkt in enumerate(packets): print(f"\nPacket {i+1}:") print(pkt) except Exception as e: print(f"[ERROR] Failed to read data: {e}")
输出示例
Packet 1: {'header': {'magic0': 258, 'magic1': 772, 'magic2': 1286, 'magic3': 1800, 'version': 50725376, 'packet_len': 128, 'platform': 661571, 'frame_num': 80, 'cpu_cycles': 1159072654, 'num_obj': 0, 'num_tlvs': 3, 'subframe_num': 0}, 'objects': [], 'snr': [], 'noise': [], 'statsinfo': [{'interFrameProcessingTime': 2998, 'transmitOutputTime': 632, 'interFrameProcessingMargin': 24202, 'interChirpProcessingMargin': 0, 'activeFrameCPULoad': 1, 'interFrameCPULoad': 10}]} Packet 2: {'header': {'magic0': 258, 'magic1': 772, 'magic2': 1286, 'magic3': 1800, 'version': 50725376, 'packet_len': 160, 'platform': 661571, 'frame_num': 81, 'cpu_cycles': 1164801812, 'num_obj': 1, 'num_tlvs': 4, 'subframe_num': 0}, 'objects': [{'x': 1.038146734237671, 'y': 1.6446927785873413, 'z': -0.18966545164585114, 'v': 1.7290256023406982}], 'snr': [136], 'noise': [471], 'statsinfo': [{'interFrameProcessingTime': 3069, 'transmitOutputTime': 523, 'interFrameProcessingMargin': 24416, 'interChirpProcessingMargin': 0, 'activeFrameCPULoad': 1, 'interFrameCPULoad': 9}]}
问题分析与解决建议
核心问题点
当前代码采用ser.read(ser.in_waiting)一次性读取串口缓冲区所有数据,再通过魔术字分割数据包。这种方式本身不会丢失数据,但会导致多个数据包被批量读取,造成“帧率减半”的错觉——本质是读取频率跟不上雷达发送频率,导致缓冲区堆积,而非雷达实际发送帧率下降。
排查方向与修复方案
改为按协议读取完整数据包
放弃读取缓冲区所有数据的方式,根据IWR1843的UART协议,先读取固定长度的头部,解析出packet_len字段,再读取对应长度的剩余数据,确保每次只读取一个完整数据包。示例代码如下:import serial import time def read_data_from_sensor(port, baudrate): try: with serial.Serial(port, baudrate, timeout=0.1) as ser: # 增大接收缓冲区,避免数据堆积 ser.set_buffer_size(rx_size=20480) print(f"[INFO] Listening to {port}...") while True: # 读取头部(IWR1843头部固定为48字节,以魔术字开头) header = ser.read(48) if len(header) != 48: continue # 解析packet_len(偏移量需对照实际协议,此处为示例) packet_len = int.from_bytes(header[12:16], byteorder='little') # 读取剩余数据包内容 payload = ser.read(packet_len - 48) full_packet = header + payload # 解析并输出 parsed = decode_packet(full_packet) print(f"\nReceived at {time.time()*1000:.2f}ms, Frame Num: {parsed['header']['frame_num']}") print(parsed) except Exception as e: print(f"[ERROR] Failed to read data: {e}")检查雷达固件配置
- 确认雷达是否启用了“数据包缓存”功能:部分TI雷达的固件会将多个数据包缓存后批量发送,可通过TI官方工具调整UART输出模式为实时发送。
- 验证波特率匹配:确保串口波特率与雷达配置完全一致,过低的波特率会导致数据传输速度不足,触发缓冲区堆积。
优化读取循环的时间控制
在循环中加入微小延迟(如time.sleep(0.001)),避免CPU空转导致的频繁读取,让串口缓冲区有足够时间接收完整数据包。验证实际发送帧率
通过解析数据包中的frame_num和cpu_cycles字段,计算雷达实际的发送间隔:prev_cycles = 0 # 在解析后加入 current_cycles = parsed['header']['cpu_cycles'] if prev_cycles != 0: cycle_diff = current_cycles - prev_cycles # IWR1843的CPU时钟为400MHz,计算时间差(ms) time_diff = (cycle_diff / 400000000) * 1000 print(f"Frame interval: {time_diff:.2f}ms") prev_cycles = current_cycles若计算出的间隔接近29ms,说明雷达是按35fps发送的,问题出在接收端读取逻辑;若间隔接近60ms,则是雷达端的缓存配置问题。
内容的提问来源于stack exchange,提问作者radastro
相关产品推荐
相关产品推荐

