axxpd
Python library for controlling an AxxPD USB-C PD 3.1 EPR power source over its SCPI interface.
AxxPD is a programmable USB-C Power Delivery tool: it draws negotiated power from a USB-C PD charger (it is a PD sink) and re-exposes it as a controllable bench-supply output, from 3.3 V up to 48 V (up to 240 W), with voltage/current/power measurement, protection, and automation over a USB CDC serial port. This library wraps that SCPI command set as a Python API and auto-discovers the device's serial port.
Installation
pip install axxpd
Requires Python 3.8+ and pyserial (installed automatically).
Before you start
- AxxPD is a sink — plug a USB-C PD charger or power bank into its input.
- The output is off at boot; call
output_on()to enable it. - Voltages above 20 V (the EPR range, up to 48 V / 240 W) require both the charger and the cable to support EPR — use a 240 W e-marked USB-C cable. Without one you're capped around 20 V.
- The voltages you can actually reach depend on what the charger advertises; AxxPD requests the closest match and reports the contract it got.
⚠️ Safety: the output can reach 48 V at up to 240 W. Current-limit or disconnect your load before enabling the output, and set set_ocp() appropriately.
Quick start
from axxpd import AxxPD, AxxPDError
try:
pd = AxxPD() # auto-detects the AxxPD serial port
except AxxPDError:
pd = AxxPD("COM10") # ...or pass the port explicitly
with pd:
print(pd.idn()) # device identity
pd.set_voltage(12.0, current=2.0) # 12 V, 2 A current limit
pd.output_on()
m = pd.measure() # dict: voltage, current, power, energy_wh,
# charge_ah, temp_die, temp_ntc
print(f"{m['voltage']:.3f} V, {m['current']:.3f} A")
for sample in pd.stream(duration=10): # ~20 Hz telemetry
print(sample)
pd.output_off()
All values are SI: volts, amps, watts, energy in Wh, charge in Ah, temperature in °C (or °F if the device's Fahrenheit setting is on).
Connecting
Auto-detect picks the STMicroelectronics Virtual COM Port (VID:PID 0483:5740) — not the ST-Link debug port. If no device is found, AxxPD() raises AxxPDError; pass the port explicitly instead. Ports look like COM10 on Windows, /dev/ttyACM0 on Linux, or /dev/cu.usbmodem* on macOS. To list candidates:
from serial.tools import list_ports
for p in list_ports.comports():
print(p.device, p.description)
All library errors (connection failure, unparseable device response) raise AxxPDError, so wrap calls in try/except AxxPDError for robust automation.
A few terms
A PD charger advertises one or more PDOs (selectable voltage/current offerings); the sink negotiates one, forming a contract. PPS and AVS are adjustable-voltage modes; EPR (Extended Power Range) unlocks voltages above 20 V, up to 48 V / 240 W.
API overview
- Identity / system:
idn(),reset(),reboot(),selftest() - Output:
output_on(),output_off(),output_state() - Set point:
set_voltage(v, current=None),set_pps(v, current=None),set_avs(v),set_pdo(index),set_mode(mode) - PD info:
list_pdos(),list_all_pdos(),contract(),enter_epr(),exit_epr() - Measurement:
measure(),measure_voltage(),measure_current(),measure_power(),measure_temperature(),measure_energy() - Protection:
set_ocp(amps),set_ovp(volts),protection_status(),protection_clear() - Sequencing:
seq_add(v, time_ms),seq_clear(),seq_list(),seq_run(),seq_stop() - Streaming:
stream(duration=None, callback=None)— yields telemetry dicts at ~20 Hz (omitdurationto stream until interrupted) - Errors: every library error raises
AxxPDError
stream() skips malformed frames silently, so the sample count over a fixed duration isn't guaranteed. set_voltage() does not raise if the source can't satisfy the request — it falls back to the nearest PDO, so confirm with measure() or contract().
Troubleshooting
| Symptom | Likely cause |
|---|---|
AxxPDError on connect / wrong port |
Device not enumerated, or the ST-Link port was picked — pass the port explicitly |
| Reads 0 V | Output not enabled (output_on()), no PD source connected, or no contract — check contract() and output_state() |
| Can't reach voltages above 20 V | No EPR — use a 240 W e-marked cable and a charger that advertises EPR |
For the full SCPI command reference and device documentation, see the project repository.
License
GPL-3.0-only. Copyright Axel Johansson.
Metadata
Release files for axxpd 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| axxpd-1.0.0.tar.gz | 21.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| axxpd-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.9 kB
Release files / axxpd-1.0.0.tar.gz
| Download URL | axxpd-1.0.0.tar.gz |
|---|---|
| Size | 21.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9791cbbd96114b787415732145e55716965463baedb80e6fd90b034b983df91f
|
|
BLAKE2b-256 checksum How to use checksums |
3392cad95ad90718ae9ca7b6169d8575bec0153ddf26837e7229529dcda4a893
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / axxpd-1.0.0-py3-none-any.whl
| Download URL | axxpd-1.0.0-py3-none-any.whl |
|---|---|
| Size | 21.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
70c28434544c6a35cd63f2d29f8d0b944649473122a848f1464b2e173bf45d43
|
|
BLAKE2b-256 checksum How to use checksums |
562e0d1ed251f5590eb33e84dfb055a32bcdd2eebd7f944dbb222fc7f4e0dd5e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|