# PocketPD: turning a USB-C charger into a bench power supply

> PocketPD is open source firmware for a pocket-sized bench power supply that sits between a USB-C charger and a load, negotiating the PD and PPS profiles the charger publishes and giving you adjustable voltage and current with live readings on an OLED. It suits a maker who wants a small adjustable supply without buying a bench unit, and the detail to understand first is that the hardware revisions share one firmware with per-board build targets.

**CentyLab/PocketPD** — Opensource firmware for PocketPD

- Repository: https://github.com/CentyLab/PocketPD
- Stars: 536 · Forks: 54
- Language: C++
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/centylab-pocketpd

## What the device is

PocketPD turns any PPS-capable USB-C charger into a pocket-sized bench power supply. It offers simple controls via a rotary encoder knob and two buttons, while the OLED display shows live readings of voltage, current, power, energy, and more.

The arrangement is worth understanding because it is unusual for a bench supply. There is no mains input and no power supply inside. The device is a USB-C sink that negotiates with a charger, and the charger remains the source of the power. What PocketPD adds is the control layer: it reads the profiles the charger publishes, lets you pick one, and where the profile is adjustable, lets you set a voltage and a current.

That is what Programmable Power Supply, or PPS, gives you. A PPS charger publishes a range rather than a single fixed output, and the sink can ask for any point within that range. A plain fixed-profile charger publishes something like 5 volts at 3 amps and nothing else, so with one of those the device is a meter rather than a supply.

The project is by CentyLab, MIT licensed, written in C++, and the hardware is published separately in a PocketPD_HW repository. There is also a Hackaday project page. The firmware badge points at PlatformIO CI, and the other badges give the MCU as RP2040 and the framework as Arduino-Pico, so the firmware targets a Raspberry Pi Pico-class microcontroller.

The releases are v2.3.0 from 2026-07-20, v2.2.0 from 2026-06-15 and v2.1.0 from 2026-05-31, and the last push was on 2026-08-05.

The README opens with a note about the hardware, and it is worth reading because it explains the firmware's shape. The image shown is what the Limited HW1.0 looks like, but the design had to be moved away from because of difficulty during mass production. So the hardware has been through a revision cycle, and the firmware is what has to cope with that.

## The features, and the two that are not obvious

PocketPD detects and displays the full set of PDO, both Fixed and PPS, profiles, and with a PPS-capable charger it provides adjustable voltage and current controls.

The feature list has six entries. PPS Control sets voltage in 20 mV steps and current in 50 mA steps, with a knob push cycling the step size between coarse, medium and fine. Non-PD Source Passthrough means the device also works with chargers that speak no PD at all, providing live monitoring. Live Readings covers voltage, current and power. The Energy Screen shows running watt-hours, amp-hours, power and time. Then there are the two that are worth reading twice.

Cable Compensation holds your set voltage at the load instead of at the terminals, by raising the PPS request to cancel the drop across the cable.

This is the feature that makes the device usable in practice rather than merely interesting. A USB-C cable under load drops voltage, and the drop grows with current and with cable length, so a supply that regulates at its own terminals delivers less than you asked for at the far end. PocketPD measures the load-side voltage and raises the request to compensate, in 20 mV steps up to 500 mV. It runs only while the output is on and a PPS profile is active, and it resets whenever the output is off or you change profiles.

The 500 mV ceiling is the honest limit of the mechanism. That is enough to cover a typical cable at moderate current and not enough to cover a long cable at high current, which is a hardware limit rather than a software one.

Input Locking freezes the controls by holding both the L and R buttons. That is the other one to notice, because it is a safety feature rather than a convenience. A supply that can be knocked from 12 volts to 5 volts by brushing the knob while setting up a circuit is a supply that will eventually do that at the wrong moment. Locking the controls is a two-button hold, deliberately awkward so it cannot happen by accident.

The step sizes are worth noting as a design decision. Voltage in 1 V, 100 mV and 20 mV, and current in 1 A, 100 mA and 50 mA, so the knob can be coarse for setting up and fine for trimming. The fine voltage step of 20 mV is unusually fine for a supply built from a phone charger.

## The controls, and why they are context aware

PocketPD has three control buttons: a rotary encoder, which is the knob, a left button and a right button. Both short-press and long-press are supported, and the actions are context-aware, so what they do depends on where you are in the interface. The README says they encourage users to play around, since features keep being added.

