CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyvisa-py

Pure Python implementation of a VISA library for instrument communication.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

gpib-communication.mddocs/

GPIB Communication

General Purpose Interface Bus (GPIB/IEEE 488) communication for controlling GPIB instruments with support for bus management, device addressing, and control operations. PyVISA-py provides comprehensive GPIB support through linux-gpib and gpib-ctypes backends with automatic device discovery and proper bus control.

Capabilities

GPIBSessionDispatch Class

Main dispatcher for GPIB instrument communication that automatically creates the appropriate session implementation (native GPIB or Prologix adapter) based on the GPIB board configuration.

class GPIBSessionDispatch:
    """Dispatcher that creates native GPIB or Prologix sessions based on board configuration."""
    
    def __new__(cls, resource_manager_session, resource_name, parsed, open_timeout):
        """
        Create appropriate GPIB session based on board configuration.
        
        Args:
            resource_manager_session (VISARMSession): Parent RM session
            resource_name (str): GPIB resource name
            parsed (rname.ResourceName): Parsed resource name
            open_timeout (int): Connection timeout in milliseconds
            
        Returns:
            GPIBSession or PrologixInstrSession: Implementation-specific session
        """

GPIBSession Class

Native GPIB instrument communication using linux-gpib or gpib-ctypes drivers with full IEEE 488.2 protocol support.

class GPIBSession:
    """Session for native GPIB instrument communication."""
    
    def __init__(self, resource_manager_session, resource_name, parsed, open_timeout):
        """
        Initialize GPIB instrument session.
        
        Args:
            resource_manager_session (VISARMSession): Parent RM session
            resource_name (str): GPIB resource name (e.g., "GPIB0::10::INSTR")
            parsed (rname.ResourceName): Parsed resource name
            open_timeout (int): Connection timeout in milliseconds
        """
    
    def read(self, count):
        """
        Read data from GPIB instrument.
        
        Args:
            count (int): Maximum number of bytes to read
            
        Returns:
            Tuple[bytes, StatusCode]: Data read and operation status
        """
    
    def write(self, data):
        """
        Write data to GPIB instrument.
        
        Args:
            data (bytes): Data to transmit
            
        Returns:
            Tuple[int, StatusCode]: Number of bytes written and status
        """
    
    def gpib_command(self, command_byte):
        """
        Send GPIB command bytes (ATN asserted).
        
        Args:
            command_byte (bytes): GPIB command bytes to send
            
        Returns:
            Tuple[int, StatusCode]: Bytes written and status
        """
    
    def read_stb(self):
        """
        Read status byte from GPIB device.
        
        Returns:
            Tuple[int, StatusCode]: Status byte value and operation status
        """
    
    def clear(self):
        """
        Clear GPIB device (send Device Clear command).
        
        Returns:
            StatusCode: Operation result
        """
    
    def close(self):
        """
        Close GPIB session and release device.
        
        Returns:
            StatusCode: Operation result
        """
    
    @staticmethod
    def list_resources():
        """
        List available GPIB instruments.
        
        Returns:
            List[str]: List of GPIB instrument resource strings
        """

GPIBInterface Class

Provides GPIB bus controller operations for managing the GPIB bus and controlling multiple devices.

