Skip to content

Connecting Instruments

galois-edge discovers instruments on every supported bus at startup and at a configurable cadence afterward (RESCAN_INTERVAL_SEC). Each instrument is queried with *IDN?, matched against the 130+ bundled YAML profiles by regex, and registered with all of its profile-defined commands. Instruments without a profile still work — they accept raw SCPI through SendCommand.

When the daemon starts, the Python engine walks each enabled bus:

  1. GPIBlinux-gpib bus scan, primary addresses 1–30.
  2. USB — PyVISA’s list_resources() covers USBTMC. The raw-USB transport (USB_RAW_ENABLED) walks vendor IDs known not to use USBTMC (e.g. Signal Recovery lock-in amplifiers).
  3. LAN — mDNS/Zeroconf browses _lxi._tcp.local. for LXI-compliant instruments, plus any explicit addresses in LAN_INSTRUMENTS.
  4. Serial — VID/PID-tagged USB-serial adapters surfaced through PyVISA’s serial backend.

Each candidate is opened, queried with *IDN?, and matched against identity.patterns in the loaded YAML profiles. The first matching profile wins. Matched instruments expose:

  • All commands: from the profile, with typed parameters and units
  • All sequences: (multi-step measurements like IV sweeps)
  • The instrument’s settings block (timeout, terminator, OPC behavior)
  • Any SDK binding (sdk:) for non-SCPI vendor libraries
Terminal window
galois-edge status
Daemon status: RUNNING
Python gRPC: 127.0.0.1:50052
Instruments: 3 found
- Keithley 2400 (GPIB0::24::INSTR) [connected]
- Keysight 34461A (USB0::0x2A8D::0x0101::MY54505555::INSTR) [connected]
- Tektronix MSO64 (TCPIP::192.168.1.42::INSTR) [connected]

You can also call galois-edge configure list to see active bus toggles and galois-edge doctor to verify drivers are installed and udev permissions are correct.

GPIB is enabled by default on Linux (GPIB_ENABLED=auto). Install linux-gpib, load its kernel module, and configure your board.

  1. Install the kernel driver and userspace tools (Debian/Ubuntu example):

    Terminal window
    sudo apt install linux-gpib-dev linux-gpib-bin
  2. Edit /etc/gpib.conf for your board. For a typical Agilent 82357B:

    interface {
    minor = 0
    board_type = "agilent_82357a"
    pad = 0
    master = yes
    }
  3. Load the driver:

    Terminal window
    sudo gpib_config

    Verify with ibtest or ibterm. If gpib_config is missing, galois-edge doctor will flag it as a fail.

  4. Restart the daemon:

    Terminal window
    sudo systemctl restart galois-edge

To use a different board index, set GPIB_BOARD=1. To skip the slow startup scan and only scan on demand, set GPIB_SCAN_ON_INIT=false.

USBTMC instruments work out of the box on Linux — the installer drops udev rules at /etc/udev/rules.d/99-galois-edge.rules granting the plugdev group access to common vendors:

VendorUSB VID
Keysight / Agilent0x0957
Tektronix0x0699
Rohde & Schwarz0x0aad
National Instruments0x3923
Rigol0x1ab1
Siglent0xf4ec

For other vendors, you can either add a rule yourself or run the daemon as root. After the rules are installed:

Terminal window
sudo usermod -aG plugdev $USER # add yourself if needed
newgrp plugdev # pick it up without re-login
sudo udevadm control --reload-rules
sudo udevadm trigger

Verify USB permissions with:

Terminal window
galois-edge doctor
# look for: [PASS] usb_permissions: User <name> is in plugdev group

Set USB_RAW_ENABLED=true (the default) to enable the raw-USB transport for vendor-specific devices that don’t speak USBTMC. The engine ships a small set of vendor matchers — Signal Recovery (0x0A2D) lock-in amplifiers are the headline use case — and uses pyusb under the hood. Other vendors (Digilent, Keithley pico-ammeters, etc.) are typically supported through their own SDK rather than raw USB; see the SDK proxy section.

