SCPI指令是可编程仪器标准命令(Standard Commands for Programmable Instruments)的简称,它实际定义了一套用于控制可编程测量仪器的标准语法和命令。
SCP命令实际是通过ASCII字符串形式在命令与仪器进行交互。命令一般由一系列的关键字构成,有的还需要包括参数,命令一般由英文单词的4个大写首字母定义,一般仪器对于命令的返回也是一系列的ASCII字符串,当然在进行大量数据传输的时候直接采用二进制的形式也是可以的。
基本语法
一般的仪器指令可以分为控制指令和查询指令,比如将电源开关的开关和查询电源的输出电流,在SCPI指令中查询指令一般是以?结束的,多个指令之间还可以通过:
进行串联,指令的参数一般跟在指令后面,以空格隔开,多个级联的指令还可以通过一条语句下发,指令之间以;
分隔,比如测量直流电压和交流电流可以通过以下的形式实现:
MEASure:VOLTage:DC?;:MEASure:CURRent:AC?
用SCPI指令控制万用表
最近要用到万用表测量很多数据,如果人肉测量的话就太麻烦了,并且容易出错,对现代人来说,不要在重复的事情上花太多的时间,于是就用python
结合SCPI指令写了一个简单的脚本,也就一个小时的时间就可以搞定几天的工作,腾出一点时间来写写文章也是非常不错的呀。
实际万用表的控制只用到了一点非常基本的命令,不过还是碰到一个坑,这里也记录一下。在用串口通过SCPI指令控制万用表的时候,需要注意的是首先要将万用表的操作模式设置为远程模式,否则所有的命令都会报错,模式的切换可以通过以下的命令实现:
SYSTem:REMote
之后就可以将万用表设置为直流电压测量模式:MEAS:VOLT:DC? AUTO
,这个指令的含义是用自动的量程进行直流电压测量。
最后就可以在一个循环中不停地读取测量结果了:READ?
用SCPI指令控制SMU
在控制源测量单元的时候,有一个需要需要注意的地方就是前后面板的切换,一般的仪器都会在前后面板上都有测试端子,我们在使用的时候需要去选择前面板还是后面板,在SMU中这个选择是通过命令切换的:ROUT:TERM REAR
, 其它一些基本都是通用的指令,完整的程序这里也直接贴出来好了:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script to run dcdc loading test, using source meter
as DCDC loading and DMM to measure DCDC output voltage
"""
import serial
import time
SOURCE_METER_DEV = "COM3"
DMM_DEV = "COM10"
BUFFER_LEN = 1024
class SCPI():
"""
Source meter class
"""
def __init__(self, port, timeout=2, stop=1, baudrate=9600, reset=True):
# open serial port
# baudrate: 9600
# timeout 1s
self.com = serial.Serial(
port,
timeout=timeout,
stopbits=stop,
baudrate=baudrate
)
if reset:
self.reset()
def send(self, cmd):
"""
Send out a command, will automaticlly add \n
at the end of command
"""
if not cmd.endswith("\n"):
cmd += "\n"
return self.com.write(cmd.encode())
def query(self, cmd, decode=True):
self.send(cmd)
echo = self.com.read(BUFFER_LEN)
if decode:
try:
# try to decode to utf8
echo = echo.decode()
# try to decode to float
echo = float(echo)
except:
pass
return echo
def reset(self):
return self.send("*RST")
def close(self):
return self.com.close()
def dcdc_loading():
sm = SCPI(SOURCE_METER_DEV)
dmm = SCPI(DMM_DEV, stop=2)
# init source meter to current source
sm.send(":OUTP OFF")
sm.send(":ROUT:TERM REAR")
sm.send(":SOUR:FUNC CURR")
sm.send(":SOUR:CURR:RANG:AUTO ON")
sm.send(":SOUR:CURR:LEV 0")
sm.send(":OUTP ON")
# init dmm
dmm.send("SYST:REM")
dmm.query("MEAS:VOLT:DC? AUTO")
for i in range(50):
# set current source
curr = -(i / 100)
sm.send("SOUR:CURR:LEV " + str(curr))
# read result
time.sleep(1)
print(curr, ", ", dmm.query("READ?"))
sm.send(":OUTP OFF")
sm.close()
dmm.close()
dcdc_loading()