Hardware Drivers

Connect and control test instruments, fixtures, and custom hardware

Overview

SeqMaster's hardware abstraction layer provides a unified interface for controlling various test instruments. Drivers are auto-detected on startup and can be used immediately in test sequences.

🔌

Plug & Play

Auto-detection of USB/GPIB/Serial devices

🌳

Capability Tree

Organized by function, not brand

🔧

Extensible

Easy Python API for custom drivers

Supported Devices

📊

Digital Multimeters

Voltage, current, resistance measurements

Keysight 34461A / 34465A / 34470A
Fluke 8845A / 8846A
Keithley 2000 / 2100
Rigol DM3058 / DM3068
Siglent SDM3055
HP/Agilent 34401A

Power Supplies

DC power with voltage/current control

Rigol DP832 / DP831 / DP821
Keysight E36xx Series
Siglent SPD3303X
BK Precision 9130B
Korad KA3005P
TDK-Lambda Z+ Series
📈

Oscilloscopes

Waveform capture and analysis

Rigol DS1054Z / DS1104Z
Keysight DSOX1xxx / DSOX3xxx
Siglent SDS1xxx / SDS2xxx
Tektronix TBS1xxx / TBS2xxx
🎛️

DAQ & GPIO

Digital I/O, analog input/output

Raspberry Pi GPIO (native)
Arduino (via Firmata)
LabJack U3 / U6 / T7
MCC USB-1608 / USB-2408
Quanser Q2-USB / Q8-USB
Modbus RTU/TCP devices
📦

Additional Hardware

Signal generators, counters, programmers

Rigol DG1022Z Function Generator
FTDI USB-Serial Adapters
Barcode Scanners (HID)
Zebra Label Printers
J-Link / ST-Link Programmers
Custom Serial/TCP Devices

Configuration

Hardware is configured in the hardware_config.yaml file. Devices can be auto-detected or explicitly configured.

hardware_config.yaml
# Auto-detection settings
auto_detect:
  enabled: true
  usb: true
  serial: true
  gpib: true
  tcp: false  # Requires explicit config

# Explicit device configurations
devices:
  # USB TMC device (auto-detect friendly)
  - name: main_dmm
    driver: keysight_34461a
    connection:
      type: usb_tmc
      serial: MY54321  # Optional: specific unit
    config:
      default_timeout: 5.0
      
  # TCP/IP device (must be explicit)
  - name: network_psu
    driver: rigol_dp832
    connection:
      type: tcp
      address: "192.168.1.100"
      port: 5555
      
  # Serial device
  - name: test_fixture
    driver: custom_fixture
    connection:
      type: serial
      port: "/dev/ttyUSB0"
      baudrate: 115200
      parity: none
      stopbits: 1
      
  # GPIB device
  - name: legacy_counter
    driver: hp_53131a
    connection:
      type: gpib
      address: 12
      adapter: prologix

Creating Custom Drivers

Custom drivers can be created by extending the base driver class. Place your driver in the drivers/ directory.

drivers/my_custom_dmm.py
from seqmaster.drivers.base import BaseDriver, DriverCapability
from seqmaster.drivers.registry import register_driver


@register_driver(
    name="my_custom_dmm",
    vendor="MyCompany",
    models=["DMM-1000", "DMM-2000"],
    usb_ids=[("1234", "5678")]  # VID, PID for auto-detect
)
class MyCustomDMM(BaseDriver):
    """Driver for MyCompany DMM-1000/2000 series."""
    
    # Declare capabilities this driver provides
    capabilities = [
        DriverCapability.MEASURE_DC_VOLTAGE,
        DriverCapability.MEASURE_DC_CURRENT,
        DriverCapability.MEASURE_RESISTANCE,
    ]
    
    def initialize(self):
        """Initialize the device."""
        self.write("*RST")  # Reset to defaults
        self.write("*CLS")  # Clear status
        
        # Verify identity
        idn = self.query("*IDN?")
        self.logger.info(f"Connected to: {idn}")
        
    def measure_dc_voltage(self, range="AUTO") -> float:
        """Measure DC voltage.
        
        Args:
            range: Measurement range (AUTO, 0.1, 1, 10, 100, 1000)
            
        Returns:
            Measured voltage in volts
        """
        self.write(f"CONF:VOLT:DC {range}")
        value = self.query("READ?")
        return float(value)
        
    def measure_dc_current(self, range="AUTO") -> float:
        """Measure DC current."""
        self.write(f"CONF:CURR:DC {range}")
        value = self.query("READ?")
        return float(value)
        
    def measure_resistance(self, range="AUTO", four_wire=False) -> float:
        """Measure resistance."""
        mode = "FRES" if four_wire else "RES"
        self.write(f"CONF:{mode} {range}")
        value = self.query("READ?")
        return float(value)
        
    def close(self):
        """Cleanup when disconnecting."""
        self.write("*RST")  # Reset before closing
        super().close()

💡 Tip: Using Capability Aliases

By declaring capabilities, your driver automatically gets aliases. For example, MEASURE_DC_VOLTAGE allows the driver to be referenced as dmm or voltmeter in sequences.

Capability Tree

The capability tree organizes hardware by function rather than brand. This allows sequences to request capabilities instead of specific devices, enabling hardware substitution.

Capability Tree Structure
measurement:
  voltage:
    dc:
      - keysight_34461a
      - fluke_8845a
      - rigol_dm3058
    ac:
      - keysight_34461a
      - fluke_8845a
  current:
    dc:
      - keysight_34461a
      - keithley_2000
    ac:
      - keysight_34461a
  resistance:
    two_wire:
      - keysight_34461a
      - fluke_8845a
    four_wire:
      - keysight_34461a
      - keithley_2000

source:
  dc_power:
    - rigol_dp832
    - keysight_e36xx
    - siglent_spd3303x
  waveform:
    - rigol_dg1022z
    - siglent_sdg1032x

digital_io:
  gpio:
    - raspberry_pi_gpio
    - arduino_firmata
    - labjack_u3
  relay:
    - usb_relay_hid
    - modbus_relay
Using Capabilities in Sequences
steps:
  - id: measure_voltage
    name: Measure VCC
    type: measurement
    
    # Option 1: Request by capability (recommended)
    capability: measurement.voltage.dc
    
    # Option 2: Request specific driver
    # driver: keysight_34461a
    
    # Option 3: Request by device name
    # device: main_dmm
    
    action: measure_dc_voltage
    params:
      range: 10
    limits:
      low: 4.8
      high: 5.2

Next Steps

Continue learning about SeqMaster: