Validated Measurements
Raw SCPI gets the job done, but it puts the burden on you to remember valid ranges, parse response strings, and sequence multi-step operations correctly. pymeasure drivers handle all of that. They validate parameters before commands reach the instrument, parse typed responses, and encode complex SCPI sequences behind simple method calls. This tutorial walks through the difference using a Keithley 2400 source-measure unit.
Prerequisites
Section titled “Prerequisites”Before starting this tutorial, make sure you have:
- Completed the Getting Started and First Measurement tutorials
- The pymeasure optional dependency installed
- A supported instrument reachable through a connected backend
Install the pymeasure extra if you have not already:
uv add mcpyvisa[pymeasure]pip install mcpyvisa[pymeasure]cd /path/to/mcgpibuv sync --extra pymeasureWhen pymeasure is installed, four additional tools become available: instrument_inspect, instrument_get, instrument_set, and instrument_call. If you do not see them in your tool list, the dependency is not installed correctly.
Discover what the driver knows
Section titled “Discover what the driver knows”The first step with a pymeasure-backed instrument is always instrument_inspect. It tells you what the driver can do — every property, every method, with validation constraints.
This tutorial uses a Keithley 2400 with the alias "smu" configured in mcpyvisa.toml:
[instruments.smu]resource = "GPIB0::24::INSTR"backend = "bench-a"You can also use the full VISA resource string ("GPIB0::24::INSTR") or any other alias you have configured for this instrument.
-
Inspect the Keithley 2400
> What can the smu do?Claude calls
instrument_inspect("smu"):pymeasure driver: keithley-2400 (Keithley2400)Instrument: smu (GPIB0::24::INSTR on bench-a)Use instrument_get/instrument_set/instrument_call for validated access.# Keithley2400## Measurements (read-only -- triggers a measurement)- `voltage` (SCPI: :MEAS:VOLT?)- `current` (SCPI: :MEAS:CURR?)- `resistance` (SCPI: :MEAS:RES?)## Controls (read + write -- get/set with validation)- `source_voltage` (SCPI: :SOUR:VOLT? / :SOUR:VOLT %g)Valid: [-210, 210]Validator: truncated_range- `source_current` (SCPI: :SOUR:CURR? / :SOUR:CURR %g)Valid: [-1.05, 1.05]Validator: truncated_range- `compliance_voltage` (SCPI: :SENS:VOLT:PROT? / :SENS:VOLT:PROT %g)Valid: [-210, 210]- `compliance_current` (SCPI: :SENS:CURR:PROT? / :SENS:CURR:PROT %g)Valid: [-1.05, 1.05]- `source_mode` (SCPI: :SOUR:FUNC:MODE? / :SOUR:FUNC:MODE %s)Valid: ['current', 'voltage']- `source_enabled` (SCPI: :OUTP? / :OUTP %d)## Methods (high-level operations)- `apply_voltage(voltage_range, compliance_current)`- `apply_current(current_range, compliance_voltage)`- `enable_source()`- `disable_source()`- `shutdown()`Three things to notice in this output.
Measurements are read-only. Reading
voltagetriggers an actual measurement on the instrument and returns a float. You cannot write to a measurement property — it would not make sense to “set” a measured voltage.Controls are read/write with validation. The
source_voltageproperty accepts values from -210 to 210. The driver checks this range before sending anything over the bus. Thetruncated_rangevalidator means values outside the range are clamped to the nearest boundary rather than rejected outright.Methods are multi-step operations.
apply_voltagedoes not just set a voltage — it configures the source mode, sets the range, sets the compliance limit, and enables the output, all in the correct sequence.
Read a measurement
Section titled “Read a measurement”-
Read the voltage
> What voltage is the smu measuring?Claude calls
instrument_get("smu", "voltage"):voltage = 3.2941That is a typed float, not a raw SCPI string like
+3.29410E+00. pymeasure queried:MEAS:VOLT?, parsed the scientific notation response, and returned a number you can reason about directly. No manual parsing needed.
Configure with validation
Section titled “Configure with validation”This is where pymeasure earns its keep. Setting parameters through the driver means your values are checked before they reach the instrument.
-
Set a source voltage
> Set the smu source voltage to 5 voltsClaude calls
instrument_set("smu", "source_voltage", "5.0"):Set source_voltage = 5.0The driver checked that 5.0 falls within [-210, 210], then sent
:SOUR:VOLT 5.0to the instrument. Straightforward. -
Try an invalid value
Now suppose someone asks for a source voltage that the instrument cannot produce:
> Set the source voltage to 999 voltsClaude calls
instrument_set("smu", "source_voltage", "999"):Error: Validation error for 'source_voltage' = '999':999 is out of the range [-210, 210]The command never reached the Keithley. The driver rejected 999 because it exceeds the instrument’s output range. The bus stayed silent. The instrument is unharmed.
This matters more than it might seem. A typo in a raw
instrument_writecommand — say,:SOUR:VOLT 999— would be sent directly to the bus. Some instruments clamp silently. Others throw an error you might not notice until something smells hot. The pymeasure driver catches these mistakes at the software layer, where they are cheap to fix.
Use high-level methods
Section titled “Use high-level methods”Individual property sets are fine for tweaking one parameter. But configuring a full source-measure setup from scratch takes several steps — source mode, range, compliance, output enable — and the order matters. That is what methods are for.
-
Apply a voltage with compliance
> Configure the smu to source 5V with 100mA complianceClaude calls
instrument_call("smu", "apply_voltage", "{\"voltage\": 5.0, \"compliance_current\": 0.1}"):Called apply_voltage(voltage=5.0, compliance_current=0.1)Behind that single call, the pymeasure driver sent a sequence of SCPI commands:
:SOUR:FUNC VOLT— set source mode to voltage:SOUR:VOLT:RANG 5.0— select the appropriate range:SENS:CURR:PROT 0.1— set compliance current to 100mA:SOUR:VOLT 5.0— set the voltage level:OUTP ON— enable the output
Getting that sequence right manually with
instrument_writecalls is doable, but getting it wrong is easy — set the voltage before selecting voltage mode and the instrument ignores you silently. The method encodes the correct order. -
Read the resulting current
With the source active, measure what the DUT is drawing:
> What current is the smu drawing?Claude calls
instrument_get("smu", "current"):current = 0.0478247.82 mA. Below the 100mA compliance limit, so the Keithley is regulating voltage as requested.
Clean up
Section titled “Clean up”Source-measure units have outputs that stay active until you explicitly turn them off. Always shut down when you are done.
-
Shut down the output
> Shut down the smu outputClaude calls
instrument_call("smu", "shutdown"):Called shutdown()The
shutdownmethod disables the source output and resets the instrument to a safe state. The output relay clicks open and the front panel shows the output is off. -
Return to local control
> Return the smu to front panel controlClaude calls
instrument_local("smu"):smu returned to local controlThe RMT indicator on the Keithley’s display turns off. The front panel knobs and buttons work again.
When to use raw SCPI vs pymeasure
Section titled “When to use raw SCPI vs pymeasure”Both approaches talk to the same instrument over the same bus. The difference is where the intelligence lives.
| Raw SCPI | pymeasure | |
|---|---|---|
| Available for | Any SCPI instrument on any backend | 8 supported instruments |
| Parameter checking | None — commands go straight to the bus | Validated before sending |
| Response format | Raw string (+3.29410E+00) | Typed Python value (3.2941) |
| Multi-step operations | Manual — you sequence the commands | Encoded in methods |
| When to use | Unsupported instruments, unusual commands, diagnostics | Day-to-day operation of supported instruments |
The pymeasure-guided prompt can help you decide. It inspects the instrument first, and if a pymeasure driver exists, it steers toward the validated tools. If not, it falls back to raw SCPI automatically.
> Use the pymeasure-guided prompt for the smuThis triggers a guided workflow that walks through inspection, configuration, measurement, and cleanup in sequence.
What is next
Section titled “What is next”- Prompts Reference — all guided workflows, including
pymeasure-guidedfor driver-assisted measurements - Universal Tools Reference — full details on query, write, identify, and reset
- Architecture — how pymeasure, pyvisa, and the async backend system work together under the hood