|
KiCad 9.0 |
|
|
Raspberry Pi Pico SDKRaspberry Pi
|
Tiny Programmable Power Supply (tinyPPS)
TinyPPS is a pocket-sized programmable power supply built on the USB Power Delivery (PD) standard and the USB Programmable Power Supply (PPS) feature. It transforms a standard USB-C PD charger into a flexible bench-style power source by negotiating selectable output voltages and current limits directly with the charger.
Key features:
- Support for fixed PDO, PPS and AVS profiles
- Operating voltage range: 3.3V to 31V
- Fine-grained voltage adjustment via PPS negotiation (100mV/Step)
- Output current up to 5A (charger and cable dependent)
- Programmable current limit (250mA/Step)
- User-switchable output
For a detailed look at the schematics, PCB design and firmware, visit the GitHub repository.
Idea
Everything started with buying a 15$ USB powered mini SMD hot plate that required a supply with the following capabilities: PD65W 20V 3.25A. By acquiring a 100W power supply I have found out something called PPS, beside regular voltage/current values, on the label.
PPS 3.3V-21.0V - 5.0A 100W max - tickled my brain. What is PPS? It turned out it is a neat USB-C feature. To be more precise, it is an advanced feature of the USB Power Delivery (USB PD) 3.0 standard that allows chargers to dynamically adjust voltage and current in real time. Unlike standard PD, which uses fixed voltage “steps” (e.g., 5V, 9V, 15V, 20V), PPS allows for fine-grained adjustments - typically in 20mV voltage increments and 50mA current steps.
Knowing this, I came up with the idea of using USB PPS to build a small “lab” power supply as a proof of concept. Before jumping in to realization, I explored existing solutions and stumbled upon PocketPD by Centylab. Although it’s a great product, I wanted to add my own twist and use the project as a learning experience by implementing my own solution.
Hardware
For this project I wanted to use a microcontroller family other than ESP32. Options were Raspberry Pico-series or STM32. Due to ease of use (mostly flashing) I have chosen the Pico - RP2040.
Since I am not really a hardware guy, the schematic is basically an amalgamation of a few reference designs - mostly RP2040, AP33772S and INA226, with an OLED, rotary encoder and some extra connectors added on top.
The Pico’s QFN package is already challenging to solder and the 0402 SMD components are the icing on the cake.
This is the finished PCB without the OLED attached:

Firmware
Firmware is organized in the following logical layers and modules:

Pico SDK
The firmware is written in C++ (C++20) using the Pico SDK, running directly on the hardware without RTOS.
Hardware Abstraction Layer (HAL)
HAL is created as a set of hardware independent interfaces for controlling microcontroller peripherals like: GPIO, timer and I2C. It provides APIs that other components can use without knowing hardware details. While this layer is not actually needed for this project, since it is running only on RP2040, the drivers for INA226, SSD1306, … can be re-used on other projects.
For example: the driver for SSD1306 OLED display is already picked up from one of my previous projects.
Pico HAL
This layer is on top of the generic HAL. It implements interfaces declared in the HAL using PicoSDK. Besides main.cpp, Pico HAL is the only place where Pico SDK is used.
Drivers
This layer defines modules for controlling peripherals attached to RP2040 via I2C bus or via input pins. Each peripheral is represented as a class, providing a public API for controlling it by user code.
By looking at the schematic, the following modules can be identified as requiring driver code:
ap33772s: Driver for the AP33772S USB Type-C PD3.1 sink controller.
ina226: Driver for the INA226 Ultra-Precise I2C Output Current, Voltage, and Power Monitor.
rotary_encoder: Driver for the rotary encoder. It uses a polling mechanism to read the encoder state. The rotary encoder driver detects multiple states, including rotary increment/decrement, short button press, long button press, and rotary movement while the button is pressed.
ssd1306: Driver for the OLED display. The driver performs a partial display update using page-level dirty tracking. The display driver does not refresh the entire screen on every update. Instead, it keeps track of which display pages have changed since the last refresh. This results in shorter I2C transfer times, improving performance and reducing the time the main loop is blocked.
Main
This layer is responsible for implementing the business logic, in this case, the power supply logic. This layer relies on STL library’s data structures and functions, simplifying the logic.
Main layer is divided into three sub-sections:
- TinyPPS: This is a module that ties all components together. It is organized as a simple state machine with the following states: init, menu and main.
- Utils: It contains helper classes, like configuration.
- Gui: This sub-section is used for gathering graphics related modules, from framework (Screen) to specific screens (LoadingScreen, MenuScreen and MainScreen).
User interface
Loading screen
During startup, the loading screen is shown with a logo and a loading ellipsis:

As soon as PDOs are read from the USB source or after a timeout, the number of available PDOs is printed out:

Menu screen
If more than one PDO is available, the menu screen is shown as a simple list from which the user can select the desired PDO:

User inputs:
- rotary encoder increment/decrement: Move up/down in the menu
- rotary encoder button press: select PDO and move to main state
Main screen
This is the screen that shows the power supply user interface. It enables control and monitoring of voltage, current, and output. Besides this, it shows the active PDO type (FIX, PPS or AVS) and temperature read from the NTC in the upper corners.
The actual output voltage/current values are periodically read from INA226 and displayed with bigger font while the target/limit referent values are displayed with regular font.
On the bottom are located three boxes marked as CV (constant voltage), CC (constant current) and EN (output enable) used as status bar.

User inputs:
- rotary encoder increment/decrement: Select target voltage or max current fields. Increment/Decrement target voltage or max current values.
- rotary encoder button press: If target voltage or current limit field is selected enter value editing mode.
- rotary encoder long button press: enable/disable output.
- rotary encoder double press: Go back to menu state/screen if there are more than one PDO available.
Key takeaways
- This little device turned out to be a great addition to my toolbox.
- Soldering small packages is much easier than it looks at first glance.
- During development, I discovered that the AP33772S and its older sibling, the AP33772, differ in their voltage and current step sizes. The older IC provides finer adjustments, which makes it better suited for a lab-style power supply.
- The short-circuit protection is not working properly with the back-to-back NMOS switch. The issue may be due to the 30ms debounce time of the AP33772S, which allows the current to rise faster than the IC can react, causing the USB source’s protection to trigger. This can be solved with an ideal diode IC equipped with short circuit protection.
- Inrush current handling is not implemented in this version and remains an area for future improvement.
Tiny Programmable Power Supply (tinyPPS)
*PCBWay community is a sharing platform. We are not responsible for any design issues and parameter issues (board thickness, surface finish, etc.) you choose.
Raspberry Pi 5 7 Inch Touch Screen IPS 1024x600 HD LCD HDMI-compatible Display for RPI 4B 3B+ OPI 5 AIDA64 PC Secondary Screen(Without Speaker)
BUY NOW- Comments(0)
- Likes(0)
- 0 USER VOTES
- YOUR VOTE 0.00 0.00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
More by Daniel Knezevic
-
ARPS-2 – Arduino-Compatible Robot Project Shield for Arduino UNO
423 0 0 -
A Compact Charging Breakout Board For Waveshare ESP32-C3
780 3 6 -
AI-driven LoRa & LLM-enabled Kiosk & Food Delivery System
757 2 0 -
-
-
-
ESP32-C3 BLE Keyboard - Battery Powered with USB-C Charging
968 0 1 -
-
mammoth-3D SLM Voron Toolhead – Manual Drill & Tap Edition
858 0 1 -
-
AEL-2011 Power Supply Module
1582 0 2







