Skip to main content
Raspberry Pi HATs

Building a USB Power Delivery Trigger HAT

Overview

This tutorial will walk you through building a Raspberry Pi HAT (Hardware Attached on Top) that negotiates USB Power Delivery (PD) voltages from a USB-C power supply. The board uses a CH224K PD controller to request specific voltages (5V, 9V, 12V, 15V, or 20V) and routes the negotiated power through terminal blocks — perfect for powering motors, LED strips, or other high-power projects from a standard USB-C charger.

What is USB Power Delivery?

USB Power Delivery (USB PD) is a specification that allows USB-C devices to negotiate higher voltages and currents beyond the standard 5V. With USB PD, a device can request:

ProfileVoltageMax CurrentMax Power
PDO 15V3A15W
PDO 29V3A27W
PDO 312V3A36W
PDO 415V3A45W
PDO 520V5A100W

A PD trigger chip like the CH224K handles the negotiation automatically — you just configure which voltage you want via resistor strapping.

Understanding the Components

CH224K USB PD Controller

The CH224K is a low-cost USB PD sink controller that:

  • Supports PD 2.0 and PD 3.0 protocols
  • Negotiates voltages from 5V to 20V
  • Configures requested voltage via 3 CFG pins (resistor strapping)
  • Requires no firmware or programming
  • Available in ESSOP-10 or SOP-8 packages

Voltage Selection

The CH224K uses three configuration pins (CFG1, CFG2, CFG3) to select the output voltage:

Requested VoltageCFG1CFG2CFG3
5VFloatFloatFloat
9VFloatFloatGND
12VFloatGNDFloat
15VGNDGNDFloat
20VGNDFloatFloat

Filtering Capacitors

  • C1 (10µF): Input filter on VBUS — absorbs voltage spikes from the USB-C cable
  • C2 (22µF): Output filter — smooths the negotiated voltage for the load
  • C3 (100nF): Decoupling cap near the CH224K — filters high-frequency noise on the power rail

Status LED

A green LED with a 1kΩ current-limiting resistor provides visual confirmation that the negotiated voltage is present at the output.

Building the Circuit Step by Step

Step 1: Import the RaspberryPiHatBoard

First, we import the RaspberryPiHatBoard component from @tscircuit/common. This gives us a board with the correct HAT dimensions and 40-pin GPIO header.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
{/* Components go here */}
</RaspberryPiHatBoard>
)

Step 2: Add the CH224K PD Controller

The CH224K is the heart of the circuit. It communicates with the USB-C charger over the CC (Configuration Channel) lines and negotiates the requested voltage.

Schematic Circuit Preview

Step 3: Add Input Filtering

USB-C cables can carry switching noise and voltage transients. We add a 10µF capacitor on the VBUS input and a 100nF decoupling cap close to the CH224K.

Schematic Circuit Preview

Step 4: Configure Voltage Selection

To select 20V, we connect CFG1 to GND through a 0Ω resistor (jumper). Leaving CFG2 and CFG3 floating. You can change the voltage by modifying which CFG pins are connected to GND — see the voltage selection table above.

Schematic Circuit Preview

Step 5: Add Output Stage with Status LED

The output stage includes a 22µF filtering capacitor, terminal blocks for the load, and a green LED to indicate when power is negotiated and present.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
<chip
name="U1"
footprint="soic8"
pinLabels={{
pin1: ["CC1"],
pin2: ["CC2"],
pin3: ["CFG1"],
pin4: ["GND"],
pin5: ["CFG2"],
pin6: ["CFG3"],
pin7: ["VBUS"],
pin8: ["VOUT"],
}}
schPortArrangement={{
leftSide: { pins: ["CC1", "CC2", "CFG1", "GND"], direction: "top-to-bottom" },
rightSide: { pins: ["CFG2", "CFG3", "VBUS", "VOUT"], direction: "top-to-bottom" },
}}
pcbX={5}
pcbY={-8}
/>
<capacitor name="C2" capacitance="22uF" footprint="0805" pcbX={15} pcbY={-5} />
<chip name="LED1" footprint="0603" manufacturerPartNumber="Green LED" pcbX={15} pcbY={-12} />
<resistor name="R1" resistance="1k" footprint="0402" pcbX={10} pcbY={-12} />

<trace from=".U1 .VOUT" to=".C2 > .pin1" />
<trace from=".C2 > .pin2" to=".HAT1_chip .GND_5" />
<trace from=".U1 .VOUT" to=".R1 > .pin1" />
<trace from=".R1 > .pin2" to=".LED1 > .pin1" />
<trace from=".LED1 > .pin2" to=".HAT1_chip .GND_6" />
<trace from=".U1 .GND" to=".HAT1_chip .GND_3" />
</RaspberryPiHatBoard>
)
Schematic Circuit Preview

PCB Layout

