Skip to content

Cyclic Voltammetry Analysis

Cyclic voltammetry (CV) is a core electrochemical technique and one of velo-plot's original motivating use cases. This guide covers an end-to-end CV workflow: plotting the current–potential loop, identifying anodic/cathodic peak pairs, measuring peak separation, and estimating diffusion behaviour.

1. Plotting the voltammogram

A CV sweep produces current (I) as a function of applied potential (E), traced as a closed loop as the potential is swept forward and back.

typescript
import { createChart } from 'velo-plot'
import { PluginAnalysis } from 'velo-plot/plugins/analysis'

const chart = createChart({
  container: '#cv',
  xAxis: { label: 'E / V vs Ag/AgCl' },
  yAxis: { label: 'I / \\mu A', latex: true },
})
await chart.use(PluginAnalysis())

// `E` sweeps up then back down; `I` is the measured current.
chart.addSeries({ id: 'cv', type: 'line', data: { x: E, y: I } })

Because a CV curve doubles back on itself, plot it as a single ordered series (the forward and reverse scans share the series) so the hysteresis loop renders correctly.

2. Locating redox peaks

The anodic (oxidation) and cathodic (reduction) peaks are the local extrema of the current. Split the loop into forward and reverse scans, then run peak detection on each half:

typescript
const turningPoint = E.indexOf(Math.max(...E)) // apex of the sweep
const forward = { x: E.slice(0, turningPoint), y: I.slice(0, turningPoint) }
const reverse = { x: E.slice(turningPoint), y: I.slice(turningPoint) }

const anodic = chart.analysis.detectPeaksInData(forward, { minProminence: 1 })
const cathodic = chart.analysis.detectPeaksInData(
  { x: reverse.x, y: reverse.y.map((v) => -v) }, // invert to find minima
  { minProminence: 1 },
)

3. Peak separation (ΔEp)

The peak-to-peak separation is diagnostic of electrochemical reversibility:

typescript
const Epa = anodic[0].x     // anodic peak potential
const Epc = cathodic[0].x   // cathodic peak potential
const deltaEp = Math.abs(Epa - Epc)

chart.addAnnotation({
  type: 'text',
  x: (Epa + Epc) / 2,
  y: 0,
  text: `\\Delta E_p = ${(deltaEp * 1000).toFixed(0)}\\,\\text{mV}`,
  latex: true,
})

For a reversible one-electron couple at 25 °C, ΔEp ≈ 59 mV; larger values indicate quasi-reversible or irreversible kinetics.

4. Randles–Ševčík: diffusion check

Peak current scales with the square root of scan rate for a diffusion-controlled process. Fit Ip vs √ν with the regression plugin:

typescript
import { PluginRegression } from 'velo-plot/plugins/regression'
await chart.use(PluginRegression())

const sqrtRate = scanRates.map(Math.sqrt)
const fit = chart.regression.fit(
  { x: sqrtRate, y: peakCurrents },
  { type: 'linear' },
)
// A high fit.r2 (≈1) confirms diffusion control.

5. Polar / radar comparison of samples (optional)

To compare several electrochemical descriptors (ΔEp, Ipa/Ipc ratio, onset potential, peak current) across samples at a glance, feed them to a radar chart via PluginRadar.

Released under the MIT License.