普源精电RIGOL DS2202A示波器保存波形到CSV文件过慢解决方法:保存为WFM格式、通过LAN接口使用SCPI+PyVISA控制

提示:本文包含AI编写的代码。

前言

最近我正在研究学校的这个包浆示波器,发现它在保存内存所有采样点为CSV文件时的速度非常堪忧,于是准备研究一下解决办法。
通过自行搜索和询问群友,我找到了以下两种方法。

方法一:保存为WFM格式

在存储菜单中,选择“保存波形”,示波器会在U盘中新建一个WFM格式的文件。不同于CSV将采样数据格式化为字符串后再保存,WFM文件似乎是直接存储二进制,保存只需不到2分钟。对于14Mpts的波形,我存储的CSV文件的文件大小为303MiB,而WFM波形仅有不到14MiB。但这个文件无法直接打开,需要通过一个Python库进行读取。

首先安装RigolWFM:https://pypi.org/project/RigolWFM/ 。这个库似乎是经过对WFM文件逆向后编写的,支持日狗示波器的大部分机型。
按照RigolWFM文档,编写如下代码,成功读取波形。

import matplotlib.pyplot as plt
import RigolWFM.wfm as rigol

filename = "example.wfm"
scope = "DS2000"

scope_data = rigol.Wfm.from_file(filename, scope)

ch = scope_data.channels[0]
plt.plot(ch.times, ch.volts)
plt.xlabel("Time (s)")
plt.ylabel("Voltage (V)")
plt.grid()
plt.show()

方法二:通过LAN接口,使用SCPI+PyVISA控制

似乎大部分仪器都支持SCPI。RIGOL官方提供的编程手册包含了非常多的指令,看起来用LabView做自动化测试的就是通过这个SCPI接口完成的。

将示波器通过网线连接到路由器,并在计算机上安装PyVISA、NI VISA。打开NI硬件配置工具,点击加号,手动输入示波器的IP地址。网上的教程似乎都是要用“NI MAX”配置,但我安装完NI MAX后连在哪里启动都找不到,可能是版本不同吧。

根据PyVISA手册中的描述,打开Python命令行,输入以下代码。

import pyvisa
rm = pyvisa.ResourceManager()
print(rm.list_resources())

输出如下。

('TCPIP0::192.168.31.92::inst0::INSTR', 'ASRL3::INSTR', 'ASRL4::INSTR')

可以看到成功找到了示波器。

我参考了一个1000系列的Python库[2] ,修改了一些SCPI指令,完成了截图和读取波形的程序。

截图程序如下。

import pyvisa
import matplotlib.pyplot as plt
import time
from PIL import Image
import io

visa_address = "TCPIP0::192.168.31.92::inst0::INSTR"

rm = pyvisa.ResourceManager()
scope = rm.open_resource(visa_address)
print(scope.query("*IDN?"))


# 截图并显示,计时
time_start = time.time()
while True:
    scope.write(":DISPlay:DATA?")
    raw_image = scope.read_raw()[11:]
    filename = "scope_screenshot.bmp"
    with open(filename, "wb") as f:
        f.write(raw_image)
    # 实时刷新窗口里的图片
    try:
        img = Image.open(io.BytesIO(raw_image))
        if "fig" not in locals():
            fig, ax = plt.subplots()
            im = ax.imshow(img)
            plt.axis("off")
            plt.ion()
            plt.figure(figsize=(10, 10))
            plt.show()
        else:
            im.set_data(img)
            fig.canvas.draw()
            fig.canvas.flush_events()
    except Exception as e:
        print(f"图片显示失败: {e}")
    print(f"截图并显示耗时: {time.time() - time_start:.2f} 秒")
    time_start = time.time()
    # time.sleep(1)

一次截图需要约2秒。

读取波形程序如下。

import pyvisa
import matplotlib.pyplot as plt
import numpy as np
import time
import tqdm

visa_address = "TCPIP0::192.168.31.92::inst0::INSTR"

rm = pyvisa.ResourceManager()
print(rm.list_resources())
# rm.close()
scope = rm.open_resource(visa_address)
scope.timeout = 30000

print(scope.query("*IDN?"))

scope.write("STOP")
scope.write(":WAV:SOUR CHAN1")
scope.write(":WAV:MODE RAW")
scope.write(":WAV:FORM BYTE")

pre = scope.query_ascii_values(":WAVeform:PREamble?")
# <format>,<type>,<points>,<count>,<xincrement>,<xorigin>,<xreference>,<yincrement>,<yorigin> ,<yreference>
pre_dict = {
    "format": int(pre[0]),
    "type": int(pre[1]),
    "points": int(pre[2]),
    "count": int(pre[3]),
    "xincrement": float(pre[4]),
    "xorigin": float(pre[5]),
    "xreference": float(pre[6]),
    "yincrement": float(pre[7]),
    "yorigin": float(pre[8]),
    "yreference": float(pre[9]),
}
max_num_pts = 250000
num_blocks = pre_dict["points"] // max_num_pts
last_block_pts = pre_dict["points"] % max_num_pts

time_start = time.time()

full_data = np.array([])
for i in tqdm.tqdm(range(num_blocks + 1), ncols=60):
    if i < num_blocks:
        scope.write(":WAV:STAR %i" % (1 + i * max_num_pts))
        scope.write(":WAV:STOP %i" % (max_num_pts * (i + 1)))
    else:
        if last_block_pts:
            scope.write(":WAV:STAR %i" % (1 + num_blocks * max_num_pts))
            scope.write(":WAV:STOP %i" % (num_blocks * max_num_pts + last_block_pts))
        else:
            break
    data = scope.query_binary_values(":WAV:DATA?", datatype="B", container=np.array)
    full_data = np.concatenate((full_data, data))

print(len(full_data))

Y_voltage, X_time = (
    np.arange(len(full_data)) * pre_dict["xincrement"],
    (full_data - pre_dict["yreference"] - pre_dict["yorigin"]) * pre_dict["yincrement"],
)

print(f"耗时: {X_time.time() - time_start:.2f} 秒")
plt.plot(Y_voltage, X_time)
plt.show()

# 保存数据到CSV文件
np.savetxt(
    "waveform_data.csv",
    np.column_stack((Y_voltage, X_time)),
    delimiter=",",
    header="Time (s), Voltage (V)",
    comments="",
)
print("数据已保存到 waveform_data.csv")

一次截图大致需要76秒,可算出传输速率大约为184kB/s,看起来读取波形速度慢不是USB或者以太网接口的问题。

参考文献

[1] https://pyvisa.readthedocs.io/en/latest/
[2] https://github.com/jeanyvesb9/Rigol1000z#
[3] https://blog.csdn.net/weixin_73011353/article/details/137994653

posted @ 2025-10-16 19:18  GongYeSUDA  阅读(7)  评论(0)    收藏  举报