galois-edge finds LAN instruments two ways:

mDNS / Zeroconf (LAN_MDNS_ENABLED=true, default). The discovery layer browses for _lxi._tcp.local. — every LXI-compliant instrument advertises that service type. Anything responding gets queried automatically.

Static list (LAN_INSTRUMENTS). For instruments behind a router that drops mDNS, or for raw-socket devices that don’t advertise:

Terminal window
LAN_INSTRUMENTS=TCPIP::192.168.1.42::INSTR,TCPIP::scope.lab.example.com::5025::SOCKET

Use VISA resource syntax:

FormMeaning
TCPIP::host::INSTRVXI-11 (port 111 → dynamic) — the default for LXI gear
TCPIP::host::hislip0::INSTRHiSLIP — preferred for high-throughput Keysight/R&S
TCPIP::host::5025::SOCKETRaw TCP socket on port 5025 (typical SCPI-Raw port)

Apply changes with galois-edge configure set LAN_INSTRUMENTS … followed by systemctl restart galois-edge, or edit config.env directly.

USB-serial adapters (FTDI 0403, Prolific 067b, CH340 1a86, CP210x 10c4) are auto-recognised. Linux users need to be in the dialout group:

Terminal window
sudo usermod -aG dialout $USER

Profiles for serial instruments declare interfaces: with type: serial and the expected baud rate, parity, data bits, and stop bits — discovery reads those fields rather than guessing.

Take a Keithley 2400 sourcemeter. Its *IDN? response looks like:

KEITHLEY INSTRUMENTS INC.,MODEL 2400,1234567,C30

The bundled profile keithley_2400.yaml contains:

identity:
query: "*IDN?"
pattern: "KEITHLEY INSTRUMENTS INC.,MODEL 24[0-4][0-9]"

(pattern: is a single regex; patterns: is the multi-regex form. Either works.)

The first profile whose pattern (or any patterns) matches case-insensitively wins. Once matched, the instrument exposes named commands like set_voltage, measure_current, sequences like iv_sweep, and any vendor SDK binding declared in the profile’s sdk: block.

To inspect what matched and what’s available:

Terminal window
grpcurl -plaintext localhost:50051 \
galois.edge.v1.EdgeDaemonService/ListInstruments
grpcurl -plaintext -d '{"instrument_id": "GPIB0::24::INSTR"}' \
localhost:50051 \
galois.edge.v1.EdgeDaemonService/GetCapabilities

Instruments without a matching profile still appear in ListInstruments and accept raw SCPI through SendCommand — they just have no commands or sequences to advertise.

If you have an instrument with no bundled profile, you have three options:

  1. Use it as raw SCPI. No setup required — just open a session and send commands.
  2. Write a YAML profile. Drop it in your PROFILE_DIR (or contribute it upstream). See Instrument Profiles for the schema.
  3. Bind a vendor SDK. For non-SCPI instruments (Quantum Design PPMS, Zurich Instruments MFLI, etc.), write a profile with an sdk: block that points at a Python package. The daemon importlib-loads it on demand.

Periodic rescans run every RESCAN_INTERVAL_SEC seconds (default 60). To force one immediately, call the gRPC method:

Terminal window
grpcurl -plaintext localhost:50051 \
galois.edge.v1.EdgeDaemonService/ScanInstruments

Newly discovered instruments appear in subsequent ListInstruments calls and are pushed in the next heartbeat.

SymptomLikely causeFix
[FAIL] python_health: Cannot reach Python gRPCPython engine crashedjournalctl -u galois-edge -n 100 for tracebacks
Instrument missing on USBPermissionsVerify plugdev group, run sudo udevadm trigger
Instrument shows but *IDN? is emptyWrong terminatorSome serial instruments use \r\n — set in profile settings.terminator
GPIB scan times outBus contention or wrong boardibtest to confirm; set GPIB_SCAN_ON_INIT=false and trigger ScanInstruments manually
LAN instrument visible to ping but not discoveredmDNS blocked or non-LXIAdd to LAN_INSTRUMENTS explicitly