4、仪器控制基础:SCPI命令基础、VISA库安装与配置、PyVISA/PySerial库使用、仪器连接与识别

好,咱们进入第四讲。这一讲,说白了就是解决一个核心问题:怎么让电脑跟仪器对上话

我刚开始带产线项目时,最头疼的就是仪器连不上。不是驱动没装对,就是命令发出去没反应。折腾半天,最后发现是VISA库版本不对。嗯,这些坑,今天咱们一次性填平。

4.1 SCPI命令基础

SCPI,全称是Standard Commands for Programmable Instruments。翻译过来就是「可编程仪器标准命令集」。

你想想看,安捷伦的信号源、罗德与施瓦茨的频谱仪、泰克的示波器,它们虽然长得不一样,但底层都听懂同一套语言——SCPI。这就是标准化的好处。

4.1.1 命令结构

SCPI命令长得像一棵树。根节点是系统级命令,往下分各种子系统。举个例子:

*IDN?          // 查询仪器身份标识
*RST           // 复位仪器
*CLS           // 清除状态寄存器

:FREQuency:CW 1GHz      // 设置连续波频率为1GHz
:SOURce:POWer:LEVel -20dBm  // 设置输出功率为-20dBm
:MEASure:POWer?         // 测量功率并返回结果

注意看,命令不区分大小写。我习惯全大写,看着整齐。但仪器内部处理时,大小写都一样。

我的小习惯:写SCPI命令时,我会把冒号分隔的每一级首字母大写,比如 :FREQuency:CW。这样可读性更好,也符合大多数仪器的官方文档写法。

4.1.2 查询命令与设置命令

SCPI命令分两种:

  • 设置命令:不带问号,用来配置仪器参数
  • 查询命令:带问号,用来读取仪器状态或测量结果

举个例子:

:SOURce:FREQuency 2.4GHz    // 设置频率为2.4GHz
:SOURce:FREQuency?          // 查询当前频率设置值

我在项目中遇到过一个问题:发查询命令时,如果仪器还没准备好,返回的数据可能是空的。所以我的习惯是,查询之前先加个延时,或者用状态寄存器确认仪器不忙了再读。

4.1.3 常用SCPI命令速查表

命令 功能 示例
*IDN? 查询仪器型号、厂商、序列号 返回:Keysight Technologies,E4438C,US12345678,A.01.02
*RST 复位到出厂默认状态 直接发送即可
:SYSTem:ERRor? 查询错误队列 返回:0,"No error"
:SOURce:POWer:LEVel 设置输出功率 :SOUR:POW:LEV -10dBm
:FETCh:POWer? 获取测量结果 返回:-9.98
注意:不同厂商对同一功能的SCPI命令可能有细微差异。比如安捷伦的信号源用 :SOURce:POWer,而罗德与施瓦茨可能用 :SOUR:POW。写代码前,一定先看仪器编程手册。

4.2 VISA库安装与配置

VISA,全称Virtual Instrument Software Architecture。它是仪器通信的中间层。说白了,你不需要关心仪器是连USB、GPIB还是以太网,VISA帮你统一了接口。

我个人习惯用NI-VISA,因为它兼容性最好。但如果你用的是Keysight的仪器,也可以装Keysight IO Libraries Suite。两者功能类似,选一个就行。

4.2.1 安装步骤

  1. 去NI官网下载NI-VISA安装包(建议选最新版)
  2. 双击安装,一路Next
  3. 安装完成后,打开NI MAX(Measurement & Automation Explorer)
  4. 在「设备和接口」下,应该能看到你的仪器

嗯,这里要注意:如果装完看不到仪器,八成是驱动没装对。我遇到过好几次,USB转GPIB的线插上后,Windows自动装了通用驱动,但NI-VISA不认。解决办法是手动更新驱动,选NI-VISA自带的驱动文件。

4.2.2 验证安装

打开NI MAX,点「扫描设备」。如果仪器列表里出现了你的设备,说明VISA安装成功。你还可以右键设备,选「Open VISA Test Panel」,发一条 *IDN? 试试。

避坑指南:我曾经在产线上遇到一台信号源,NI MAX能识别,但发命令就是没反应。折腾了两小时,最后发现是仪器的GPIB地址设成了30,而VISA默认扫描范围是0-15。改一下地址范围就好了。

