Skip to main content

Simple library for Keithley 2400 Source Measure Unit (SMU) control over RS-232/USB-serial

Project description

keithley2400

Simple, clean Python library for controlling the Keithley 2400 Source Measure Unit (SMU) over RS-232 / USB-serial.

Features

  • Full V/I/R sourcing and measurement control via SCPI
  • Pure-Python — no National Instruments VISA required
  • Works natively on macOS (including Apple Silicon M1/M2/M3/M4), Linux, and Windows
  • Statistical sampling with mean and standard deviation
  • Generator-based voltage sweep (sweep_iv) for IV curves
  • One-liner convenience function: quick_iv_sweep()
  • Context manager support for safe resource cleanup
  • Serial port discovery helper: find_serial_port()
  • Automatic Keithley 2400 port discovery via *IDN? probing when resource=None or when a stale configured port fails

Installation

pip install keithley2400

Requirements

  • Python 3.6+
  • pyvisa >= 1.11.0
  • pyvisa-py >= 0.5.2
  • pyserial >= 3.4

Hardware Setup

The Keithley 2400 communicates over RS-232 using a USB-serial adapter.

  1. Connect the USB-serial cable between the instrument's RS-232 port and your computer.
  2. Ensure the instrument's baud rate matches (factory default: 9600 baud, 8N1).
  3. Find your port:
from keithley2400 import find_serial_port
ports = find_serial_port()
# Example output: ['ASRL/dev/cu.usbserial-FTRTKC3X::INSTR']

Quick Start

1. Connect automatically (recommended)

from keithley2400 import Keithley2400

with Keithley2400(resource=None) as k:   # auto-discovers by probing *IDN?
    print(k.idn())

2. Find your serial port manually

from keithley2400 import find_serial_port
print(find_serial_port())

3. Run an IV Sweep (one-liner)

from keithley2400 import quick_iv_sweep

voltages = [v * 0.5 for v in range(0, 21)]  # 0 to 10 V in 0.5 V steps

csv_file = quick_iv_sweep(
    voltages=voltages,
    out_csv="iv_curve.csv",
    compliance_amps=0.01,    # 10 mA current limit
    stabilize_s=0.5,         # wait 500 ms after each voltage step
    n_samples=50,            # average 50 readings per point
)
print(f"Saved: {csv_file}")

4. Full Manual Control

from keithley2400 import Keithley2400

# Using context manager (automatically turns output off and closes on exit)
with Keithley2400(resource="ASRL/dev/cu.usbserial-FTRTKC3X::INSTR") as k:
    print(k.idn())

    k.set_source_v(5.0)
    k.set_current_compliance(0.01)  # 10 mA limit
    k.configure_measure_vi()
    k.output_on()

    v, i = k.read_v_i()
    print(f"V={v:.4f} V  I={i:.6e} A")

    # Statistical sampling
    stats = k.sample_stats(param="I", n=100, delay_s=0.01, stabilize_s=0.5)
    print(f"I mean={stats['mean']:.6e} A  stdev={stats['stdev']:.2e} A")

5. Resistance Measurement

from keithley2400 import Keithley2400

with Keithley2400() as k:
    # 2-wire resistance
    k.configure_measure_ohms(method="2W")
    k.set_ohms_source_current(1e-3)  # 1 mA test current
    k.output_on()
    r = k.read_r(mode="ohms")
    print(f"R = {r:.2f} Ohm")

6. Custom IV Sweep with Generator

from keithley2400 import Keithley2400
import csv

voltages = [round(v * 0.1, 2) for v in range(0, 101)]  # 0 to 10 V

with Keithley2400() as k:
    k.output_on()
    with open("iv_data.csv", "w", newline="") as f:
        writer = csv.writer(f)
        writer.writerow(["V_set", "I_mean_A", "I_stdev_A"])
        for v, i_mean, i_stdev in k.sweep_iv(voltages, compliance_amps=0.05):
            writer.writerow([v, i_mean, i_stdev])
            print(f"V={v:.2f}  I={i_mean:.4e} A")

API Reference

Keithley2400 Class

__init__(resource, backend="@py", settings=None)

Open connection to the instrument.

