PyVISA
PyVISADocs

Events & SRQ

How to use PyVISA events and Service Request (SRQ) to get instrument notifications without polling.

PyVISA supports hardware events so your script can react to instrument signals instead of polling in a loop. The most useful event is Service Request (SRQ), where the instrument tells you it's done.

Why SRQ Beats Polling

The polling approach sends *OPC? repeatedly until the instrument replies. This ties up the bus and wastes CPU time.

import pyvisa

rm = pyvisa.ResourceManager()
inst = rm.open_resource("TCPIP0::192.168.1.50::inst0::INSTR")

try:
    inst.write("MEAS:VOLT:DC?")
    # Blocks until measurement completes
    result = inst.read()
    print(f"Voltage: {result.strip()} V")
finally:
    inst.close()

With SRQ, the instrument asserts a hardware line when the operation completes. Your script sleeps until the event fires.

Wait for SRQ with wait_on_event

Enable the SRQ event, trigger a long measurement, and wait for the instrument to signal completion.

import pyvisa
from pyvisa import constants

rm = pyvisa.ResourceManager()
inst = rm.open_resource("TCPIP0::192.168.1.50::inst0::INSTR")
inst.timeout = 30000

try:
    inst.write("*RST")
    inst.write("*CLS")

    # Enable SRQ on operation complete (bit 5 of SRE)
    inst.write("*ESE 1")    # OPC sets ESR bit 0
    inst.write("*SRE 32")   # ESR summary enables SRQ

    # Enable SRQ event handling
    inst.enable_event(
        constants.EventType.service_request,
        constants.EventMechanism.queue,
    )

    # Start a slow measurement
    inst.write("CONF:VOLT:DC 10, 0.0001")
    inst.write("SAMP:COUN 100")
    inst.write("INIT")
    inst.write("*OPC")  # Set OPC when measurement finishes

    # Block until the instrument fires SRQ (up to timeout)
    response = inst.wait_on_event(
        constants.EventType.service_request, timeout=25000
    )
    print(f"SRQ received, event type: {response.event.event_type}")

    # Read the status byte to confirm
    stb = inst.read_stb()
    print(f"Status byte: {stb:#04x}")

    # Fetch the results
    data = inst.query("FETC?")
    values = [float(v) for v in data.strip().split(",")]
    print(f"Got {len(values)} readings, mean: {sum(values)/len(values):.6f} V")

    inst.disable_event(
        constants.EventType.service_request,
        constants.EventMechanism.queue,
    )
finally:
    inst.close()
    rm.close()

Log measurements automatically

TofuPilot records test results from your PyVISA scripts, tracks pass/fail rates, and generates compliance reports. Free to start.

Install an Event Handler (Callback)

For continuous monitoring, install a callback that fires every time the instrument asserts SRQ. This is useful in long-running test sequences where multiple operations complete at different times.

import pyvisa
from pyvisa import constants
import threading

done = threading.Event()

def handle_srq(resource, event, user_handle):
    stb = resource.read_stb()
    print(f"SRQ fired, status byte: {stb:#04x}")
    done.set()
    return constants.StatusCode.success

rm = pyvisa.ResourceManager()
inst = rm.open_resource("TCPIP0::192.168.1.50::inst0::INSTR")

try:
    inst.write("*RST")
    inst.write("*CLS")
    inst.write("*ESE 1")
    inst.write("*SRE 32")

    wrapped = inst.install_handler(
        constants.EventType.service_request, handle_srq
    )
    inst.enable_event(
        constants.EventType.service_request,
        constants.EventMechanism.handler,
    )

    inst.write("CONF:VOLT:DC")
    inst.write("INIT")
    inst.write("*OPC")

    done.wait(timeout=20)
    if done.is_set():
        result = inst.query("FETC?")
        print(f"Voltage: {float(result.strip()):.6f} V")
    else:
        print("Timed out waiting for SRQ")

    inst.disable_event(
        constants.EventType.service_request,
        constants.EventMechanism.handler,
    )
    inst.uninstall_handler(
        constants.EventType.service_request, wrapped, handle_srq
    )
finally:
    inst.close()
    rm.close()

Handler thread safety

The callback runs in a separate thread. Don't call inst.write() or inst.query() from inside the handler. Use a threading event or queue to communicate back to the main thread.

Event Types

Event typeConstantUse case
Service RequestEventType.service_requestInstrument signals operation complete, error, or data ready
GPIB TalkEventType.gpib_talkController addressed this device to talk
GPIB ListenEventType.gpib_listenController addressed this device to listen
VXI SignalEventType.vxi_signal_interruptVXI backplane interrupt
PXI InterruptEventType.pxi_interruptPXI hardware interrupt

Useful Status Commands

CommandWhat it does
inst.read_stb()Read the status byte without clearing it
inst.write("*SRE 32")Enable SRQ when ESR summary bit is set
inst.write("*ESE 1")Enable OPC bit in the Event Status Register
inst.write("*CLS")Clear all event registers and queues
inst.write("*OPC")Set OPC bit when all pending operations complete
inst.assert_trigger()Send a hardware trigger (Group Execute Trigger)

Status Byte Bits

BitWeightMeaning
0-11, 2Instrument-specific
24Error/event queue not empty
38Questionable data summary
416Message available (MAV)
532Event Status Byte summary (ESB)
664Request Service (RQS) / Master Summary
7128Instrument-specific