An adjustable power supply for motor drives using USB-C Power Delivery negotiation, supporting up to 240W at 48V 5A. This device is designed to be compatible with USB-PD up to 3.2. Firmware runs on a Raspberry Pi Pico (RP2040).
Follow the latest project logs and updates on
Hackaday.io
Warning
Disclaimer: Firmware v2.0.0 includes guarded AVS/EPR negotiation, startup restore, and EPR-exit handling, but high-voltage charger interoperability still depends on the source and cable combination you test with. Validate 28V/36V/48V operation on your hardware.
- Features
- Hardware
- Quick Start
- Controls
- Firmware Structure
- Want one?
- Planned Features
- Acknowledgements
- USB-C Power Delivery: Negotiates Fixed, PPS (3.3-21V programmable), and AVS (15-48V EPR) profiles
- Current Limiting: Adjustable 10mA-5A via INA228 power monitor with hardware overcurrent protection
- LCD Interface: 240x320 ST7789 display with anti-aliased fonts and Prusa-style encoder navigation
- Safety: Overcurrent ISR, overtemperature monitoring (NTC + INA228)
- Settings Persistence: User settings stored in RP2040 flash with CRC32 validation
- Auto PPS/AVS Tuning: Closed-loop voltage correction for PPS/AVS charger output accuracy
- Charger Diagnostics: On-device PD revision, charger identity, cable inference, and max-power reporting
- Remote CLI: USB serial command interface for measurements, PD selection, and settings updates
- Energy Monitoring: Tracks mAh delivered since boot via INA228 charge accumulator
- 17V Buck Output: Optional mock STO/SBC voltage for motor drive safety circuits
- Configurable: Brightness, auto-dim, startup melody, auto-output on boot and more
| Type | Path | Contents |
|---|---|---|
| PCB (STEP) | 3D_models/PD240W_PCB.stp |
Full PCB 3D model |
| Enclosure (STL) | 3D_models/enclosure/ |
Casing top/bottom, knob, button, LCD support, SWD cover |
| Gerbers | PCB_files/Manufacturing/Fabrication/ |
PCB manufacturing files |
| BOM | PCB_files/Manufacturing/Assembly/ |
Bill of materials |
| Pick & Place | PCB_files/Manufacturing/Assembly/ |
Pick and place file |
USB data lines (D+/D-) are reversed in the current PCB revision, preventing native USB communication between the RP2040 and the USB host. This can be easily fixed by crossing the D+ and D- lines on the PCB by crossing the series 27Ω resistors as shown below:
- Download
PD240W.uf2from the latest release - Hold BOOTSEL button on the Pico while connecting USB
- Drag
PD240W.uf2to the mountedRPI-RP2drive
Requires: Pico SDK 2.2.0, ARM GCC toolchain, CMake, Ninja
git clone --recurse-submodules https://github.com/theohg/PD240W.git
cd PD240W
mkdir -p build && cd build
cmake -G Ninja ..
ninjaThe output binary is build/PD240W.uf2.
The INA228 driver is tracked as a Git submodule in external/ina228_multiplatform. If you already cloned the repository without submodules, run:
git submodule update --init --recursivePD240W does not automatically follow the newest INA228 library release. The version is pinned by the parent repository's recorded submodule commit for external/ina228_multiplatform, and that exact checked-out commit is what gets compiled into the firmware. Prebuilt PD240W.uf2 releases already include that pinned INA version.
openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg \
-c "adapter speed 5000; program build/PD240W.elf verify reset exit"Important
EEPROM Initial Setup: Before full PD negotiation can work, you must flash the TPS26750 EEPROM configuration. This is done via the EEPROM Flash workflow found in the Settings menu.
Note: Before the EEPROM is flashed, the board will only power on when connected to a standard 5V non-PD charger (USB BC1.2 mode).
Once the firmware has been successfully flashed, connect the device to a compatible USB-PD power source and interact with the encoder and buttons to navigate the menus and adjust settings as explained below.
Note
Finding a compact and affordable charger supporting USB-PD 3.1 (up to 48V EPR) is currently quite rare. Here are a few known options:
| Model | Max single-port PD Output | Voltage Profile | Approx. Price |
|---|---|---|---|
| UGREEN Nexode 140W | 140W | 28V @ 5A | ~60€ |
| Framework Power Adapter - 180W | 180W | 36V @ 5A | ~109€ |
| HKY 240W GaN Charger | 240W | 48V @ 5A | ~90€ |
| Framework Power Adapter - 240W | 240W | 48V @ 5A | ~120€ |
| UGREEN NEXODE 500W | 240W | 48V @ 5A | ~250€ |
| Input | Action |
|---|---|
| Encoder Rotate | Navigate menus / Adjust values |
| Encoder Click | Confirm / Select |
| BTN1 (top) | Toggle load switch output |
| BTN2 (bottom) | Toggle 17V buck (requires VBUS > 18V) |
graph TD
%% Nodes
Boot([Boot]) -->|≤2s| Main[Main Screen]
Main -->|Error| Fault[Fault Screen]
Fault -->|Click| Main
Main <-->|Click| Menu[Main Menu]
Menu --> Voltage[Select Voltage]
Menu --> Current[Current Limit]
Menu --> Settings[Settings]
Menu --> AboutFirmware[About PD240W]
Menu --> AboutCharger[About This Charger]
Menu --> Back[Back]
Voltage <-->|Select PDO| AdjV[Adjust Voltage]
Current <-->|Set Limit| AdjC[Adjust Current]
Settings --> EEPROM[Flash EEPROM]
Settings --> Configs[Params: Brightness / Sounds / Tuning...]
AboutFirmware --> Main
AboutCharger --> Main
%% Styling
classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px;
classDef alert fill:#ffcccc,stroke:#cc0000,stroke-width:2px;
class Fault alert;
| Menu Item | Description |
|---|---|
| Select Voltage | Fixed / PPS / AVS PDO selection |
| Current Limit | 10mA - 5A output current limit adjustment with encoder acceleration |
| Settings | EEPROM flash workflow plus tuning, startup, brightness, and sound options |
| About PD240W | Device identity, firmware build info, flash usage, and project link |
| About This Charger | Live PD revision, CC orientation, QC inference, and cable diagnostics |
| Back | Return to the main live display |
src/
├── main.cpp Entry point, non-blocking main event loop
├── hardware.h/cpp Hardware singleton aggregating all drivers
├── interrupts.h/cpp Centralized GPIO interrupt router (RP2040 single-callback)
│
├── config/
│ ├── board_config.h Pin definitions (Board:: namespace)
│ ├── app_config.h Timeouts, thresholds, limits (AppConfig:: namespace)
│ └── version.h Firmware & hardware version, author...
│
├── drivers/ Low-level hardware drivers (no business logic)
│ ├── display/
│ │ ├── st7789.h/cpp SPI LCD driver with AA font rendering
│ │ ├── aa_font.h Anti-aliased font data structure
│ │ └── font_inter_*.h Generated Inter font bitmaps (14/20/28px)
│ ├── power/
│ │ └── tps26750/ USB-PD controller: PDO discovery, contract negotiation
│ ├── input/
│ │ ├── rotary_enc.h/cpp Quadrature encoder with velocity tracking
│ │ ├── button.h/cpp Debounced button with click/long-press
│ │ └── adc_inputs.h/cpp VBUS voltage + NTC temperature (ADC channels)
│ ├── gpio/ SimpleIO: digital output with non-blocking blink
│ ├── buzzer/ PWM buzzer with melody playback
│ └── rgb_led/ SK6812 via PIO state machine
│
├── logic/ Application logic
│ ├── state_machine.h/cpp BOOT -> MAIN <-> MENU <-> ADJUST, FAULT handling
│ ├── safety.h/cpp Temperature/voltage/current monitoring, fault triggers
│ ├── pd_manager.h/cpp PD contract caching, PPS keep-alive, auto-tuning
│ ├── settings.h/cpp Flash persistence with CRC32, debounced saves
│ └── tps_eeprom_workflow.h/cpp TPS26750 EEPROM compare/flash state machine
│
├── ui/
│ ├── display_manager.h/cpp All screen rendering (boot, main, menu, adjust, fault)
│ ├── font_config.h Central font size mapping (FONT_LARGE/MEDIUM/SMALL)
│ └── assets/synapticon_logo.h Boot screen logo bitmap
│
├── utils/
│ ├── logging.h LOG_INFO/WARN/ERROR/DEBUG/CRITICAL macros
│ ├── pd_voltage.h Shared programmable-voltage alignment helper
│ ├── tps_eeprom_loader.h/cpp Low-level TPS26750 EEPROM read/write
│ └── tps26750_patch.c TPS26750 binary configuration blob
Feel free to order assembled PCBs, flash the firmware, and test it for yourself! Manufacturing 5 assembled PCBs will cost approximately $415.
The project is open for contributions. Don't hesitate to improve the code, report bugs, or suggest new features via Pull Requests and Issues!
This repository contains different types of source files, which are licensed as follows:
All hardware design files in the PCB_files directory (Schematics, PCB layout, Gerbers, BOM) and 3D printable enclosure files are licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
You are free to download, modify, and build this board for personal, educational, and hobbyist use. However, you may not use these designs for commercial purposes (such as manufacturing and selling the boards) without prior written permission.
Please see the LICENSE.txt file for full terms.
The firmware and software source code in this repository is licensed under the MIT License.
You are free to use, modify, and distribute the software component of this project.
Please see the LICENSE-FIRMWARE.txt file for full terms.
- PPS battery charging in Constant Current (CC) mode: PPS allows a fixed current mode that can be used for battery charging. This is to be tested by charging lithium-ion battery packs.
- Improved CLI interface: Needs more testing and polish.
- Extended PPS and AVS Range: Support for PPS voltages as low as 3.5V, AND SPR AVS profiles down to 9V.
This project was made possible by Synapticon GmbH, who funded and supported its development. Thank you for providing the resources, hardware, and opportunity to bring PD240W to life.
Inspiration for this project was taken from the great work on portable USB-C PD power supplies by CentyLab on the PocketPD project and Alex Xia with his ProtoV MINI.
All work done on this project, from Hardware design to Firmware development, was done by me, as the sole contributor. I am grateful for the support and feedback from the community, and I hope this project can be a useful resource for anyone interested in USB-C PD power supplies!
Made with ❤️ by Théo Heng








