将 Python 和 PvVISA 应用于自动化测试
Python 已成为电子测试自动化领域广泛使用的编程语言,尤其是在与 PyVISA 库配合使用时。虽然实验室自动化的基本原理(例如 SCPI 协议)由来已久,但 Python 和 PyVISA 使得快速启动测试自动化变得轻而易举。数据收集完成后,Python 还提供了大量的数据分析工具(pandas、scipy、scikit 等),可用于分析数据。
本文将介绍如何使用 Python/PyVISA 与仪器进行交互,并给出一个测量电源效率的实际示例。最后,我将介绍如何直接在 Python 中绘制收集到的效率数据。
SCPI 协议
可编程仪器标准命令 (SCPI) 是IEEE 488.2-1987 仪器通信标准之上的一个定义层。SCPI 最初是为IEEE 488.1(GPIB 连接)设计的,但后来扩展到RS-232、以太网、USB 以及其他几种连接方式。SCPI 命令以 ASCII 格式发送,并以 ASCII 文本字符串的形式接收。以下是一个简单的 SCPI 事务示例:
主机查询:*IDN?
设备回复: Siglent Technologies,SDL1020X‑E,SDLxxxxxxxxxxx,1.1.1.21R2\n
SCPI 定义了许多通用命令,如MEASure和CONFigure ,可用于从测试设备读取数据或配置测试设备参数。
VISA规范
遗憾的是,对于 SCPI 标准来说,不同的操作系统、接口和设备意味着 SCPI 早期需要为每个设备和总线系统提供不同的库。为了缓解这一难题,虚拟仪器软件架构 (VISA) 规范应运而生,旨在与所有设备和总线系统无缝协作。
Python和PyVISA
即使有了 VISA 规范,在没有昂贵/繁琐的软件和硬件的情况下,将主机连接到测量设备一直以来都极具挑战性。鉴于这些缺陷,PyVISA 库应运而生,旨在简化仪器通信,提高实验室自动化效率。
ython 本身是一种免费的解释型编程语言,可以在任何现代操作系统上使用。由于它是一种解释型(而非编译型)语言,因此 Python 通常可以“安装”在任何系统上,即使用户没有管理员/root权限。虽然 Python 的语法可能需要一些时间来适应(使用空格而不是 ;或其他字符作为分隔符),但它是一种非常广泛的语言,拥有众多可用的库、示例和代码片段。
PyVISA 是 VISA 库的前端,简化了与仪器的通信过程。PyVISA 已通过 National Instruments VISA 和 Keysight IO Library Suite 的官方测试,并且可以与 National Instruments、Keysight 等众多公司的硬件适配器配合使用。
首先,这里有一个简单的程序,用于查询我的电脑上哪些仪器对 PyVISA 可见。在下面的代码片段中,我在一台运行 Python 3.11.5 和 PyVISA 1.13.0 的 64 位 Windows 计算机上使用 National Instruments VISA 。
In [2]:
import pyvisa
instruments = pyvisa.ResourceManager().list_resources()
instruments
Out[2]:
(‘USB0::0xF4EC::0x1621::SDL13GCQ6R0772::INSTR’,
‘USB0::0x2A8D::0x3402::MY61003767::INSTR’,
‘GPIB0::12::INSTR’,
‘GPIB0::22::INSTR’)
此输出显示有四台仪器连接到我的计算机,其中两台通过 USB 连接,两台通过 GPIB 连接。现在我们可以为每台仪器创建一个对象并查询它是什么。请注意,所有仪器都会响应特殊的 *IDN? 命令:
In [5]:
for i in instruments:
inst = pyvisa.ResourceManager().open_resource(i)
print(i,inst.query(‘*IDN?’))
USB0::0xF4EC::0x1621::SDL13GCQ6R0772::INSTR Siglent Technologies,SDL1020X-E,SDL13GCQ6R0772,1.1.1.21R2
USB0::0x2A8D::0x3402::MY61003767::INSTR Keysight Technologies,E36234A,MY61003767,1.0.4-1.0.3-1.00
GPIB0::12::INSTR HEWLETT-PACKARD,34401A,0,7-5-2
GPIB0::22::INSTR HEWLETT-PACKARD,34401A,0,11-5-2
从查询结果中,您可以看到我有一个 Keysight 电源 (E35234A) 和一个 Siglent 电源 (SDL1020X-E)。以下示例中,我仅使用Siglent 电源读取被测设备 (DUT) 的输入和输出电压。
测量效率
对于电源来说,效率是衡量每单位输入功率输出功率的指标。由于P = VI,因此可以写成:
由于该等式得出的分数小于 1,因此通常将其乘以 100,并将效率表示为百分比。
电源设置
在接下来的测试中,我使用DROK 的 720 W 可调 DC-DC 电源( 如图1所示)。为了进行此示例效率测试,我使用25 V 的恒定输入电压和 12 V 的固定输出。请注意,电路板北侧附近有一个大风扇,当电源负载过重时,它会启动。我们将在全效率特性中观察这个风扇的效果。
图1:Drok 720 W可调直流电源
图2:用于效率测量的电源实用仪器
实际效率测量
为了测量DC-DC电源的效率,我们必须施加源电压v s和负载电流i LOAD。电压源是直流电压,负载电流是在恒流模式下运行的电子负载。我们提高负载电流,并测量不同负载点的效率,以绘制完整的电源效率特性图。
由于每次测量需要四个值(输入电压、输入电流、输出电压和输出电流),我们需要足够的设备来读取所有这些参数。实际操作中,最好使用尽可能靠近被测设备的独立仪表来测量输入和输出电压。
对于电流测量,使用现代校准的设备时,直接从电压源(用于输入电流)和电子负载(用于输出电流)读取电流通常足够接近。
用于高效数据收集的仪器对象
我们可以使用 Python 中提供的工具为每台设备创建一个对象,并创建一个标准方法列表,供我们的仪器使用。例如,我们可以为所有仪器对象创建一个 read_v() 方法,用于读取电压值。在顶层,我们只看到方法 instrument.read_v(),但它实际上映射到我们仪器的特定 SCPI 命令,并返回 Python 可以读取的数据。
对于这个测试,我们将需要四个仪器对象,尽管电压测量将是具有不同地址(相同的仪表,不同的 GPIB 地址)的同一对象的实例。
In [6]:
#Basic object for Keysight E36200 series power supply
#Note that channel must be specified
class keysight_E36200(object):
def __init__(self, visa_address, **kwargs):
self.pyvisa = pyvisa.ResourceManager().open_resource(visa_address)
#
#Setup some things
#
self.__channel = int(kwargs[‘channel’])
#check if this is the correct device
def set_v(self, voltage):
self.pyvisa.write(‘VOLT {0:G}, (@{1})’.format(voltage,self.__channel))
def set_i(self, current):
self.pyvisa.write(‘CURR {0:G}, (@{1})’.format(current,self.__channel))
def read_v(self):
return float( self.pyvisa.query(‘MEAS:VOLT? (@{0})’.format(self.__channel)) )
def read_i(self):
return float( self.pyvisa.query(‘MEAS:CURR? (@{0})’.format(self.__channel)) )
def output_enable(self):
self.pyvisa.write(‘OUTP 1, (@{0})’.format(self.__channel))
def output_disable(self):
self.pyvisa.write(‘OUTP 0, (@{0})’.format(self.__channel))
In [7]:
class SDL1000X(object):
def __init__(self, visa_address):
self.pyvisa = pyvisa.ResourceManager().open_resource(visa_address)
#
#Setup some things
#
def read_v(self):
return float(self.pyvisa.query(‘MEASure:VOLTage:DC?’))
def read_i(self):
return float(self.pyvisa.query(‘MEASure:CURRent:DC?’))
def set_i(self, current):
self.pyvisa.write(‘:SOURce:CURRent:LEVel:IMMediate {0:f}’.format(current))
def output_enable(self):
self.pyvisa.write(‘:SOURce:INPut:STATe ON’)
def output_disable(self):
self.pyvisa.write(‘:SOURce:INPut:STATe OFF’)
In [8]:
class hp34401(object):
def __init__(self, visa_address):
self.pyvisa = pyvisa.ResourceManager().open_resource(visa_address)
def read_v(self, average=1):
#start from v=0, add values and average as needed
v = 0.0
self.pyvisa.write(“CONFigure:VOLTage:DC”)
for x in range(average):
v += float(self.pyvisa.query(“READ?”))
voltage = v / average
return voltage
我们还需要导入一些有助于此测试的库:
In [9]:
import time
import numpy as np
import pandas as pd
然后,为每个仪器创建一个具有描述性名称的对象:
In [10]:
inst_load = SDL1000X(‘USB0::0xF4EC::0x1621::SDL13GCQ6R0772::INSTR’)
inst_supply = keysight_E36200(‘USB0::0x2A8D::0x3402::MY61003767::INSTR’,channel=1)
inst_vin_sense = hp34401(‘GPIB0::12::INSTR’)
inst_vo_sense = hp34401(‘GPIB0::22::INSTR’)
我们现在有了用于测量效率的四种仪器的对象,每种仪器都有具有描述性名称的高级方法。再次注意,发送给每个对象的实际 SCPI 命令非常不同,但预期数据(例如测量电流)会返回适合 Python 的数据。
校准输入电压
连接电源和被测器件 (DUT) 的导线具有有限的阻抗,当输入电流增加(由于负载电流增加)时,DUT 输入端的输入电压会降低。为了补偿这种影响,我们可以直接测量 DUT 上的电压,并增加/减少电源电压,使其保持在一定范围内(在本例中为 10mV)。
In [11]:
def calibrate_vin(supply, sense, v_target):
v_meas = sense.read_v()
v_diff = v_meas – v_target
#Keep input to within 10mV
while abs(v_diff) > 0.01:
supply.set_v(supply.read_v() – v_diff/1.5)
time.sleep(1)
v_meas = sense.read_v()
v_diff = v_meas – v_target
冷却
在负载电流非常高的情况下使用校准功能时,输入电压可能会过高,从而导致被测器件发生电气过载 (EOS)。为了避免这种情况,我们可以创建一个简单的“冷却”循环,降低负载并将电源电压缓慢降至安全电压:
In [12]:
def cooldown(v_final,steps):
#Read current and voltage right now
v_now = inst_supply.read_v()
i_now = inst_load.read_i()
#Determine step size
v_step = (v_now – v_final)/steps
i_step = i_now/steps
#Reduce by step sizes
i_now -= i_step
v_now -= v_step
for s in range(steps):
inst_supply.set_v(v_now)
inst_load.set_i(i_now)
i_now -= i_step
v_now -= v_step
time.sleep(1)
#Disable when current is 0 and voltage is at target
inst_load.output_disable()
inst_supply.output_disable()
初始设置
接下来,我们需要设置用于测试的负载点并设置其余参数。所有测试数据都将存储在 Pandas DataFrame 对象中,这将有助于稍后绘制和导出为 .csv。
In [13]:
load_currents = np.linspace(0,5,51) #100mA steps
#load_currents = np.logspace(-2,0.6989700043360189,100)
supply_voltage = 25
inst_supply.set_v(supply_voltage)
inst_supply.output_enable()
time.sleep(1)
inst_load.set_i(0)
inst_load.output_enable()
input(“Press ENTER when ready\n”)
row_counter = 0
column_labels = [‘Vin_set’,’Iload_set’,’Vin’,’Iin’,’Vout’,’Iout’,’Efficiency’]
all_data = pd.DataFrame(columns=column_labels)
环路电流
主循环的工作原理如下:
- 在电子负载上设置下一个负载电流值;
- 等待电流稳定;
- 校准输入电压(就在 DUT 处),使其接近电源电压值;
- 读取所有仪表并计算效率;
- 将所有读取的数据作为新行存储在 all_ data DataFrame 中;并且
- 增加行计数器并继续下一个加载值。
In [14]:
for lc in load_currents:
inst_load.set_i(lc)
time.sleep(1)
calibrate_vin(inst_supply, inst_vin_sense, supply_voltage)
data = [supply_voltage,
lc,
inst_vin_sense.read_v(),
inst_supply.read_i(),
inst_vo_sense.read_v(),
inst_load.read_i()]
efficiency = (100* data[4] * data[5]) / (data[2] * data[3])
data.append(efficiency)
#print(*data, sep=”,”)
all_data.loc[row_counter] = data
row_counter += 1
冷却和保存数据
循环完成后,以 10 步冷却并将 all_data DataFrame 保存到 .csv 文件(带有时间戳,以保证所有数据文件都是唯一的):
In [15]:
cooldown(supply_voltage,10)
timestamp = time.strftime(“%Y.%m.%d.%H.%M.%S”)
all_data.to_csv(‘.\\data\\Efficiency_’+timestamp+’.csv’)
内联绘制数据
由于整个 all_data DataFrame 仍然存在于内存中,我们可以使用 matplotlib 轻松地绘制它:
In [22]:
%matplotlib inline
import matplotlib.pyplot as plt
In [31]:
all_data.plot(x=’Iout’,y=’Efficiency’)
plt.title(‘Efficiency vs. Load Current’)
plt.xlabel(‘Load Current (A)’)
plt.ylabel(‘Efficiency (%)’)
plt.show()
图 3:效率与负载电流的 Python 图
请注意,当负载电流接近 2 A 时,效率会出现大幅下降。此时 DC-DC 转换器上的风扇会打开,并导致效率特性出现明显的扭曲。
使用对数 X 轴进行绘图
类似地,我们可以将 X 轴改为对数刻度,这样在绘制效率时往往会呈现平滑的曲线:
In [37]:
fig, axs = plt.subplots(1)
all_data.plot(ax=axs,x=’Iout’,y=’Efficiency’)
plt.title(‘Efficiency vs. Load Current’)
plt.xlabel(‘Load Current (A)’)
axs.set_xscale(‘log’)
plt.ylabel(‘Efficiency (%)’)
plt.show()
图 4:效率与负载电流的关系图,X 轴为对数
概括
我们利用 Python 和 PyVISA 库创建了仪器对象和一个简单的程序,用于计算直流电源的效率。我们还使用了 Python 中的绘图工具来绘制本次测试的效率图表。
有了基本程序,就可以修改该程序以添加功能,包括:
- 循环不同的输入电压;
- 改变测试电流;
- 将绘图数据保存为图像或 pdf 文件;
- 将数据保存为 Word 文档或 PowerPoint 幻灯片。