Skip to content

Use pymeasure Drivers

When a pymeasure driver exists for an instrument, mcpyvisa can validate parameters before they reach the hardware, parse typed responses, and expose high-level methods that encode multi-step SCPI sequences. Four additional tools become available: instrument_inspect, instrument_get, instrument_set, and instrument_call. The raw instrument_query and instrument_write tools remain as fallback for everything else.

pymeasure is an optional dependency. Install it with:

Terminal window
uv add mcpyvisa[pymeasure]

Once installed, the four pymeasure tools are automatically registered at server startup.

Call instrument_inspect to discover whether a pymeasure driver is available for a given instrument:

> Inspect the DMM

The LLM calls instrument_inspect("dmm"). If a driver exists, the response lists categorized properties and methods:

pymeasure driver: keithley-2000 (Keithley2000)
Instrument: dmm (GPIB0::22::INSTR on bench-a)
Use instrument_get/instrument_set/instrument_call for validated access.
## Measurements (read-only -- triggers a measurement)
- `voltage` (SCPI: :MEAS:VOLT:DC?) -- DC voltage measurement
- `current` (SCPI: :MEAS:CURR:DC?) -- DC current measurement
...
## Controls (read + write -- get/set with validation)
- `voltage_range` (SCPI: :SENS:VOLT:DC:RANG / :SENS:VOLT:DC:RANG %g)
Valid: [0.1, 1, 10, 100, 1000]
Validator: strict_discrete_set
...

You can also use a VISA resource string instead of an alias:

instrument_inspect("GPIB0::22::INSTR")

If no driver is available:

No pymeasure driver available for instrument "dmm" (GPIB0::22::INSTR).
Use instrument_query() and instrument_write() for raw SCPI access.
Supported instruments with pymeasure drivers:
- hp-33120a: pymeasure.instruments.hp.HP33120A
- hp-34401a: pymeasure.instruments.hp.HP34401A
...
Instrumentpymeasure ClassCategory
HP 33120AHP33120AFunction Generator
HP 34401AHP34401AMultimeter
HP 3478AHP3478AMultimeter
HP 8657BHP8657BSignal Generator
Agilent 4284AAgilent4284ALCR Meter
Keithley 2000Keithley2000Multimeter
Keithley 2400Keithley2400Source-Measure Unit
Keithley 6517BKeithley6517BElectrometer

Measurement properties are read-only and trigger an actual measurement on the instrument. They are not cached values.

> Read the voltage from the DMM

The LLM calls instrument_get("dmm", "voltage"):

voltage = 12.0045

The pymeasure driver sends the appropriate SCPI query, parses the response, and returns a typed Python value. No manual string parsing needed.

Control properties are read/write. Reading one queries the instrument’s current setting without triggering a measurement.

> What voltage range is the DMM set to?

The LLM calls instrument_get("dmm", "voltage_range"):

voltage_range = 100

This tells you the instrument is currently configured for the 100V range. The instrument is not disturbed — it just reports its setting.

Use instrument_set to change a control property. The pymeasure driver validates the value against its defined constraints before sending anything to the instrument.

> Set the voltage range on the DMM to 10

The LLM calls instrument_set("dmm", "voltage_range", "10"):

Set voltage_range = 10

If you pass a value outside the driver’s allowed set:

> Set the voltage range on the DMM to 50

The LLM calls instrument_set("dmm", "voltage_range", "50"):

Validation error for 'voltage_range' = '50': 50 is not in the discrete set [0.1, 1, 10, 100, 1000]

The instrument never receives the command. The pymeasure validator (strict_discrete_set, truncated_range, strict_range) rejects the value before it reaches the bus.

Methods encode multi-step operations that would otherwise require manually constructing several SCPI commands in sequence.

> Apply 5V with 100mA compliance on the Keithley 2400

The LLM calls instrument_call("smu", "apply_voltage", '{"voltage": 5.0, "compliance_current": 0.1}'):

Called apply_voltage(voltage=5.0, compliance_current=0.1)

Internally, the pymeasure driver configures the source mode, sets the voltage, sets the compliance limit, and enables the output — all from a single method call.

> Shut down the Keithley 2400

The LLM calls instrument_call("smu", "shutdown"):

Called shutdown()

The kwargs_json parameter accepts a JSON string. For methods with no arguments, omit it or pass "{}". For methods with arguments, pass a JSON object:

'{"voltage": 5.0, "compliance_current": 0.1}'

When no pymeasure driver exists for an instrument, use instrument_query and instrument_write directly. The pymeasure-guided prompt guides this decision.

> Inspect the function generator

The LLM calls instrument_inspect("funcgen"):

No pymeasure driver available for instrument "funcgen" (GPIB0::14::INSTR).
Use instrument_query() and instrument_write() for raw SCPI access.

From here, use instrument_query and instrument_write:

instrument_query("funcgen", "MEAS:VOLT:DC?") -> +4.56789012E+00
instrument_write("funcgen", "CONF:VOLT:DC 10,0.001")
instrument_query("funcgen", "READ?") -> +4.56789012E+00

You can use both approaches on the same instrument. pymeasure handles the common operations; raw SCPI handles instrument-specific commands the driver does not cover.

For example, on a Keithley 2400 configured as alias "smu":

# Use pymeasure for standard configuration
instrument_set("smu", "source_mode", "voltage")
instrument_set("smu", "source_voltage", "5.0")
# Use raw SCPI for a command the pymeasure driver doesn't expose
instrument_write("smu", ":SYST:BEEP:STAT OFF")
# Read a measurement through pymeasure
instrument_get("smu", "current")

The pymeasure driver and raw SCPI tools share the same backend connection. Commands are serialized through the backend lock regardless of which tool sends them.