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

如何通过PyVisa解决Jeti光谱仪自定义起始块的二进制数据提取问题

问题

尝试以字节模式从Jeti GmbH光谱仪获取数据,但无法提取二进制数据,怀疑数据起始块为\x06\x07。使用PyVisa的query_binary_values方法并指定header_fmt='ieee'时出现警告,提示块起始位置异常。ASCII模式可正常获取数据但耗时过长,询问是否有方法指定自定义起始块。

环境信息

  • Win10
  • Python3.9
  • PyVisa1.13.0

相关代码

二进制模式尝试代码

import pyvisa

def start(cr):
    resource_manager = pyvisa.ResourceManager()
    device_0 = resource_manager.list_resources()
    jeti = resource_manager.open_resource(device_0[0], read_termination=cr,
                                          baud_rate=115200,  # send_end=True, # open_timeout=3000,                                   
                                          )
    jeti.clear()
    return jeti


def collect_responses(jeti):
    exposue_tint = 0.01  # ms
    av = 1  # average spectras
    format_scpi = 1

    visa_res = jeti.query_binary_values(f"*MEAS:LIGHT {exposue_tint} {av} {format_scpi}",
                                        datatype='f', is_big_endian=False, header_fmt='ieee')

    print(visa_res)
    return visa_res


if __name__ == "__main__":
    cr = '\r'  # carriage return
    jeti = start(cr)

    response = collect_responses(jeti)

    jeti.close()  

ASCII模式可行代码

def collect_responses(visa_res):
    res_s = []
    while True:
        try:
            res = visa_res.read().split("\t")[1]
        except:
            break
        res_s.append(res)

    return res_s
format_scpi = 2
jeti.write(f"*MEAS:LIGHT {exposue_tint} {av} {format_scpi}")
response_s = collect_responses(jeti)
解决方案

PyVisa的query_binary_values仅支持IEEE、HP等标准头部格式,不支持自定义起始块,因此需要手动处理原始字节流来实现需求,具体步骤如下:

  1. 发送测量命令后读取原始字节数据
  2. 在原始数据中定位自定义起始块\x06\x07
  3. 跳过起始块后,根据光谱仪的二进制格式解析数据

修改后的示例代码:

import pyvisa
import struct

def start(cr):
    resource_manager = pyvisa.ResourceManager()
    device_0 = resource_manager.list_resources()
    jeti = resource_manager.open_resource(device_0[0], read_termination=cr,
                                          baud_rate=115200, timeout=5000,  # 增加超时确保读取完整数据
                                          )
    jeti.clear()
    return jeti

def collect_responses(jeti):
    exposue_tint = 0.01  # ms
    av = 1  # average spectras
    format_scpi = 1

    # 发送测量命令
    jeti.write(f"*MEAS:LIGHT {exposue_tint} {av} {format_scpi}")
    # 读取原始字节数据
    raw_data = jeti.read_raw()
    
    # 定位自定义起始块
    start_marker = b'\x06\x07'
    start_idx = raw_data.find(start_marker)
    if start_idx == -1:
        raise ValueError("未找到自定义起始块")
    
    # 跳过起始块,截取实际数据部分
    data_bytes = raw_data[start_idx + len(start_marker):]
    
    # 解析小端序单精度浮点数(每个占4字节)
    num_points = len(data_bytes) // 4
    visa_res = struct.unpack(f'<{num_points}f', data_bytes[:num_points*4])
    
    print(visa_res)
    return list(visa_res)

if __name__ == "__main__":
    cr = '\r'  # carriage return
    jeti = start(cr)
    response = collect_responses(jeti)
    jeti.close()

注意事项

  • 需确认光谱仪返回的二进制格式:如果是双精度浮点数,将'<f'改为'<d',每个数据占8字节;若为大端序,将'<'改为'>'。
  • 若起始块后包含数据长度标识,需先解析长度再读取对应字节数的数据,避免解析无效字节。
  • 若read_raw无法一次性获取完整数据,可循环读取直到满足终止条件(比如读取到特定结束符或达到预期数据长度)。

内容的提问来源于stack exchange,提问作者Toedsjgewg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:51:26