Skip to main content

No project description provided

Project description

# keysight-b2901

A Python library for running electrochemical experiments from the Keysight B2901A / B2901BL Source-Measure Unit (SMU). Provides a clean interface for common galvanostatic and potentiostatic techniques, with built-in CSV logging, live plotting, and hardware safety limits.

Designed for 4-wire (Kelvin) sensing with the counter/sense terminals connected to a reference electrode, as is typical in 3-electrode electrochemical cells.

## Installation

pip install keysight-b2901

## Supported methods

- constant\_current — galvanostatic hold for a fixed duration

- constant\_voltage — potentiostatic hold for a fixed duration

- constant\_current\_until\_cutoff — galvanostatic hold until a voltage limit is reached

- constant\_voltage\_until\_cutoff — potentiostatic hold until a current limit is reached

- charge\_discharge\_cycle — automated galvanostatic charge/discharge cycling (GCD)

- cyclic\_voltammetry — software-stepped CV sweep at a specified scan rate

All methods accept an optional LivePlotter for real-time V and I strip-charts, and write to a thread-safe CSV via DataLogger.

---

## Usage

### Finding your instrument address

import pyvisa

rm = pyvisa.ResourceManager()

print(rm.list\_resources())

\# e.g. 'USB0::0x2A8D::0x9101::MY63320360::INSTR'

---

### Constant current hold

from keysight\_echem import KeysightB2901, DataLogger, LivePlotter, SafetyLimits



ADDR = 'USB0::0x2A8D::0x9101::MY63320360::INSTR'



safety  = SafetyLimits(max\_voltage=4.5, min\_voltage=-0.5,

                       max\_current=1.0, min\_current=-1.0)

plotter = LivePlotter(title='CC Hold', current\_unit='mA')



with KeysightB2901(ADDR, safety=safety) as smu:

    with DataLogger('cc\_hold.csv') as log:

        smu.constant\_current(

            current=0.5,          # A

            duration=120,         # s

            sample\_rate=10,       # Hz

            voltage\_compliance=5.0,

            logger=log,

            plotter=plotter,

        )



plotter.save('cc\_hold.png')

plotter.keep\_open()

---

### GITT (Galvanostatic Intermittent Titration Technique)

GITT consists of a series of current pulses each followed by a relaxation period. It can be built directly from constant\_current and constant\_current\_until\_cutoff in a loop:

from keysight\_echem import KeysightB2901, DataLogger, LivePlotter

import time



ADDR   = 'USB0::0x2A8D::0x9101::MY63320360::INSTR'

PULSES = 20



plotter = LivePlotter(title='GITT', current\_unit='mA')



with KeysightB2901(ADDR) as smu:

    with DataLogger('gitt.csv') as log:

        for i in range(PULSES):

            # --- current pulse ---

            smu.constant\_current(

                current=0.1,            # A

                duration=60,            # s per pulse

                sample\_rate=10,

                voltage\_compliance=5.0,

                logger=log,

                plotter=plotter,

                status=f'pulse\_{i+1}',

            )



            # --- relaxation (output already off; just wait and measure at OCV) ---

            smu.constant\_current(

                current=0.0,            # zero current = open circuit measurement

                duration=300,           # s relaxation

                sample\_rate=2,

                voltage\_compliance=5.0,

                logger=log,

                plotter=plotter,

                status=f'relax\_{i+1}',

            )



plotter.save('gitt.png')

plotter.keep\_open()

Each pulse/relax pair is labelled in the CSV and plotted in a distinct colour, so the titration steps are immediately visible.

---

### Conductance-based MPPT (Maximum Power Point Tracking)

The incremental conductance algorithm tracks the maximum power point of a source (e.g. a photoelectrochemical cell) by comparing the incremental conductance dI/dV to the instantaneous conductance I/V and stepping the current accordingly:

- If dI/dV + I/V > 0 → increase current (moving toward MPP)

- If dI/dV + I/V < 0 → decrease current (overshot MPP)

- If dI/dV + I/V ≈ 0 → at MPP, hold

from keysight\_echem import KeysightB2901, DataLogger, LivePlotter

import time



ADDR       = 'USB0::0x2A8D::0x9101::MY63320360::INSTR'

I\_MIN      = 0.0    # A — lower current bound

