SCPI Commands
SCPI command reference for PyVISA with error codes, command tree, and Python examples for instrument control.
SCPI (Standard Commands for Programmable Instruments) is the command language behind virtually every modern test instrument. This page covers the commands you'll use most, with PyVISA examples.
IEEE 488.2 Common Commands
Every SCPI instrument supports these:
import pyvisa
rm = pyvisa.ResourceManager()
inst = rm.open_resource('TCPIP::192.168.1.100::INSTR')
idn = inst.query('*IDN?') # Identification
inst.write('*RST') # Reset to defaults
inst.write('*CLS') # Clear status registers
inst.query('*OPC?') # Wait for operation complete
errors = inst.query('SYST:ERR?') # Check error queueMeasurement Commands
# DC voltage
voltage = float(inst.query('MEAS:VOLT:DC?'))
# AC voltage with range
inst.write('MEAS:VOLT:AC:RANG 10')
ac_voltage = float(inst.query('MEAS:VOLT:AC?'))
# Current and resistance
current = float(inst.query('MEAS:CURR:DC?'))
resistance = float(inst.query('MEAS:RES?'))Configuration Commands
# Measurement range
inst.write('VOLT:DC:RANG 10') # 10V range
inst.write('CURR:DC:RANG 0.1') # 100 mA range
# Integration time (NPLC)
inst.write('VOLT:DC:NPLC 10') # 10 power line cycles
# Auto-ranging
inst.write('VOLT:DC:RANG:AUTO ON')Log measurements automatically
TofuPilot records SCPI measurement results from your PyVISA scripts, tracks pass/fail rates, and generates compliance reports. Free to start.
Error Checking
Always drain the error queue after a sequence of commands. The queue holds up to 20 errors on most instruments.
def check_errors(inst):
"""Read all errors from the instrument queue."""
errors = []
while True:
err = inst.query('SYST:ERR?')
if err.startswith('0') or err.startswith('+0'):
break
errors.append(err.strip())
return errors
errors = check_errors(inst)
if errors:
print(f"Errors: {errors}")Synchronization
Use *OPC? to block until the instrument finishes. Use *WAI to hold the instrument's command queue.
# Block Python until the instrument finishes
inst.write('INIT')
inst.query('*OPC?') # Returns '1' when done
# Or use service request
inst.write('*ESE 1') # Enable OPC in standard event register
inst.write('*SRE 32') # Enable standard event in status byte
inst.write('INIT')
inst.wait_for_srq() # Block until SRQ firesData Transfer
Binary transfers are 5-10x faster than ASCII for large datasets.
# ASCII (human-readable, slower)
data_ascii = inst.query('TRAC:DATA? TRAC1')
values = [float(x) for x in data_ascii.split(',')]
# Binary (faster)
inst.write('FORM:DATA REAL,32') # 32-bit floats
data = inst.query_binary_values('TRAC:DATA? TRAC1', datatype='f')Instrument-Specific Commands
Digital Multimeters
# Keysight 34401A/34461A style
inst.write('CONF:VOLT:DC 10,0.0001') # Range 10 V, resolution 0.1 mV
inst.write('TRIG:SOUR IMM')
measurement = float(inst.query('READ?'))Oscilloscopes
inst.write('ACQ:MODE RTIME') # Real-time acquisition
inst.write('ACQ:SRAT 1E9') # 1 GSa/s
inst.write('CHAN1:SCAL 0.1') # 100 mV/div
inst.write('TRIG:SOUR CHAN1')
inst.write('TRIG:LEV 0.5') # 500 mV trigger level
waveform = inst.query_binary_values('CURV?', datatype='h')Signal Generators
inst.write('SOUR:FUNC SIN')
inst.write('SOUR:FREQ 1000') # 1 kHz
inst.write('SOUR:VOLT 1') # 1 Vpp
inst.write('OUTP ON')SCPI Data Types
| Type | Examples | Notes |
|---|---|---|
| Integer | SYST:BEEP:FREQ 1000 | No decimal point |
| Real | SOUR:VOLT:AMPL 2.5 | Decimal or exponential (1.5E3) |
| Boolean | OUTP ON, OUTP 1, OUTP TRUE | All three forms are equivalent |
| String | DISP:TEXT "Hello" | Quoted for special characters |
Timeout Management
Some commands (self-test, calibration, long acquisitions) take much longer than the default 2-second timeout.
from contextlib import contextmanager
@contextmanager
def temporary_timeout(inst, timeout_ms):
old = inst.timeout
inst.timeout = timeout_ms
try:
yield inst
finally:
inst.timeout = old
# 60-second timeout for self-test
with temporary_timeout(inst, 60000):
result = inst.query('*TST?')Common SCPI Error Codes
| Code | Meaning | Typical Cause |
|---|---|---|
| -100 | Command Error | Syntax error or unknown command |
| -101 | Invalid Character | Illegal character in command string |
| -102 | Syntax Error | Missing parameter or wrong separator |
| -103 | Invalid Separator | Wrong use of comma or semicolon |
| -104 | Data Type Error | String sent where number expected |
| -108 | Parameter Not Allowed | Too many parameters |
| -109 | Missing Parameter | Required parameter omitted |
| -113 | Undefined Header | Command not recognized by this instrument |
| -200 | Execution Error | Command recognized but cannot execute |
| -221 | Settings Conflict | Parameters conflict with each other |
| -222 | Data Out of Range | Parameter value outside valid range |
| -224 | Illegal Parameter Value | Parameter value not in the allowed set |
SCPI Command Tree Reference
*CLS # Clear status
*ESE <value> # Standard event status enable
*ESR? # Standard event status register
*IDN? # Identification query
*OPC # Operation complete (set ESR bit)
*OPC? # Operation complete query (returns "1")
*RST # Reset
*SRE <value> # Service request enable
*STB? # Status byte query
*TST? # Self-test query
*WAI # Wait to continue
SYSTEM
:ERRor? # Error queue query
:VERSion? # SCPI version query
MEASure
:VOLTage
:DC? [@<list>] # DC voltage measurement
:AC? [@<list>] # AC voltage measurement
:CURRent
:DC? [@<list>] # DC current measurement
:AC? [@<list>] # AC current measurement
:RESistance? [@<list>] # 2-wire resistance
:FRESistance? [@<list>] # 4-wire resistance
:FREQuency? [@<list>] # Frequency measurement
CONFigure
:VOLTage
:DC [<range>[,<resolution>]] [@<list>]
:AC [<range>[,<resolution>]] [@<list>]
:CURRent
:DC [<range>[,<resolution>]] [@<list>]
:AC [<range>[,<resolution>]] [@<list>]
TRIGger
:SOURce <source> # IMM, EXT, BUS, TIM
:DELay <seconds> # Trigger delay
:COUNt <count> # Number of triggers
SAMPle
:COUNt <count> # Readings per trigger
READ? # Initiate + fetch measurement
INITiate # Initiate trigger system
FETCh? # Fetch last measurement (no new trigger)