PyVISA
PyVISADocs

Events & SRQ

How to use PyVISA events and Service Request (SRQ) to get instrument notifications without polling. Includes callback and queue-based patterns.

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