Parameter Type Default Description
resource str or None None PyVISA resource string. None or "auto" triggers auto-discovery by probing serial ports with *IDN?.
backend str "@py" PyVISA backend ("@py" = pyvisa-py, no NI-VISA needed)
settings SerialSettings None RS-232 parameters (default: 9600 8N1)

Output Control

Method Description
output_on() Enable source output
output_off() Disable source output

Source Configuration

Method Description
set_source_v(volts) Source a voltage
set_source_i(amps) Source a current
set_current_compliance(amps) Set current limit (when sourcing V)
set_voltage_compliance(volts) Set voltage limit (when sourcing I)

Measurement Configuration

Method Description
configure_measure_vi(auto_range=True) Measure V and I simultaneously
configure_measure_ohms(method="2W") Resistance measurement (2W or 4W)
set_current_range(amps) Manual current measurement range

Readings

Method Returns Description
read_v_i() (float, float) Voltage and current
read_v() float Voltage only
read_i() float Current only
read_r(mode="calc") float Resistance (R=V/I or instrument ohms)

Statistical Sampling

Method Returns Description
sample_stats(param, n=50, delay_s=0.01, stabilize_s=0.0) dict Mean and stdev over N readings

Returns: {"mean": float, "stdev": float, "n": float}

IV Sweep

Method Returns Description
sweep_iv(voltages, ...) Iterator[(V, I_mean, I_stdev)] Voltage sweep generator

Utilities

Method Returns Description
idn() str Instrument identification string
get_error() str Error queue query
close() Close VISA session

SerialSettings Dataclass

Field Default Description
baud_rate 9600 Communication speed
data_bits 8 Data bits per character
parity none Parity check
stop_bits one Stop bits
terminator "\r" Line terminator (CR confirmed working)
timeout_ms 5000 Read timeout in milliseconds

Convenience Functions

find_serial_port(backend="@py") -> list

List all detected USB-serial ports.

find_keithley_resource(backend="@py", settings=None, verbose=True) -> Optional[str]

Probe detected serial ports with *IDN? and return the first one that identifies as a Keithley 2400.

quick_iv_sweep(voltages, out_csv=None, resource=..., ...) -> Optional[str]

One-liner: connect → sweep → save CSV → disconnect. Returns the CSV path.

CSV Output Format

voltage_V,current_mean_A,current_stdev_A,n_samples
0.0,+1.234567e-09,2.345e-11,50
0.5,+5.678901e-09,3.456e-11,50
1.0,+1.234567e-08,4.567e-11,50
...

Notes

  • Always call output_off() before close() (the context manager does this automatically)
  • FORM:ELEM VOLT,CURR is set in initialize() — this makes read_v_i() parsing deterministic
  • If you switch to configure_measure_ohms(), FORM:ELEM changes to RES; call configure_measure_vi() again to switch back
  • If a configured serial port goes stale, Keithley2400(..., auto_discover=True) will scan candidate serial ports and accept only one whose *IDN? response looks like a Keithley 2400
  • The @py backend works without a NI-VISA installation — fully compatible with Apple Silicon

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

keithley2400-0.1.1.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

keithley2400-0.1.1-py3-none-any.whl (12.0 kB view details)

Uploaded Python 3

File details

Details for the file keithley2400-0.1.1.tar.gz.

File metadata

  • Download URL: keithley2400-0.1.1.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for keithley2400-0.1.1.tar.gz
Algorithm Hash digest
SHA256 6dde8eff445fa10dd1e8ce7d2395608b01ee376d1b839857db0bdc3ed2e760e1
MD5 cb156170d72ae31190a569452ba88401
BLAKE2b-256 fd035d3c72ace042c89e44373a382a066b827d9c3f00122ab08d48cbf7dd5af4

See more details on using hashes here.

File details

Details for the file keithley2400-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: keithley2400-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for keithley2400-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b7f975591bff794fb82960dba6b1f2b8dc79da55fef0160189b9201cbbe07d16
MD5 483fbacf63875941679f5555896d4f95
BLAKE2b-256 e7343fd75f96f48dda6d6ccd2ea8c28e4434bc672ada166631fb9b84cc17b80c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page