Skip to main content
FixturFab

Control a Rigol DP832 Power Supply with Python and PyVISA

Python instrument control with PyVISA: set up a Rigol DP832, send SCPI commands, and run a practical voltage sweep script.

PyVISA is a Python SCPI library that gives you direct, scriptable control over Rigol power supplies (and most other SCPI instruments) over USB, GPIB, or Ethernet — no proprietary vendor software required. If you need Python instrument control beyond manual bench work, this is where you start. Here's the minimum to get a response from a DP832:

import pyvisa
 
rm = pyvisa.ResourceManager('@py')
inst = rm.open_resource('USB0::6833::3601::DP8G223300053::0::INSTR')
print(inst.query('*IDN?'))
# RIGOL TECHNOLOGIES,DP832,DP8G223300053,00.01.16

If that looks straightforward, it is. The rest of this pyvisa tutorial covers setup, core SCPI commands, and a practical test sequence you can adapt for embedded automation testing.

What you need#

  • Rigol DP832 (or another SCPI-compatible programmable supply — most Rigol, Keysight, and Siglent models work)
  • Python 3.8+
  • PyVISA and a backend driver

Install PyVISA and the pure-Python backend:

pip install pyvisa
pip install pyvisa-py

pyvisa-py is the open-source backend. It handles USB-TMC and TCP/IP connections without any vendor libraries. If you already have NI-VISA installed (from LabVIEW or NI MAX), PyVISA will use it automatically — pyvisa-py is the alternative for setups without NI software.

On Linux, pyvisa-py needs pyusb and appropriate udev rules for USB-TMC. On macOS and Windows, USB-TMC works out of the box. See the PyVISA-py docs for platform-specific details.

Connecting to your instrument#

PyVISA uses VISA resource strings to identify instruments. VISA (Virtual Instrument Software Architecture) is the standard protocol layer — PyVISA is the Python implementation.

Plug in your DP832 via USB and list available instruments:

import pyvisa
 
rm = pyvisa.ResourceManager('@py')
print(rm.list_resources())
# ('USB0::6833::3601::DP8G223300053::0::INSTR',)

The resource string format tells you the connection type:

  • USB: USB0::6833::3601::[serial]::0::INSTR
  • LAN: TCPIP0::192.168.1.100::INSTR
  • GPIB: GPIB0::12::INSTR

Open a connection and verify with the standard *IDN? identity query:

inst = rm.open_resource('USB0::6833::3601::DP8G223300053::0::INSTR')
inst.timeout = 5000  # 5 seconds — prevents hanging on connection issues
print(inst.query('*IDN?'))

If this returns your instrument's identification string, you're connected. If it times out, check that no other application (Ultra Sigma, NI MAX) has an open session to the same instrument.

Basic SCPI commands#

SCPI commands follow a consistent pattern: a hierarchical path with colons, and a ? suffix for queries. Once you understand the structure, you can read any instrument's programming manual and translate commands directly.

Set voltage and current#

# Select channel 1
inst.write(':INST CH1')
 
# Set voltage to 3.3V and current limit to 1A
inst.write(':VOLT 3.3')
inst.write(':CURR 1')

Enable and disable output#

# Turn on channel 1
inst.write(':OUTP CH1,ON')
 
# Turn off channel 1
inst.write(':OUTP CH1,OFF')

Read measurements#

# Read actual output voltage on channel 1
voltage = inst.query(':MEAS:VOLT? CH1')
print(f'Measured voltage: {voltage.strip()} V')
 
# Read actual current draw
current = inst.query(':MEAS:CURR? CH1')
print(f'Measured current: {current.strip()} A')

The distinction between write and query matters: write sends a command with no response. query sends a command and reads back the instrument's answer. Using write when you need data back will leave unread bytes in the buffer, which causes confusing errors on subsequent commands.

A practical test sequence#

Individual commands compose into automated test logic. This voltage sweep sets incrementing voltages on channel 1, measures the output at each step, and logs the results — a pattern you'd use for characterizing a voltage regulator or checking a power rail under load.

import pyvisa
import time
 
rm = pyvisa.ResourceManager('@py')
inst = rm.open_resource('USB0::6833::3601::DP8G223300053::0::INSTR')
inst.timeout = 5000
 
# Configure channel 1
inst.write(':INST CH1')
inst.write(':CURR 0.5')  # 500mA current limit
 
results = []
 
try:
    inst.write(':OUTP CH1,ON')
 
    for target_voltage in [1.0, 1.8, 2.5, 3.3, 5.0]:
        inst.write(f':VOLT {target_voltage}')
        time.sleep(0.3)  # settling time
 
        measured_v = float(inst.query(':MEAS:VOLT? CH1'))
        measured_i = float(inst.query(':MEAS:CURR? CH1'))
 
        results.append({
            'set_v': target_voltage,
            'actual_v': measured_v,
            'actual_i': measured_i,
        })
        print(f'{target_voltage}V → {measured_v:.4f}V, {measured_i:.4f}A')
 
finally:
    inst.write(':OUTP CH1,OFF')
    inst.close()

The try/finally block matters. If a measurement fails or your script hits an exception, the output still gets disabled. Leaving a power supply channel on after a crashed script is how you damage DUTs.

For longer test sequences, add a check for overcurrent protection (OCP) status between steps:

ocp_status = inst.query(':OUTP:OCP:QUES? CH1')
if ocp_status.strip() == '1':
    print('OCP tripped — check your load')
    inst.write(':OUTP CH1,OFF')
    break

From scripts to frameworks#

The code above is exactly what a PyVISA instrument driver does internally: open a connection, send SCPI commands, parse responses. When you have one instrument and one script, that's all you need.

When you have multiple instruments, test sequences that need to coordinate across them, and results that need to go somewhere useful, the boilerplate adds up. Every instrument needs connection handling, error recovery, and a consistent interface.

That's what f3ts-hardware-utils abstracts. It wraps SCPI instruments (including the DP832) into Python classes with typed methods, connection management, and logging built in. The concepts are the same ones you just learned — resource strings, SCPI writes, measurement queries — packaged into reusable drivers.

For the full SCPI command set, refer to the Rigol DP832 Programming Manual — it lists every command with parameter ranges and expected responses.

Reusable instrument drivers for Rigol and more

f3ts-hardware-utils wraps the PyVISA patterns from this tutorial into typed Python classes with connection management, error recovery, and built-in logging.

Scripts talk to instruments — but instruments need physical access to your board. A bed-of-nails fixture connects your automated test code to the DUT reliably and repeatably. You can configure one in Studio once your test point locations are defined.

Last updated:March 8, 2026