The PCB layout positions the USB-C connector on the edge for easy cable access, the CH224K centrally, and the terminal block outputs on the opposite edge. Filtering capacitors are placed close to their respective ICs for optimal noise performance.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
<chip
name="U1"
footprint="soic8"
pinLabels={{
pin1: ["CC1"],
pin2: ["CC2"],
pin3: ["CFG1"],
pin4: ["GND"],
pin5: ["CFG2"],
pin6: ["CFG3"],
pin7: ["VBUS"],
pin8: ["VOUT"],
}}
schPortArrangement={{
leftSide: { pins: ["CC1", "CC2", "CFG1", "GND"], direction: "top-to-bottom" },
rightSide: { pins: ["CFG2", "CFG3", "VBUS", "VOUT"], direction: "top-to-bottom" },
}}
pcbX={5}
pcbY={-8}
/>
<chip name="J1" footprint="soic8" manufacturerPartNumber="USB-C Connector" pcbX={-15} pcbY={-8} />
<capacitor name="C1" capacitance="10uF" footprint="0805" pcbX={-5} pcbY={-5} />
<capacitor name="C2" capacitance="22uF" footprint="0805" pcbX={15} pcbY={-5} />
<capacitor name="C3" capacitance="100nF" footprint="0402" pcbX={5} pcbY={-3} />
<chip name="LED1" footprint="0603" manufacturerPartNumber="Green LED" pcbX={15} pcbY={-12} />
<resistor name="R1" resistance="1k" footprint="0402" pcbX={10} pcbY={-12} />
<resistor name="R2" resistance="0" footprint="0402" pcbX={0} pcbY={-12} />
<chip name="TB1" footprint="soic8" manufacturerPartNumber="Terminal Block" pcbX={20} pcbY={-8} />

<trace from=".J1 > .pin1" to=".U1 .VBUS" />
<trace from=".J1 > .pin3" to=".U1 .CC1" />
<trace from=".J1 > .pin4" to=".U1 .CC2" />
<trace from=".J1 > .pin1" to=".C1 > .pin1" />
<trace from=".C1 > .pin2" to=".HAT1_chip .GND_1" />
<trace from=".U1 .VBUS" to=".C3 > .pin1" />
<trace from=".C3 > .pin2" to=".HAT1_chip .GND_2" />
<trace from=".U1 .GND" to=".HAT1_chip .GND_3" />
<trace from=".U1 .CFG1" to=".R2 > .pin1" />
<trace from=".R2 > .pin2" to=".HAT1_chip .GND_4" />
<trace from=".U1 .VOUT" to=".C2 > .pin1" />
<trace from=".C2 > .pin2" to=".HAT1_chip .GND_5" />
<trace from=".U1 .VOUT" to=".TB1 > .pin1" />
<trace from=".HAT1_chip .GND_6" to=".TB1 > .pin2" />
<trace from=".U1 .VOUT" to=".R1 > .pin1" />
<trace from=".R1 > .pin2" to=".LED1 > .pin1" />
<trace from=".LED1 > .pin2" to=".HAT1_chip .GND_7" />
</RaspberryPiHatBoard>
)
PCB Circuit Preview

Bill of Materials

RefComponentPackageValueNotes
U1CH224KSOIC-8USB PD sink controller
J1USB-C Receptacle16-pin or 6-pin USB-C
C1Ceramic Capacitor080510µFVBUS input filter
C2Ceramic Capacitor080522µFOutput filter
C3Ceramic Capacitor0402100nFIC decoupling
R1Resistor04021kΩLED current limiter
R2Resistor (Jumper)0402Voltage select (CFG1→GND)
LED1LED0603GreenPower indicator
TB1Terminal Block5.08mm2-posOutput connector

Monitoring Voltage with Python

Once the HAT is assembled and attached to your Raspberry Pi, you can read the negotiated voltage using GPIO17 and an ADC, or simply monitor the status LED. Here's a simple script to detect whether power is present:

import RPi.GPIO as GPIO
import time

POWER_GOOD_PIN = 17

GPIO.setmode(GPIO.BCM)
GPIO.setup(POWER_GOOD_PIN, GPIO.IN)

try:
while True:
if GPIO.input(POWER_GOOD_PIN):
print("✅ USB PD voltage negotiated — power is available")
else:
print("❌ No USB PD power detected")
time.sleep(1)
except KeyboardInterrupt:
GPIO.cleanup()

For precise voltage measurement, you can add an I2C ADC (like the ADS1115) to measure the actual output voltage through a resistor divider.

Safety Considerations

warning

USB PD can deliver up to 100W (20V × 5A). Always ensure:

  • Capacitors are rated for the maximum negotiated voltage (25V+ rating recommended)
  • PCB traces are wide enough for the expected current (use 1oz+ copper, minimum 0.5mm trace width for power)
  • Add reverse polarity protection if connecting to sensitive loads
  • Test with a current-limited supply before connecting expensive equipment

Ordering the PCB

You can order this PCB by downloading the fabrication files and uploading them to JLCPCB or another PCB manufacturer. Follow the instructions from Ordering Prototypes.

Next Steps

  • Add an I2C EEPROM for automatic HAT configuration
  • Include a voltage divider + ADC for precise voltage readback
  • Add a MOSFET switch for programmable output enable/disable
  • Design a multi-voltage selector with DIP switches on the CFG pins
  • Add overcurrent protection with a resettable fuse (PTC)