-
Notifications
You must be signed in to change notification settings - Fork 1
CLI
All scripts run directly with Python and use the active workbench by default. Pass --workbench <name> to any script to override.
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.
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.pyfor 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).
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.
The pattern for every script is: load the workbench → open instruments by role → classify each instrument → dispatch SCPI commands through get_command.
import pyvisa
from workbench import load_workbench, open_by_role
from eewBackbone import classify, get_command
# 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 finds the instrument whose "role" field matches in the workbench JSON.
# Scripts stay portable — no hardcoded USB resource strings or IP addresses.
psu = open_by_role(rm, wb, "psu")
dmm = open_by_role(rm, wb, "dmm")
# classify() matches the *IDN? response to a family in eewBackbone.json
# and returns the full resolved command set for that specific instrument.
psu_fam = classify(psu.query("*IDN?"))
dmm_fam = classify(dmm.query("*IDN?"))
def dispatch(instr, family, operation, **kwargs):
"""Run one operation; return the query response, or None for write-only ops."""
result = None
for action, scpi in get_command(family, operation, **kwargs):
if action == "write":
instr.write(scpi)
elif action == "query":
result = instr.query(scpi)
return result
# Example: step PSU channel 1 from 1 V to 5 V, log DMM voltage at each point
dispatch(psu, psu_fam, "set_current_limit", ch=1, value="0.5") # 500 mA limit
dispatch(psu, psu_fam, "output_on", ch=1)
for v in range(1, 6):
dispatch(psu, psu_fam, "set_voltage", ch=1, value=str(v))
reading = dispatch(dmm, dmm_fam, "measure_vdc") # returns the query response string
print(f"V_set={v} V V_meas={float(reading):.4f} V")
dispatch(psu, psu_fam, "output_off", ch=1)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.