class GPIBInterface:
    """Session for GPIB interface/controller operations."""
    
    def __init__(self, resource_manager_session, resource_name, parsed, open_timeout):
        """
        Initialize GPIB interface session.
        
        Args:
            resource_manager_session (VISARMSession): Parent RM session
            resource_name (str): GPIB interface resource name (e.g., "GPIB0::INTFC")
            parsed (rname.ResourceName): Parsed resource name
            open_timeout (int): Connection timeout in milliseconds
        """
    
    def gpib_send_ifc(self):
        """
        Pulse Interface Clear (IFC) line for at least 100 microseconds.
        
        Returns:
            StatusCode: Operation result
        """
    
    def gpib_control_ren(self, mode):
        """
        Control state of Remote Enable (REN) interface line.
        
        Args:
            mode (constants.RENLineOperation): REN line operation
            
        Returns:
            StatusCode: Operation result
        """
    
    def gpib_control_atn(self, mode):
        """
        Control state of Attention (ATN) line.
        
        Args:
            mode (constants.ATNLineOperation): ATN line operation
            
        Returns:
            StatusCode: Operation result
        """
    
    def gpib_pass_control(self, primary_address, secondary_address):
        """
        Pass controller in charge (CIC) to another device.
        
        Args:
            primary_address (int): Primary address of new controller
            secondary_address (int): Secondary address (or VI_NO_SEC_ADDR)
            
        Returns:
            StatusCode: Operation result
        """

GPIB Bus Management

Operations for managing GPIB bus state, addressing, and device control.

# GPIB addressing constants
VI_NO_SEC_ADDR = 0xFFFF  # No secondary address

# REN line operations
VI_GPIB_REN_DEASSERT = 0      # Deassert REN line
VI_GPIB_REN_ASSERT = 1        # Assert REN line  
VI_GPIB_REN_DEASSERT_GTL = 2  # Deassert REN and send GTL
VI_GPIB_REN_ASSERT_ADDRESS = 3 # Assert REN and address device
VI_GPIB_REN_ASSERT_LLO = 4    # Assert REN and send LLO

# ATN line operations  
VI_GPIB_ATN_DEASSERT = 0      # Deassert ATN line
VI_GPIB_ATN_ASSERT = 1        # Assert ATN line
VI_GPIB_ATN_DEASSERT_HANDSHAKE = 2 # Deassert ATN with handshake
VI_GPIB_ATN_ASSERT_IMMEDIATE = 3   # Assert ATN immediately

Usage Examples

Basic GPIB Instrument Communication

import pyvisa

# Use PyVISA-py backend
rm = pyvisa.ResourceManager('@py')

# List GPIB instruments
gpib_resources = rm.list_resources('GPIB?*::INSTR')
print("GPIB instruments:", gpib_resources)

# Resource string format: GPIB[board]::primary_address[::secondary_address]::INSTR
# Examples: "GPIB0::10::INSTR", "GPIB0::5::2::INSTR" (with secondary address)

if gpib_resources:
    try:
        # Open GPIB instrument at primary address 10
        inst = rm.open_resource("GPIB0::10::INSTR")
        
        # Configure timeout
        inst.timeout = 5000  # 5 seconds
        
        # Standard IEEE 488.2 communication
        idn = inst.query("*IDN?")
        print("Instrument ID:", idn.strip())
        
        # Reset and clear instrument
        inst.write("*RST")
        inst.write("*CLS")
        
        # Check operation complete
        inst.write("*OPC?")
        opc = inst.read()
        print("Operation complete:", opc.strip())
        
        # Read measurement
        inst.write("READ?")
        measurement = float(inst.read())
        print(f"Measurement: {measurement}")
        
    except pyvisa.VisaIOError as e:
        print(f"GPIB communication error: {e}")
    finally:
        inst.close()

rm.close()

GPIB Bus Controller Operations

# Open GPIB interface for bus control operations
try:
    gpib_intfc = rm.open_resource("GPIB0::INTFC")
    
    # Send Interface Clear to reset bus
    gpib_intfc.send_ifc()
    print("Interface Clear sent")
    
    # Assert Remote Enable for all devices
    gpib_intfc.control_ren(pyvisa.constants.VI_GPIB_REN_ASSERT)
    print("REN asserted")
    
    # Address device at primary address 5
    gpib_intfc.control_ren(pyvisa.constants.VI_GPIB_REN_ASSERT_ADDRESS)
    
    # Send Group Execute Trigger to all devices
    gpib_intfc.assert_trigger(pyvisa.constants.VI_TRIG_PROT_ON)
    
    # Return devices to local control
    gpib_intfc.control_ren(pyvisa.constants.VI_GPIB_REN_DEASSERT_GTL)
    print("Devices returned to local control")
    