I\_MAX      = 0.5    # A — upper current bound

I\_STEP     = 0.005  # A — perturbation step size

TOLERANCE  = 1e-4   # conductance tolerance for "at MPP"

INTERVAL   = 0.5    # s between MPPT updates

DURATION   = 600    # s total run time



plotter = LivePlotter(title='MPPT', current\_unit='mA')



with KeysightB2901(ADDR) as smu:

&#x20;   with DataLogger('mppt.csv') as log:



&#x20;       current\_setpoint = 0.05   # A — initial guess

&#x20;       v\_prev, i\_prev   = None, None

&#x20;       t\_end = time.time() + DURATION



&#x20;       while time.time() < t\_end:

&#x20;           # Apply current and take a single timed sample

&#x20;           smu.constant\_current(

&#x20;               current=current\_setpoint,

&#x20;               duration=INTERVAL,

&#x20;               sample\_rate=1,

&#x20;               voltage\_compliance=5.0,

&#x20;               logger=log,

&#x20;               plotter=plotter,

&#x20;               status='mppt',

&#x20;           )



&#x20;           # Read the last logged values back from the plotter's buffer

&#x20;           seg = plotter.\_segments.get('mppt')

&#x20;           if seg is None or len(seg\['v']) < 2:

&#x20;               continue



&#x20;           v\_now = seg\['v']\[-1]

&#x20;           i\_now = seg\['i']\[-1] / 1e3   # plotter stores in mA; convert back to A



&#x20;           if v\_prev is not None:

&#x20;               dV = v\_now - v\_prev

&#x20;               dI = i\_now - i\_prev



&#x20;               if abs(dV) > 1e-6:   # avoid division by zero

&#x20;                   inc\_conductance  = dI / dV

&#x20;                   inst\_conductance = i\_now / v\_now if abs(v\_now) > 1e-6 else 0.0

&#x20;                   error = inc\_conductance + inst\_conductance



&#x20;                   if error > TOLERANCE:

&#x20;                       current\_setpoint = min(current\_setpoint + I\_STEP, I\_MAX)

&#x20;                   elif error < -TOLERANCE:

&#x20;                       current\_setpoint = max(current\_setpoint - I\_STEP, I\_MIN)

&#x20;                   # else: within tolerance, hold current



&#x20;           v\_prev, i\_prev = v\_now, i\_now



plotter.save('mppt.png')

plotter.keep\_open()

**Note:** For a real MPPT deployment you would tune I\_STEP, INTERVAL, and TOLERANCE to match the time constants of your cell. Smaller steps give finer tracking at the cost of convergence speed.

---

## Safety limits

All methods respect a SafetyLimits object that acts as a software-level emergency stop independent of the instrument's own compliance settings:

from keysight\_echem import SafetyLimits



safety = SafetyLimits(

&#x20;   max\_voltage =  4.5,   # V

&#x20;   min\_voltage = -0.5,   # V

&#x20;   max\_current =  1.0,   # A

&#x20;   min\_current = -1.0,   # A

)



smu = KeysightB2901(ADDR, safety=safety)

If either boundary is exceeded during any measurement the output is switched off immediately and the loop exits.

---

## License

MIT. Not affiliated with or endorsed by Keysight Technologies.

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

keysight_echem-0.1.1.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

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

keysight_echem-0.1.1-py2.py3-none-any.whl (14.0 kB view details)

Uploaded Python 2Python 3

File details

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

File metadata

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

File hashes

Hashes for keysight_echem-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f2eb6bef7cfa7165e0a67e702d7cbb9f694844c3ff9b50d3f4b81333a80b9a05
MD5 7642834e365d08753a7664465481e417
BLAKE2b-256 f4c43a898b353e371853f4cc3ebe5dce06a1c5af6bf740cfd42684790aa19599

See more details on using hashes here.

File details

Details for the file keysight_echem-0.1.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for keysight_echem-0.1.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 3f553368d0d4ed5ff238894a51bccc8f789394d8812f251a5b1635291c10dbd6
MD5 4933a9389bd2344ceb8578362560bd4d
BLAKE2b-256 4441e0b4998d20611e4ba59043ac925fe37e36ada6f27f4846fc2327ad1f9f22

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