Tutorial 5 · Connecting real instruments¶
Goal: understand how procedures find instruments, map them to your ports, and move a measurement from debug to real hardware. Time: ~15 minutes. Hardware: optional — you can follow along in debug mode.
What you'll learn
- How instruments are declared in
instruments.yaml. - How to auto-detect adapters with
setup_adapters. - The lifecycle from "queued" proxy to live instrument, and back to debug.
Safety first
Real source-meters and supplies can damage devices. Double-check ranges,
compliance currents and gate voltages before energizing anything. When in
doubt, prototype in debug mode (-d).
How a procedure gets its instruments¶
A procedure declares the instruments it needs as class attributes, each
queued from the Instruments config:
class It(VgMixin, LaserMixin, ChipProcedure):
instruments = InstrumentManager()
meter: Keithley2450 = instruments.queue(**Instruments.Keithley2450)
tenma_neg: TENMA = instruments.queue(**Instruments.TENMANEG)
tenma_laser: TENMA = instruments.queue(**Instruments.TENMALASER)
At class-definition time these are lightweight proxies — no hardware is
contacted yet. When you press Queue, the procedure's startup() calls
connect_instruments(), which replaces each proxy with a live instrument (or a
DebugInstrument in debug mode).
flowchart LR
Q["queue()<br/>(proxy)"] --> C["connect_all()<br/>at startup"]
C -->|real connection ok| R["Live instrument"]
C -->|fails & debug=True| D["DebugInstrument<br/>(random data)"]
R --> S["shutdown_all()"]
Step 1 — Look at instruments.yaml¶
Each instrument entry maps a logical name to an adapter (address), an identity string, and the Python class to use:
Keithley2450:
adapter: USB0::0x05E6::0x2450::04448997::0::INSTR # VISA resource string
name: Keithley 2450
IDN: KEITHLEY
target: ${class:laser_setup.instruments.keithley.Keithley2450}
TENMANEG:
adapter: COM3 # serial port
IDN: TENMA 72-2715 V6.6 SN:37793902
target: ${class:laser_setup.instruments.tenma.TENMA}
There are three flavors of adapter:
| Kind | Example | Used by |
|---|---|---|
| VISA resource string | USB0::0x05E6::0x2450::...::INSTR |
Keithley, Thorlabs |
| Serial COM port | COM3 (Windows) / /dev/ttyUSB0 (Linux) |
TENMA, PT100, Clicker |
| Proprietary serial number | USB\VID_04D8&... |
Bentham (via bendev) |
${class:...} is a resolver that
turns the dotted path into the actual Python class when the config loads.
Step 2 — Auto-detect your adapters¶
Adapter addresses differ on every machine. Rather than editing them by hand, run
the Set up Adapters script, which scans the VISA bus, reads each device's
*IDN?, matches it against instruments.yaml, and writes the discovered
addresses back:
or from the GUI: Scripts → Set up Adapters. For TENMA supplies (which share
an identical IDN) it briefly applies a voltage and asks you which one responded,
so it can tell tenma_neg/tenma_pos/tenma_laser apart.
Requires a VISA backend
Discovery needs a VISA backend (NI-VISA, or pyvisa-py installed via uv).
Without one, list_resources() returns nothing and no devices are found.
See Installation → VISA backend.
Step 3 — Run for real¶
Once adapters are correct, drop the -d flag:
Now connect_instruments() opens real connections. If a connection fails
without debug mode, the run raises an error instead of silently faking data —
that's intentional, so you never mistake simulated data for a real measurement.
Step 4 — Use toggles to skip instruments¶
You rarely need every instrument every time. The toggles you met in
Tutorial 2 translate directly into instrument
management. For example, with Laser toggle off, It calls:
which swaps that instrument for a DisabledInstrument — a no-op that safely
ignores all commands. Likewise, turning Use temperature sensor off disables
the PT100 and Clicker.
Step 5 — Calibrate the laser (real-world example)¶
A typical bench task is mapping laser-driver voltage to optical power:
- Run the
LaserCalibrationprocedure with a Thorlabs power meter to sweep voltage and record power. - Use the
find_calibration_voltagescript to interpolate the voltage that yields a desired power (in µW) from the calibration CSV.
See the LED power calibration protocol for the full bench procedure and the CLI & Scripts page for the scripts.
Recap¶
- Procedures queue instruments as proxies; they connect at
startup(). instruments.yamlmaps logical names → adapter address → instrument class.setup_adaptersauto-discovers addresses; debug mode fakes everything.- Toggles disable unused instruments via
instruments.disable(...). - Without
-d, a failed connection errors out — by design.
Where to go next¶
You now understand the whole user workflow. Next, build your own measurement:
Tutorial 6 · Write your own procedure
(For the full reference, that tutorial links into the Developer Guide.)