except pyvisa.VisaIOError as e:
    print(f"GPIB interface error: {e}")
finally:
    gpib_intfc.close()

Multi-Device GPIB Communication

# Communicate with multiple GPIB devices
devices = {
    "DMM": "GPIB0::3::INSTR",      # Digital multimeter
    "PSU": "GPIB0::5::INSTR",      # Power supply  
    "GEN": "GPIB0::10::INSTR",     # Function generator
}

instruments = {}

try:
    # Open all devices
    for name, resource in devices.items():
        inst = rm.open_resource(resource)
        inst.timeout = 3000
        instruments[name] = inst
        
        # Verify communication
        idn = inst.query("*IDN?")
        print(f"{name}: {idn.strip()}")
    
    # Configure instruments
    instruments["PSU"].write("VOLT 5.0")     # Set 5V output
    instruments["PSU"].write("CURR 1.0")     # Set 1A limit
    instruments["PSU"].write("OUTP ON")      # Enable output
    
    instruments["GEN"].write("FREQ 1000")    # Set 1kHz frequency
    instruments["GEN"].write("VOLT 1.0")     # Set 1V amplitude
    instruments["GEN"].write("OUTP ON")      # Enable output
    
    # Make measurement
    instruments["DMM"].write("MEAS:VOLT:DC?")
    voltage = float(instruments["DMM"].read())
    print(f"Measured voltage: {voltage} V")
    
    # Turn off outputs
    instruments["PSU"].write("OUTP OFF")
    instruments["GEN"].write("OUTP OFF")
    
except pyvisa.VisaIOError as e:
    print(f"Multi-device error: {e}")
finally:
    # Close all instruments
    for inst in instruments.values():
        inst.close()

GPIB Status and Error Handling

# Check GPIB device status and handle errors
inst = rm.open_resource("GPIB0::10::INSTR")

try:
    # Clear status registers
    inst.write("*CLS")
    
    # Send command that might cause error
    inst.write("INVALID:COMMAND")
    
    # Check for errors using status byte
    stb = inst.read_stb()
    print(f"Status byte: 0x{stb:02X}")
    
    # Check error queue if error bit set
    if stb & 0x04:  # Error queue not empty
        error = inst.query("SYST:ERR?")
        print(f"Device error: {error.strip()}")
    
    # Check for Standard Event Status
    if stb & 0x20:  # ESB bit set
        esr = int(inst.query("*ESR?"))
        print(f"Event Status Register: 0x{esr:02X}")
        
        if esr & 0x20:  # Command error
            print("Command error detected")
        if esr & 0x04:  # Query error  
            print("Query error detected")
    
    # Wait for operation complete
    inst.write("*OPC")
    while True:
        stb = inst.read_stb()
        if stb & 0x01:  # OPC bit set
            break
        time.sleep(0.1)
    
except pyvisa.VisaIOError as e:
    print(f"Status check error: {e}")
finally:
    inst.close()

GPIB Device Discovery and Addressing

def scan_gpib_bus(board=0, max_address=30):
    """Scan GPIB bus for responding devices."""
    rm = pyvisa.ResourceManager('@py')
    found_devices = []
    
    for address in range(1, max_address + 1):
        resource_name = f"GPIB{board}::{address}::INSTR"
        try:
            # Try to open device
            inst = rm.open_resource(resource_name)
            inst.timeout = 1000  # Short timeout for scanning
            
            # Try to communicate
            idn = inst.query("*IDN?")
            found_devices.append({
                'address': address,
                'resource': resource_name,
                'id': idn.strip()
            })
            
            inst.close()
            
        except pyvisa.VisaIOError:
            # Device not responding or not present
            continue
        except Exception as e:
            # Other errors (might be non-SCPI device)
            found_devices.append({
                'address': address,
                'resource': resource_name,
                'id': f'Present but non-SCPI: {e}'
            })
    
    rm.close()
    return found_devices

