TinyPPS

Key features:

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.

Huge thank you to PCBWay for providing me PCBs and SMD stencil for free. TinyPPS PCB & SMD stencil

PCBWay offers high-quality PCBs at affordable prices. The boards are ready to solder straight out of the box, with no leftover tabs that need to be sanded down. Ordering is super easy: just upload the Gerber files and select the desired parameters.

What I like most is their customer support. They are quick to review orders and don’t just point out issues - they provide detailed explanations on how to address them. Whether it is about a missing Gerber file or out of capabilies issue. At the end, the outcome is always positive.

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.

Schematic and PCB are designed in KiCAD:

TinyPPS schematic diagram

Open image in new tab for a better view

This is the finished PCB without the OLED attached:

Firmware

Firmware is organized in the following logical layers and modules: TinyPPS firmware organization

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:

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:

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:

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:

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:

Key takeaways

References

  1. Hardware design with RP2040
  2. AP33772S I2C USB PD Sink Controller EVB User Guide
  3. SSD1306
  4. INA226
  5. RobTillaart/INA226