4.3 PyVISA/PySerial库使用

好,VISA装好了,接下来就是用Python控制仪器。这里有两个库:PyVISAPySerial

  • PyVISA:基于VISA库,支持GPIB、USB、TCP/IP、串口等多种接口
  • PySerial:纯串口通信库,适合直接连串口设备(比如老式频谱仪)

我个人建议:能用PyVISA就用PyVISA。因为它封装了底层细节,代码更简洁。只有遇到VISA不支持的设备时,才考虑PySerial。

4.3.1 安装PyVISA

pip install pyvisa
pip install pyvisa-py    # 纯Python后端,不需要NI-VISA也能用

注意:如果装了NI-VISA,PyVISA默认会用NI-VISA后端。如果没装,可以用 pyvisa-py 后端,但功能会受限。

4.3.2 基本用法示例

import pyvisa

# 创建资源管理器
rm = pyvisa.ResourceManager()

# 列出所有可用仪器
print(rm.list_resources())
# 输出示例:('USB0::0x0957::0x1A26::MY12345678::0::INSTR',)

# 连接仪器
inst = rm.open_resource('USB0::0x0957::0x1A26::MY12345678::0::INSTR')

# 发送SCPI命令
inst.write('*RST')
inst.write(':SOURce:POWer:LEVel -20dBm')

# 查询仪器
idn = inst.query('*IDN?')
print(idn)

# 读取测量结果
power = inst.query(':FETCh:POWer?')
print(f'测量功率:{power} dBm')

# 关闭连接
inst.close()

你看,代码就这么几行。核心就是三步:连接 → 发命令 → 读结果

4.3.3 PySerial用法(备用方案)

如果仪器只支持串口,或者VISA死活装不上,可以用PySerial:

import serial
import time

# 打开串口
ser = serial.Serial(
    port='COM3',
    baudrate=9600,
    bytesize=8,
    parity='N',
    stopbits=1,
    timeout=1
)

# 发送命令(注意要加换行符)
ser.write(b'*IDN?\n')
time.sleep(0.1)

# 读取响应
response = ser.read(100)
print(response.decode())

ser.close()
注意:串口通信时,命令结尾一定要加 \n\r\n。具体加哪个,看仪器手册。我遇到过一台老仪器,只认 \r,不加就死活没反应。

4.4 仪器连接与识别

最后一步,就是让程序自动找到仪器,而不是每次都手动输入VISA地址。

4.4.1 自动识别仪器

import pyvisa

rm = pyvisa.ResourceManager()
devices = rm.list_resources()

for addr in devices:
    try:
        inst = rm.open_resource(addr)
        idn = inst.query('*IDN?')
        print(f'找到仪器:{addr} -> {idn.strip()}')
        inst.close()
    except:
        print(f'{addr} 连接失败')

这段代码会扫描所有VISA资源,发 *IDN? 查询,然后打印出仪器信息。产线上我经常用这个脚本做「仪器发现」。

4.4.2 按型号筛选

如果产线上有多台仪器,你只想连信号源,可以加个筛选:

def find_signal_generator():
    rm = pyvisa.ResourceManager()
    for addr in rm.list_resources():
        try:
            inst = rm.open_resource(addr)
            idn = inst.query('*IDN?')
            if 'E4438C' in idn or 'N5182B' in idn:
                print(f'找到信号源:{addr}')
                return inst
            inst.close()
        except:
            continue
    return None
我的经验:产线上仪器地址可能会变(比如换了USB口)。所以我从来不硬编码VISA地址。每次启动测试程序时,先跑一遍自动发现,找到仪器再开始测试。这样换线、换仪器都不需要改代码。

4.4.3 连接状态检查

连接后,建议加个心跳检测:

def check_connection(inst):
    try:
        inst.write('*TST?')  # 自检命令
        result = inst.read()
        return result.strip() == '0'  # 0表示自检通过
    except:
        return False

嗯,这一讲的内容就这些。总结一下:SCPI是仪器的通用语言,VISA是通信的桥梁,PyVISA是Python端的利器。下一讲,咱们会把这些知识串起来,写一个完整的自动化测试脚本。

记住,仪器控制没有捷径。多试、多查手册、多写代码。踩过的坑,都会变成你的经验。