PyVISA
PyVISADocs

Keysight Instruments

How to control Keysight oscilloscopes, DMMs, and signal generators with PyVISA. Connection snippets, examples, and vendor quirks.

Control Keysight oscilloscopes, DMMs, and signal generators with PyVISA. One connect snippet, one example per instrument type.

Supported Models

FamilyModelsInterface
DMMs34461A, 34470A (Truevolt), 34401A (legacy)USB, LAN
OscilloscopesInfiniiVision 1000X/2000X/3000X/4000X, Infiniium 90000X/Z-SeriesUSB, LAN
Signal generators33500B (function/arb), E8257D/E8267D (PSG), N5182A (MXG)USB, LAN, GPIB
Network analyzersE5071C, E5063A (ENA), N9918A (FieldFox), P9372ALAN, USB
Power suppliesE36300 (triple), N6700/N6900 (modular), U8000 seriesUSB, LAN

Connect to a Keysight Instrument

Keysight's USB vendor ID is 0x2A8D. You can filter list_resources() to find them.

import pyvisa

rm = pyvisa.ResourceManager()

# Find all Keysight USB instruments
resources = rm.list_resources()
keysight = [r for r in resources if "0x2A8D" in r]

for r in keysight:
    inst = rm.open_resource(r)
    print(f"{r}: {inst.query('*IDN?').strip()}")
    inst.close()

For LAN connections:

import pyvisa

rm = pyvisa.ResourceManager()

# Raw socket (fastest, most Keysight instruments listen on 5025)
inst = rm.open_resource("TCPIP0::192.168.1.100::5025::SOCKET")
inst.read_termination = '\n'
inst.write_termination = '\n'

# VXI-11 (more compatible, auto-discovers termination)
inst = rm.open_resource("TCPIP0::192.168.1.100::inst0::INSTR")

Track test results across instruments

TofuPilot records measurements from your Keysight instruments, tracks pass/fail rates per serial number, and generates compliance reports. Free to start.

DMM (34461A / 34470A)

High-accuracy DC voltage, then a fast burst read.

import pyvisa
import time

rm = pyvisa.ResourceManager()
dmm = rm.open_resource("USB0::0x2A8D::0x0101::MY53220001::INSTR")
dmm.timeout = 10000
dmm.write("*RST")

# High-accuracy single reading
dmm.write("CONF:VOLT:DC")
dmm.write("VOLT:DC:RANG 10")
dmm.write("VOLT:DC:NPLC 100")
dmm.write("VOLT:DC:ZERO:AUTO ON")
voltage = float(dmm.query("READ?"))
print(f"High-accuracy: {voltage:.8f} V")

# Fast burst: 100 readings at max speed
dmm.write("VOLT:DC:NPLC 0.02")
dmm.write("VOLT:DC:ZERO:AUTO OFF")
dmm.write("SAMP:COUN 100")

start = time.time()
response = dmm.query("READ?")
elapsed = time.time() - start

values = [float(x) for x in response.split(",")]
print(f"{len(values)} readings in {elapsed:.2f} s")

dmm.close()
rm.close()

Oscilloscope (InfiniiVision)

Capture a waveform and read automated measurements.

import pyvisa
import numpy as np

rm = pyvisa.ResourceManager()
scope = rm.open_resource("USB0::0x2A8D::0x0001::MY52345678::INSTR")
scope.timeout = 30000
scope.chunk_size = 1024 * 1024

scope.write("*RST")
scope.write(":CHAN1:DISP ON")
scope.write(":CHAN1:SCAL 1.0")         # 1 V/div
scope.write(":TIM:SCAL 1E-3")         # 1 ms/div
scope.write(":TRIG:EDGE:SOUR CHAN1")
scope.write(":TRIG:EDGE:LEV 0.5")

# Single acquisition
scope.write(":SING")
scope.query("*OPC?")

# Automated measurements
vpp = float(scope.query(":MEAS:VPP? CHAN1"))
freq = float(scope.query(":MEAS:FREQ? CHAN1"))
print(f"Vpp: {vpp:.3f} V, Freq: {freq:.1f} Hz")

# Download waveform data
scope.write(":WAV:FORM BYTE")
scope.write(":WAV:SOUR CHAN1")
scope.write(":WAV:POIN 1000")
preamble = scope.query(":WAV:PRE?").split(",")
y_inc = float(preamble[7])
y_orig = float(preamble[8])
y_ref = float(preamble[9])

raw = scope.query_binary_values(":WAV:DATA?", datatype='B', container=np.array)
voltage = (raw - y_ref) * y_inc + y_orig

scope.close()
rm.close()

Signal Generator (33500B)

Generate a sine wave and a frequency sweep.

import pyvisa

rm = pyvisa.ResourceManager()
gen = rm.open_resource("USB0::0x2A8D::0x0001::MY52345678::INSTR")
gen.timeout = 10000
gen.write("*RST")

# 1 kHz sine, 2 Vpp
gen.write("SOUR1:FUNC SIN")
gen.write("SOUR1:FREQ 1000")
gen.write("SOUR1:VOLT 2.0")
gen.write("OUTP1 ON")

# Frequency sweep: 100 Hz to 10 kHz over 10 seconds
gen.write("SOUR1:FREQ:START 100")
gen.write("SOUR1:FREQ:STOP 10000")
gen.write("SOUR1:SWE:TIME 10")
gen.write("SOUR1:SWE:STAT ON")
gen.write("OUTP1 ON")

print("Sweep running")

# Clean up
# gen.write("OUTP1 OFF")
# gen.close()
# rm.close()

Keysight Quirks

QuirkDetailsWorkaround
Slow display updatesGUI rendering slows SCPI throughputSYST:DISP:UPD OFF during fast acquisition
LAN socket needs terminationRaw socket (port 5025) doesn't auto-detect terminationSet read_termination = '\n' and write_termination = '\n'
Legacy Agilent IDNOlder instruments return "Agilent Technologies" in *IDN?Match both "Keysight" and "Agilent" in detection code
Long self-test*TST? can take 30+ secondsSet timeout = 60000 before calling
Output protection tripOverload triggers protection, silently disables outputCheck OUTP:PROT:TRIP? after enabling output
Binary byte orderDefault is big-endian on some modelsVerify with FORM:BORD?, set to NORM or SWAP as needed
Chunk size for waveformsDefault 20 KB chunk size is too small for long recordsSet inst.chunk_size = 1024 * 1024