Pure Python implementation of a VISA library for instrument communication.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Serial communication support for interfacing with instruments via serial ports, USB-to-serial adapters, and virtual COM ports. The SerialSession class provides comprehensive serial communication capabilities with configurable parameters and robust error handling.
Handles serial communication with instruments using PySerial as the underlying library, supporting various serial configurations and termination modes.
class SerialSession:
"""Session for serial port communication."""
def __init__(self, resource_manager_session, resource_name, parsed, open_timeout):
"""
Initialize serial session.
Args:
resource_manager_session (VISARMSession): Parent RM session
resource_name (str): Serial resource name (e.g., "ASRL1::INSTR")
parsed (rname.ResourceName): Parsed resource name
open_timeout (int): Connection timeout in milliseconds
"""
def read(self, count):
"""
Read data from serial port.
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 serial port.
Args:
data (bytes): Data to transmit
Returns:
Tuple[int, StatusCode]: Number of bytes written and status
"""
def flush(self, mask):
"""
Flush serial port buffers.
Args:
mask (constants.BufferOperation): Buffer flush operation type
Returns:
StatusCode: Operation result
"""
def close(self):
"""
Close serial port connection.
Returns:
StatusCode: Operation result
"""
@staticmethod
def list_resources():
"""
List available serial ports.
Returns:
List[str]: List of available serial port resource strings
"""Configure serial communication parameters through VISA attributes for baud rate, data bits, parity, stop bits, and flow control.
# Common serial attributes (accessed via get_attribute/set_attribute)
VI_ATTR_ASRL_BAUD = 0x3FFF0021 # Baud rate
VI_ATTR_ASRL_DATA_BITS = 0x3FFF0022 # Data bits (5-8)
VI_ATTR_ASRL_PARITY = 0x3FFF0023 # Parity setting
VI_ATTR_ASRL_STOP_BITS = 0x3FFF0024 # Stop bits
VI_ATTR_ASRL_FLOW_CNTRL = 0x3FFF0025 # Flow control
VI_ATTR_ASRL_END_IN = 0x3FFF00B0 # Input termination method
VI_ATTR_ASRL_END_OUT = 0x3FFF00B1 # Output termination methodControl how data transmission is terminated and detected for reliable communication with various instrument protocols.
# Termination constants
VI_ASRL_END_NONE = 0 # No termination
VI_ASRL_END_LAST_BIT = 1 # Use last bit for termination
VI_ASRL_END_TERMCHAR = 2 # Use termination character
VI_ASRL_END_BREAK = 3 # Use break condition
# Parity constants
VI_ASRL_PAR_NONE = 0 # No parity
VI_ASRL_PAR_ODD = 1 # Odd parity
VI_ASRL_PAR_EVEN = 2 # Even parity
VI_ASRL_PAR_MARK = 3 # Mark parity
VI_ASRL_PAR_SPACE = 4 # Space parity
# Flow control constants
VI_ASRL_FLOW_NONE = 0 # No flow control
VI_ASRL_FLOW_XON_XOFF = 1 # Software flow control
VI_ASRL_FLOW_RTS_CTS = 2 # Hardware flow control
VI_ASRL_FLOW_DTR_DSR = 4 # DTR/DSR flow controlimport pyvisa
# Use PyVISA-py backend
rm = pyvisa.ResourceManager('@py')
# Open serial instrument
# Resource formats:
# - Windows: "ASRLCOM1::INSTR"
# - Linux: "ASRL/dev/ttyUSB0::INSTR"
# - macOS: "ASRL/dev/cu.usbserial::INSTR"
try:
inst = rm.open_resource("ASRL/dev/ttyUSB0::INSTR")
# Configure serial parameters
inst.baud_rate = 9600
inst.data_bits = 8
inst.parity = pyvisa.constants.Parity.none
inst.stop_bits = pyvisa.constants.StopBits.one
inst.flow_control = pyvisa.constants.ControlFlow.none
# Set termination characters
inst.read_termination = '\\n'
inst.write_termination = '\\n'
# Set timeout
inst.timeout = 2000 # 2 seconds
# Send commands
inst.write("*IDN?")
response = inst.read()
print("Instrument ID:", response.strip())
# Query shortcut (write + read)
response = inst.query("*IDN?")
print("ID:", response.strip())
finally:
inst.close()
rm.close()from pyvisa import constants
# Open with specific configuration
inst = rm.open_resource("ASRL1::INSTR")
# Set specific serial parameters using attributes
inst.set_visa_attribute(constants.VI_ATTR_ASRL_BAUD, 115200)
inst.set_visa_attribute(constants.VI_ATTR_ASRL_DATA_BITS, 8)
inst.set_visa_attribute(constants.VI_ATTR_ASRL_PARITY, constants.VI_ASRL_PAR_EVEN)
inst.set_visa_attribute(constants.VI_ATTR_ASRL_STOP_BITS, constants.VI_ASRL_STOP_TWO)
# Configure flow control
inst.set_visa_attribute(constants.VI_ATTR_ASRL_FLOW_CNTRL, constants.VI_ASRL_FLOW_RTS_CTS)
# Set termination handling
inst.set_visa_attribute(constants.VI_ATTR_ASRL_END_IN, constants.VI_ASRL_END_TERMCHAR)
inst.set_visa_attribute(constants.VI_ATTR_ASRL_END_OUT, constants.VI_ASRL_END_TERMCHAR)
inst.set_visa_attribute(constants.VI_ATTR_TERMCHAR, ord('\\r'))
# Query current configuration
baud = inst.get_visa_attribute(constants.VI_ATTR_ASRL_BAUD)
data_bits = inst.get_visa_attribute(constants.VI_ATTR_ASRL_DATA_BITS)
print(f"Config: {baud} baud, {data_bits} data bits")# Reading binary data
inst = rm.open_resource("ASRL1::INSTR")
# Disable termination for binary data
inst.read_termination = None
inst.write_termination = None
# Request specific number of bytes
inst.write(b"DATA?")
binary_data = inst.read_bytes(1024)
print(f"Received {len(binary_data)} bytes")
# Reading with timeout
try:
data = inst.read_bytes(512, timeout=1000)
except pyvisa.VisaIOError as e:
if e.error_code == constants.StatusCode.error_timeout:
print("Read timeout occurred")
else:
raise# Flush input/output buffers
inst.flush(constants.BufferOperation.discard_read_buffer)
inst.flush(constants.BufferOperation.discard_write_buffer)
# Flush both buffers
inst.flush(constants.BufferOperation.discard_read_buffer |
constants.BufferOperation.discard_write_buffer)
# Check bytes available
try:
# Non-blocking read to check if data is available
data = inst.read_bytes(1, timeout=0)
print("Data available:", data)
except pyvisa.VisaIOError as e:
if e.error_code == constants.StatusCode.error_timeout:
print("No data available")Serial port enumeration automatically detects available serial interfaces:
# List all available serial ports
rm = pyvisa.ResourceManager('@py')
resources = rm.list_resources('ASRL?*::INSTR')
print("Serial ports:", resources)
# Typical resource strings:
# Windows: ['ASRLCOM1::INSTR', 'ASRLCOM3::INSTR']
# Linux: ['ASRL/dev/ttyUSB0::INSTR', 'ASRL/dev/ttyACM0::INSTR']
# macOS: ['ASRL/dev/cu.usbserial-123::INSTR']Common serial communication errors and their handling:
from pyvisa import VisaIOError
from pyvisa.constants import StatusCode
try:
inst = rm.open_resource("ASRL99::INSTR") # Non-existent port
except VisaIOError as e:
if e.error_code == StatusCode.error_resource_not_found:
print("Serial port not found")
elif e.error_code == StatusCode.error_resource_busy:
print("Serial port is already in use")
else:
print(f"Error opening serial port: {e}")
try:
response = inst.query("*IDN?", timeout=1000)
except VisaIOError as e:
if e.error_code == StatusCode.error_timeout:
print("Communication timeout - check connections and settings")
elif e.error_code == StatusCode.error_io:
print("I/O error - check serial configuration")Serial communication requires the optional PySerial package:
# Install PySerial support
pip install pyvisa-py[serial]
# Or install PySerial directly
pip install pyserial>=3.0Without PySerial, serial resources will not be available and attempting to open serial sessions will raise import errors.
COM1, COM2, etc.ASRLCOM1::INSTR/dev/ttyUSB0, /dev/ttyACM0, /dev/ttyS0ASRL/dev/ttyUSB0::INSTR/dev/cu.usbserial-*, /dev/cu.SLAB_USBtoUARTASRL/dev/cu.usbserial-123::INSTRInstall with Tessl CLI
npx tessl i tessl/pypi-pyvisa-py