# Scan for devices
print("Scanning GPIB bus...")
devices = scan_gpib_bus()

for device in devices:
    print(f"Address {device['address']}: {device['id']}")

Secondary Addressing

# Some GPIB devices support secondary addressing
# Resource format: GPIB[board]::primary::secondary::INSTR

try:
    # Open device with secondary address
    inst = rm.open_resource("GPIB0::5::2::INSTR")
    
    # Communication works normally
    idn = inst.query("*IDN?")
    print(f"Device 5.2: {idn.strip()}")
    
except pyvisa.VisaIOError as e:
    print(f"Secondary addressing error: {e}")
finally:
    inst.close()

Resource String Format

GPIB resource strings follow the VISA standard:

GPIB[board]::primary_address[::secondary_address]::INSTR
GPIB[board]::INTFC

Components:

  • board: GPIB interface board number (usually 0)
  • primary_address: GPIB primary address (1-30)
  • secondary_address: GPIB secondary address (0-30, optional)
  • INSTR: Instrument resource class
  • INTFC: Interface controller resource class

Examples:

  • GPIB0::10::INSTR - Device at primary address 10
  • GPIB0::5::2::INSTR - Device at primary 5, secondary 2
  • GPIB1::15::INSTR - Device on second GPIB board
  • GPIB0::INTFC - GPIB interface controller

Error Handling

GPIB-specific error handling and troubleshooting:

from pyvisa import VisaIOError
from pyvisa.constants import StatusCode

try:
    inst = rm.open_resource("GPIB0::10::INSTR")
except VisaIOError as e:
    if e.error_code == StatusCode.error_resource_not_found:
        print("GPIB device not found - check address and connections")
    elif e.error_code == StatusCode.error_resource_busy:
        print("GPIB device busy - another application may be using it")
    elif e.error_code == StatusCode.error_system_error:
        print("GPIB system error - check interface card and drivers")
    else:
        print(f"GPIB open error: {e}")

# Handle communication timeouts
try:
    response = inst.query("*IDN?", timeout=2000)
except VisaIOError as e:
    if e.error_code == StatusCode.error_timeout:
        print("GPIB timeout - device may not respond or be misconfigured")
    elif e.error_code == StatusCode.error_io:
        print("GPIB I/O error - check bus termination and cables")

Dependencies

GPIB communication requires platform-specific GPIB drivers:

Linux

# Install linux-gpib support
pip install pyvisa-py[gpib-ctypes]

# Or use gpib-ctypes directly
pip install gpib-ctypes>=0.3.0

Windows

# Install gpib-ctypes for Windows
pip install pyvisa-py[gpib-ctypes]
pip install gpib-ctypes>=0.3.0

Driver Requirements:

  • Linux: linux-gpib drivers and libraries
  • Windows: National Instruments GPIB drivers or Keysight Connection Expert
  • Hardware: GPIB interface card (PCIe, USB-to-GPIB, Ethernet-to-GPIB)

GPIB Hardware

Interface Cards

  • PCIe GPIB cards: High-performance, lowest latency
  • USB-to-GPIB adapters: Portable, moderate performance
  • Ethernet-to-GPIB: Remote access, network-based

Cable and Termination

  • Use proper GPIB cables (IEEE 488 standard)
  • Maximum cable length: 20 meters total, 2 meters between devices
  • Proper bus termination required (usually automatic)
  • Star topology not recommended - use linear daisy-chain

Bus Configuration

  • Maximum 15 devices per bus (including controller)
  • Each device needs unique primary address (1-30)
  • Controller typically uses address 0
  • Secondary addressing extends to 960 possible addresses

Install with Tessl CLI

npx tessl i tessl/pypi-pyvisa-py

docs

core-backend.md

gpib-communication.md

index.md

prologix-adapters.md

serial-communication.md

tcpip-communication.md

usb-communication.md

tile.json