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 type | Constant | Use case |
|---|---|---|
| Service Request | EventType.service_request | Instrument signals operation complete, error, or data ready |
| GPIB Talk | EventType.gpib_talk | Controller addressed this device to talk |
| GPIB Listen | EventType.gpib_listen | Controller addressed this device to listen |
| VXI Signal | EventType.vxi_signal_interrupt | VXI backplane interrupt |
| PXI Interrupt | EventType.pxi_interrupt | PXI hardware interrupt |
Useful Status Commands
| Command | What 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
| Bit | Weight | Meaning |
|---|---|---|
| 0-1 | 1, 2 | Instrument-specific |
| 2 | 4 | Error/event queue not empty |
| 3 | 8 | Questionable data summary |
| 4 | 16 | Message available (MAV) |
| 5 | 32 | Event Status Byte summary (ESB) |
| 6 | 64 | Request Service (RQS) / Master Summary |
| 7 | 128 | Instrument-specific |