You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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)一次性读取串口缓冲区所有数据,再通过魔术字分割数据包。这种方式本身不会丢失数据,但会导致多个数据包被批量读取,造成“帧率减半”的错觉——本质是读取频率跟不上雷达发送频率,导致缓冲区堆积,而非雷达实际发送帧率下降。

排查方向与修复方案

  1. 改为按协议读取完整数据包
    放弃读取缓冲区所有数据的方式,根据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}")
    
  2. 检查雷达固件配置

    • 确认雷达是否启用了“数据包缓存”功能:部分TI雷达的固件会将多个数据包缓存后批量发送,可通过TI官方工具调整UART输出模式为实时发送。
    • 验证波特率匹配:确保串口波特率与雷达配置完全一致,过低的波特率会导致数据传输速度不足,触发缓冲区堆积。
  3. 优化读取循环的时间控制
    在循环中加入微小延迟(如time.sleep(0.001)),避免CPU空转导致的频繁读取,让串口缓冲区有足够时间接收完整数据包。

  4. 验证实际发送帧率
    通过解析数据包中的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:46:00