自动化测试程序开发:用 Python + VISA 控制仪器批量采集数据
产线测试、实验室老化、器件筛选——这些场景里,"手动点按钮→读数据→记 Excel"的方式已经跟不上节奏了。Python + PyVISA 是目前最通用的仪器控制方案,支持 Keysight、R&S、Tektronix、Keithley 等主流品牌的万用表、示波器、电源、电子负载。下面以一个实际案例——用 Keithley 2400 源表批量采集 100 个点的 IV 曲线——演示完整流程。
一、环境搭建
pip install pyvisa pyvisa-py
PyVISA 是抽象层,后端可以用 NI-VISA(需安装 NI 驱动)或纯 Python 实现的 pyvisa-py。对于大多数 USB/GPIB 仪器,pyvisa-py 够用,无需安装 NI 庞大的驱动包。
连接仪器前,先用 pyvisa-info 查看可用资源:
$ pyvisa-info
Available resources:
TCPIP0::192.168.1.100::inst0::INSTR
USB0::0x05E6::0x2400::123456::INSTR
GPIB0::24::INSTR
二、基本读写
以 Keithley 2400 为例,SCPI 命令控制:
import pyvisa
rm = pyvisa.ResourceManager()
# 通过 USB 地址连接
inst = rm.open_resource('USB0::0x05E6::0x2400::123456::INSTR')
inst.timeout = 5000 # 超时 5 秒
# 复位仪器
inst.write('*RST')
# 设置为电压源模式,输出 5V
inst.write(':SOUR:FUNC VOLT')
inst.write(':SOUR:VOLT 5')
# 开启输出
inst.write(':OUTPUT ON')
# 读取电流值
current = inst.query(':MEAS:CURR?')
print(f'Current: {float(current):.6f} A')
# 关闭输出
inst.write(':OUTPUT OFF')
inst.close()
query() 等价于 write() + read(),自动处理结束符。
三、批量采集:IV 曲线
下面的脚本对 DUT 施加 0–10V 步进 0.1V,每步测量电流,保存到 CSV:
import pyvisa
import csv
import time
rm = pyvisa.ResourceManager()
inst = rm.open_resource('USB0::0x05E6::0x2400::123456::INSTR')
inst.timeout = 10000
# 仪器配置
inst.write('*RST')
inst.write(':SOUR:FUNC VOLT')
inst.write(':SENS:FUNC "CURR"')
inst.write(':SENS:CURR:RANG:AUTO ON')
inst.write(':FORM:ELEM VOLT,CURR') # 返回格式:电压,电流
results = []
voltages = [v * 0.1 for v in range(0, 101)] # 0.0V ~ 10.0V
inst.write(':OUTPUT ON')
time.sleep(0.1) # 等待继电器稳定
for v in voltages:
inst.write(f':SOUR:VOLT {v:.3f}')
time.sleep(0.005) # 5ms 建立时间
data = inst.query(':READ?').strip().split(',')
results.append({
'voltage_set': v,
'voltage_meas': float(data[0]),
'current_meas': float(data[1])
})
print(f'{v:.1f}V -> {float(data[1]):.6f}A')
inst.write(':OUTPUT OFF')
inst.close()
# 保存 CSV
with open('iv_curve.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['voltage_set','voltage_meas','current_meas'])
writer.writeheader()
writer.writerows(results)
四、多仪器协同
有时需要同时控制电源和万用表,可以用两个 open_resource 实例:
psu = rm.open_resource('TCPIP0::192.168.1.10::inst0::INSTR') # 电源
dmm = rm.open_resource('TCPIP0::192.168.1.11::inst0::INSTR') # 万用表
psu.write(':OUTPUT ON')
for v in [3.3, 5.0, 12.0]:
psu.write(f':APPL {v}')
time.sleep(0.1)
reading = dmm.query(':MEAS:VOLT:DC?')
print(f'Supply {v}V, measured {float(reading):.4f}V')
psu.write(':OUTPUT OFF')
五、错误处理与重试
仪器通信偶尔会超时,加入重试机制:
def query_with_retry(inst, cmd, retries=3):
for attempt in range(retries):
try:
return inst.query(cmd)
except pyvisa.errors.VisaIOError as e:
print(f'Attempt {attempt+1} failed: {e}')
time.sleep(0.5)
raise Exception('Max retries exceeded')
六、实用技巧
• timeout 设置:批量采集时每个点的测量时间可能不同,设一个合理的超时(如 10 秒),避免单点卡死整个流程。
• *OPC? 同步:有些仪器需要等待操作完成,*OPC? 返回 1 表示就绪。
• 格式化输出::FORM:ELEM VOLT,CURR 让仪器返回简洁的数字,减少解析工作量。
• 关闭连接:inst.close() 释放资源,尤其是在循环中频繁开关仪器时。
Python + VISA 把仪器控制变成了"写脚本"的工作,而不是"动手点"的工作。无论是 100 个点的 IV 扫描,还是 24 小时的老化数据记录,只要 SCPI 命令能做的,脚本都能自动化。关键是先写好一个稳定的基础读写函数,再在上面搭业务逻辑。这套流程上手后,产线测试效率能提升 5–10 倍,而且数据零差错。