On the operating screen the mapping is this. Rotating the knob adjusts the value being edited, on a PPS profile only. Tapping the knob cycles the step size from coarse to fine, again PPS only. Tapping the left button switches between editing volts and amps. Holding the left button opens the menu. Tapping the right button turns the output on or off. Holding the right button opens the energy screen. Holding both together locks or unlocks the screen.

Inside the menu, the profile picker and the settings, the knob drives navigation instead: rotate to move the cursor, push to choose, and hold the left button to go back.

That last line is the pattern to understand. The same three physical controls do two entirely different jobs depending on the screen, and only the operating screen has the knob editing a value. Once you are in a menu, the knob is a cursor. This is the standard arrangement for small-screen devices and it is worth spending the ten minutes to learn, because a knob that means two things is a knob you will mis-press.

The quick start puts the sequence together. Plug a charger in, rotate the knob at the profile picker to the profile you want, push and hold to commit, and pick a PPS profile for adjustable output. Then on the operating screen, tap the left button to switch between voltage and current, push the knob to set the step size, rotate to set the value, and tap the right button to toggle the output. Holding the right button at any time shows the watt-hours, amp-hours and elapsed time.

The one thing the quick start does not mention and the manual does is that a charger with no PPS profile still works, but the adjustable power supply feature will be missing. With a fixed profile the knob and the left button's tap do nothing, and the display shows only the rated voltage and current.

## The screens and the menu settings

The operating manual section walks through the screens with screenshots, and the structure of the interface tells you what the firmware is doing under the hood.

During boot, PocketPD shows a splash screen with the firmware version while it negotiates with the charger. That negotiation is the part that takes real time, since the charger has to enumerate and publish its profiles over the USB-C power protocol, and showing a version screen covers it.

Once negotiation finishes, the profile picker lists all the published PDO profiles from the charger. Fixed profiles show as something like `PDO 5V 3A`, and PPS profiles show their adjustable range, like `PPS 3.3~21.0V 5A`. The display of a range rather than a single value is a direct consequence of PPS: the charger is telling you what it can be asked for.

On a PPS profile the operating screen shows the big live measurements, with the target voltage and current located under each reading and a small cursor marker showing whether voltage or current is being adjusted. The cursor is doing the job that a separate label would do on a bigger screen, and it is a neat solution to a space problem.

The energy screen is opened by holding the right button and shows power, live voltage and current, the elapsed time, and the watt-hours and amp-hours. The energy counter accumulates only while the output is on, which is the correct behaviour for a measurement of delivered energy.

The menu has two settings worth describing in full, because they are where the device's cleverness is.

Restore profile, when enabled, saves the last profile plus its voltage and current, and on boot restores them and jumps straight to the operating screen. When you switch to another charger, PocketPD defaults to the profile picker if the voltage and current fall outside the last profile's range. That fallback is the detail that makes the feature safe rather than annoying: restoring a 20 volt setting onto a charger that only does 5 volts would be a problem, so the device checks the range first.

Voltage comp is the cable compensation setting described earlier, and the manual gives the operating conditions explicitly: it watches the load-side voltage, raises the PPS request in 20 mV steps up to 500 mV, and only runs while the output is on and a PPS profile is active.

For a charger with no USB-PD profiles at all, PocketPD shows `Non-PD Source` and then activates Passthrough Mode on its own after a few seconds, metering the voltage and current flowing through to the load.

## The build system and the hardware revisions

The repository layout is a C++ embedded project with a PlatformIO build, and the Makefile at the root is where the structure becomes clear.

```makefile
build-v2:
	pio run -e HW1_3_V2
	$(call copy_uf2,HW1_3_V2,$(FIRMWARE_VERSION))

build-hw1_0:
	pio run -e HW1_0_V2
	$(call copy_uf2,HW1_0_V2,$(FIRMWARE_VERSION))

build-hw1_1:
	pio run -e HW1_1_V2
	$(call copy_uf2,HW1_1_V2,$(FIRMWARE_VERSION))

build-hw1_3:
	pio run -e HW1_3_V2
	$(call copy_uf2,HW1_3_V2,$(FIRMWARE_VERSION))

build-all: build-hw1_0 build-hw1_1 build-hw1_3
```

So there is a PlatformIO environment per hardware revision, named with the revision and a `_V2` suffix for the firmware generation, and a make target for each. The `build-v2` target is the current revision, HW1.3, which matches the note that v2 is a rewrite of the original monolithic firmware.

