Skip to content
robin-cachy edited this page Jun 19, 2026 · 5 revisions

CLI

All scripts run directly with Python and use the active workbench by default. Pass --workbench <name> to any script to override.


core/nachoVisa.py — Instrument scanner

Scans USB and LAN for VISA instruments, identifies them, and saves a workbench file.

python core/nachoVisa.py                        # scan USB + LAN, prompt for name
python core/nachoVisa.py --usb-only             # skip LAN scan
python core/nachoVisa.py --host 192.168.1.50    # probe a specific IP
python core/nachoVisa.py --subnet 192.168.1.0/24
python core/nachoVisa.py --save my_lab          # save without prompting
python core/nachoVisa.py --set-active my_lab    # switch active workbench
python core/nachoVisa.py --fix-udev             # write udev rules (Linux)
python core/nachoVisa.py --debug                # verbose output

--fix-udev creates /etc/udev/rules.d/70-usbtmc.rules so PyVISA-py can access USBTMC instruments without root. Run once, then re-plug USB instruments.

Duplicate resource strings: PyVISA-py's built-in discovery and nachoVisa's own LAN probe can find the same instrument under two slightly different resource strings (e.g. TCPIP::192.168.1.50::INSTR and TCPIP0::192.168.1.50::inst0::INSTR). nachoVisa deduplicates by serial number after the *IDN? query, so each physical instrument appears only once in the saved workbench.


core/setWorkbench.py — Apply instrument state

Drives all instruments in the active workbench to a specified state defined in a config JSON file.

GUI equivalent: The Save state / Load state / Reset all bar in the Workbench tab covers the same workflow interactively. Use setWorkbench.py for headless / scripted operation or when the GUI is not running. See Workbench and Instruments#bench-state--save-load-reset.

python core/setWorkbench.py                     # apply workbench_config.json
python core/setWorkbench.py --set foo.json      # apply a specific config file
python core/setWorkbench.py --reset-bench       # safe defaults on all instruments

--reset-bench zeroes outputs and disables all channels without needing a config file. The state files saved by the GUI (workbench_states/*.json) use a compatible format and can be passed to --set.

Config format:

{
  "name": "Lab Ready",
  "hosts": ["192.168.1.100"],
  "instruments": {
    "edu36311a": {
      "outputs": [
        { "channel": 1, "voltage": 5.0, "current_limit": 0.5, "enabled": false }
      ]
    },
    "edu33211a": {
      "channels": [
        { "channel": 1, "function": "SIN", "frequency": 1000,
          "amplitude": 1.0, "amplitude_unit": "VPP", "offset": 0.0, "enabled": false }
      ]
    },
    "scope": { "reset": true }
  }
}

"hosts" lists IP addresses of Ethernet instruments (LAN instruments are not auto-discovered by the @py backend).


scripts/ — Standalone scripts

These run independently without the GUI.

Script What it does
screenshot.py Capture a screenshot from the active workbench scope and save as PNG
acAnalysis.py AC frequency sweep: step a generator through frequencies from a CSV, record Vpp on scope CH1/CH2
dcSweep.py Step one or both PSU channels across a voltage range; log V/I readings at each point
psuInterrupt.py Drive a V1 → interrupt (off or V2) → V3 cycle; sweep interrupt duration and/or voltage across multiple runs
waveformAnalysis.py Live waveform analysis: autoscale, measure freq/Vpp/risetime, save screenshot and CSV

scripts/cgb-US21x-equipment/ contains instrument-specific examples for the Keysight EDU lab kit (EDU33211A AWG, EDU34450A DMM, EDU36311A PSU) and the Korad KA3005P.


Writing your own scripts

open_by_role() returns an Instrument object — the open VISA connection and the SCPI command set for that specific instrument, bundled together. Use .scpi_dispatch() to send named operations; it looks up the correct SCPI strings in eewBackbone.json, fills in any placeholders, and sends them over the connection.

import pyvisa
from workbench import load_workbench, open_by_role

# Load the active workbench (workbenches/active.json).
# Pass a name to use a different one: load_workbench("portable_rig")
wb = load_workbench()
rm = pyvisa.ResourceManager("@py")

# open_by_role opens the VISA connection for the instrument with that role and
# loads its SCPI command set from eewBackbone.json using the family_id stored
# in the workbench file (written there when the bench was scanned with nachoVisa.py).
psu = open_by_role(rm, wb, "psu")
dmm = open_by_role(rm, wb, "dmm")

# scpi_dispatch("operation", placeholder=value, ...) sends the SCPI command(s)
# for that operation and returns the response string for queries, or None for writes.
# Operation names and their SCPI expansions are defined in core/eewBackbone.json.
psu.scpi_dispatch("set_current_limit", ch=1, value="0.5")  # 500 mA limit
psu.scpi_dispatch("output_on", ch=1)

for v in range(1, 6):
    psu.scpi_dispatch("set_voltage", ch=1, value=str(v))
    reading = dmm.scpi_dispatch("measure_vdc")
    print(f"V_set={v} V   V_meas={float(reading):.4f} V")

psu.scpi_dispatch("output_off", ch=1)

The Instrument wrapper is transparent — .write(), .query(), .timeout, and all other PyVISA attributes pass straight through to the underlying resource, so raw SCPI access works the same as before when you need it.

Because all SCPI commands go through eewBackbone.json, this script runs unchanged on any PSU and DMM family that defines set_voltage, set_current_limit, and measure_vdc — swapping instruments only requires updating the workbench file.

Clone this wiki locally