Python library for controlling AxxPD USB-C PD 3.1 EPR sink via SCPI
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file axxpd-1.0.0.tar.gz.
File metadata
- Download URL: axxpd-1.0.0.tar.gz
- Upload date:
- Size: 21.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9791cbbd96114b787415732145e55716965463baedb80e6fd90b034b983df91f
|
|
| MD5 |
478f069488175d3357191ca216fdc6db
|
|
| BLAKE2b-256 |
3392cad95ad90718ae9ca7b6169d8575bec0153ddf26837e7229529dcda4a893
|
File details
Details for the file axxpd-1.0.0-py3-none-any.whl.
File metadata
- Download URL: axxpd-1.0.0-py3-none-any.whl
- Upload date:
- Size: 21.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70c28434544c6a35cd63f2d29f8d0b944649473122a848f1464b2e173bf45d43
|
|
| MD5 |
ab749ee1130baadf76de276fbf554ea8
|
|
| BLAKE2b-256 |
562e0d1ed251f5590eb33e84dfb055a32bcdd2eebd7f944dbb222fc7f4e0dd5e
|