The naming scheme explains the suffix logic. The `copy_uf2` macro takes the environment name and the version, strips `_V2` for the distribution label, and copies the built UF2 file into a `dist/` directory with a name like `PocketPD_HW1_3-v2.3.0.uf2`. So the artefact carries the hardware revision and the firmware version, which is exactly what you need when several revisions are in circulation and the wrong firmware is worse than none.

The version number itself is read out of the PlatformIO configuration rather than being written twice. The Makefile extracts `firmware_version` from the `[common]` section of `platformio.ini` with an awk expression, and the comment describes it as the single source of truth shared with the build environments. That is a small piece of build hygiene worth copying, because a firmware version that exists in two places eventually stops matching.

The test targets are equally simple:

```makefile
test: test-root test-tempo

test-root:
	pio test -e native

test-tempo:
	pio test -e native -d lib/tempo
```

Two separate test runs, one for the project and one for the `tempo` library, and the `native` environment means the tests run on the host rather than on the hardware. The `native` suffix in PlatformIO is the convention for exactly this.

The `tempo` library is what the v2 firmware is built on, described in the README as a small cooperative scheduler and typed event bus built for this project. The tests being split out for it is a sign that it is a separable component with its own contract, and the `benchmarks/` directory at the root suggests its behaviour is measured as well as tested.

## Conclusion

Adopt PocketPD if you already have the hardware and want a supply you control, since the firmware is fully open and the board designs are published separately. Do not expect a finished product, since the first hardware revision was abandoned because of difficulty during mass production, and check first which board revision you have, because the Makefile builds separate firmware images for HW1.0, HW1.1 and HW1.3 and the compatibility list in the README says which revisions the current firmware supports.

## FAQ

### What is PocketPD?

It is open source firmware that turns any PPS-capable USB-C charger into a pocket-sized bench power supply, with controls from a rotary encoder and two buttons and an OLED showing live voltage, current, power and energy readings. It targets the RP2040 with the Arduino-Pico framework, is written in C++, and is MIT licensed.

### What can PocketPD do with a PPS charger?

It lets you set voltage in 20 mV steps and current in 50 mA steps, with a knob push cycling the step size between coarse, medium and fine. It also supports cable compensation, which raises the PPS request to hold your set voltage at the load rather than at the terminals, and input locking, which freezes the controls when both buttons are held.

### How do the PocketPD controls work?

There are three controls, a rotary encoder knob, a left button and a right button, and both short-press and long-press are supported. The actions are context aware: on the operating screen the knob adjusts the value being edited, tapping it cycles the step size, the left button switches between volts and amps, the right button toggles the output and holding it opens the energy screen, and holding both locks the screen. In the menus the knob instead navigates.

### What happens with a charger that has no PPS profile?

It still works as a meter. A charger with no PPS profile has nothing to adjust, so the knob and the left button's tap do nothing on the operating screen, and only the rated voltage and current is shown. A charger with no USB-PD profiles at all shows Non-PD Source and activates Passthrough Mode on its own after a few seconds, metering the voltage and current flowing to the load.

### How do I build the PocketPD firmware?

The Makefile drives PlatformIO with one environment per hardware revision, so `make build-v2` builds the HW1.3 environment and copies the UF2 into a dist directory, and `make build-all` builds HW1.0, HW1.1 and HW1.3. The firmware version is read from the common section of platformio.ini so it exists in one place, and `make test` runs the host tests for both the project and the tempo library.

### Is PocketPD still being developed?

The repository is not archived and the last push was on 2026-08-05. Releases v2.3.0, v2.2.0 and v2.1.0 came in July, June and May 2026, and version 2 is a rewrite of the original monolithic firmware that runs on tempo, a small cooperative scheduler and typed event bus built for the project. The hardware designs are published in a separate PocketPD_HW repository and the project also has a Hackaday page.

## Sources

- [CentyLab/PocketPD on GitHub](https://github.com/CentyLab/PocketPD)
- [Issues](https://github.com/CentyLab/PocketPD/issues)
- [License: MIT](https://github.com/CentyLab/PocketPD/blob/main/LICENSE)
- [README](https://github.com/CentyLab/PocketPD/blob/main/README.md)
- [Releases](https://github.com/CentyLab/PocketPD/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/centylab-pocketpd
