Skip to main content
Raspberry Pi HATs

Building a USB Power Delivery Trigger HAT

Overview

This tutorial walks through a Raspberry Pi HAT that uses a USB-C Power Delivery trigger controller to request a fixed voltage from a USB-C charger. The HAT keeps the Raspberry Pi header available for control and status signals, then routes the negotiated output to screw terminals for powering motors, LED strips, test fixtures, or another downstream board.

Circuit Requirements

The trigger HAT needs to:

  • Accept power from a USB-C charger or power bank
  • Negotiate a fixed USB Power Delivery voltage
  • Expose the negotiated voltage on a clearly marked terminal block
  • Let the Raspberry Pi read a power-good signal
  • Add local input and output capacitors so load steps do not reset the trigger controller

This tutorial uses a CH224K-style trigger controller because it is small, inexpensive, and common on hobbyist PD trigger modules. The same layout approach works with similar fixed-voltage PD trigger ICs; always check the controller datasheet before fabricating.

Component Choices

ReferencePartPurpose
J1USB-C receptacleInput from a PD charger
U1CH224K-style PD triggerNegotiates the requested voltage
R1Voltage-select resistorSelects the requested PD profile
C1100 nF ceramic capacitorLocal high-frequency bypassing
C222 uF ceramic capacitorOutput bulk capacitance
D1, R2Green status LED and resistorShows power-good status
J22-pin terminal blockExposes VOUT and GND

Building the Circuit Step by Step

Step 1: Add the HAT and USB-C Connector

Start with the Raspberry Pi HAT board and place a USB-C connector on the edge of the board. Keep the USB-C connector close to the board edge so the cable can plug in without hitting the Raspberry Pi case.

Schematic Circuit Preview

Step 2: Add the PD Trigger Controller

The trigger controller watches CC1 and CC2, advertises the requested voltage profile, then exposes the negotiated charger voltage on VBUS. The PG pin is useful because it lets the Raspberry Pi detect when negotiation has completed.

Schematic Circuit Preview

Step 3: Select the Requested Voltage

Many PD trigger ICs use one or more configuration pins to select 5 V, 9 V, 12 V, 15 V, or 20 V. In this example, R1 pulls the VSEL pin to ground. Change this resistor network to match the table in your exact controller datasheet.

Target outputTypical use
5 VLogic, small LED strings, USB-powered boards
9 VSmall motors, audio modules, compact test loads
12 VFans, relays, light strips, instrumentation
15 VHigher-voltage analog rails or bench fixtures
20 VLaptop-style adapters and high-power loads
Schematic Circuit Preview

Step 4: Add Filtering and the Output Terminal

Place a 100 nF capacitor close to U1 and a larger ceramic capacitor near the terminal block. The terminal block should have clear silkscreen labels for VOUT and GND, especially if you plan to change the requested voltage later.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
<chip
name="J1"
footprint="usb_c_receptacle"
manufacturerPartNumber="USB-C Receptacle"
pinLabels={{
pin1: ["VBUS"],
pin2: ["GND"],
pin3: ["CC1"],
pin4: ["CC2"],
}}
pcbX={-18}
pcbY={0}
/>
<chip
name="U1"
footprint="sot23_6"
manufacturerPartNumber="CH224K USB PD trigger"
pinLabels={{
pin1: ["CC1"],
pin2: ["CC2"],
pin3: ["GND"],
pin4: ["VSEL"],
pin5: ["PG"],
pin6: ["VBUS"],
}}
pcbX={-4}
pcbY={0}
/>
<capacitor name="C1" capacitance="100nF" footprint="0402" pcbX={2} pcbY={-8} />
<capacitor name="C2" capacitance="22uF" footprint="1206" pcbX={8} pcbY={-6} />
<chip
name="J2"
footprint="terminalblock_1x02"
manufacturerPartNumber="Output terminal block"
pinLabels={{
pin1: ["VOUT"],
pin2: ["GND"],
}}
pcbX={24}
pcbY={0}
/>

<trace from=".J1 .VBUS" to=".U1 .VBUS" />
<trace from=".J1 .GND" to=".U1 .GND" />
<trace from=".U1 .VBUS" to=".C1 > .pin1" />
<trace from=".C1 > .pin2" to=".J1 .GND" />
<trace from=".U1 .VBUS" to=".C2 > .pin1" />
<trace from=".C2 > .pin2" to=".J1 .GND" />
<trace from=".U1 .VBUS" to=".J2 .VOUT" />
<trace from=".J1 .GND" to=".J2 .GND" />
</RaspberryPiHatBoard>
)
Schematic Circuit Preview

Step 5: Add Power-Good Status

Use the power-good pin as both a visual status indicator and a Raspberry Pi input. The example LED is wired to 3.3 V through a resistor and sinks through the PG pin, which matches open-drain power-good outputs on many trigger ICs.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
<chip
name="U1"
footprint="sot23_6"
manufacturerPartNumber="CH224K USB PD trigger"
pinLabels={{
pin1: ["CC1"],
pin2: ["CC2"],
pin3: ["GND"],
pin4: ["VSEL"],
pin5: ["PG"],
pin6: ["VBUS"],
}}
pcbX={-4}
pcbY={0}
/>
<resistor name="R2" resistance="2.2k" footprint="0402" pcbX={10} pcbY={5} />
<led name="D1" color="green" footprint="0603" pcbX={16} pcbY={5} />

<trace from=".HAT1_chip .V3_3_1" to=".R2 > .pin1" />
<trace from=".R2 > .pin2" to=".D1 > .pin1" />
<trace from=".D1 > .pin2" to=".U1 .PG" />
<trace from=".U1 .PG" to=".HAT1_chip .GPIO_23" />
</RaspberryPiHatBoard>
)
Schematic Circuit Preview

PCB Layout

Route the USB-C VBUS and output path as a short, wide trace. For higher-current loads, use a polygon pour or multiple traces in parallel and size the terminal block for the expected current. Keep the CC traces short and away from noisy switching loads.

import { RaspberryPiHatBoard } from "@tscircuit/common"

export default () => (
<RaspberryPiHatBoard name="HAT1">
<chip
name="J1"
footprint="usb_c_receptacle"
manufacturerPartNumber="USB-C Receptacle"
pinLabels={{
pin1: ["VBUS"],
pin2: ["GND"],
pin3: ["CC1"],
pin4: ["CC2"],
}}
pcbX={-18}
pcbY={0}
/>
<chip
name="U1"
footprint="sot23_6"
manufacturerPartNumber="CH224K USB PD trigger"
pinLabels={{
pin1: ["CC1"],
pin2: ["CC2"],
pin3: ["GND"],
pin4: ["VSEL"],
pin5: ["PG"],
pin6: ["VBUS"],
}}
pcbX={-4}
pcbY={0}
/>
<resistor name="R1" resistance="10k" footprint="0402" pcbX={-4} pcbY={-10} />
<capacitor name="C1" capacitance="100nF" footprint="0402" pcbX={2} pcbY={-8} />
<capacitor name="C2" capacitance="22uF" footprint="1206" pcbX={8} pcbY={-6} />
<resistor name="R2" resistance="2.2k" footprint="0402" pcbX={10} pcbY={5} />
<led name="D1" color="green" footprint="0603" pcbX={16} pcbY={5} />
<chip
name="J2"
footprint="terminalblock_1x02"
manufacturerPartNumber="Output terminal block"
pinLabels={{
pin1: ["VOUT"],
pin2: ["GND"],
}}
pcbX={24}
pcbY={0}
/>

<trace from=".J1 .VBUS" to=".U1 .VBUS" />
<trace from=".J1 .GND" to=".U1 .GND" />
<trace from=".J1 .CC1" to=".U1 .CC1" />
<trace from=".J1 .CC2" to=".U1 .CC2" />
<trace from=".U1 .VSEL" to=".R1 > .pin1" />
<trace from=".R1 > .pin2" to=".J1 .GND" />
<trace from=".U1 .VBUS" to=".C1 > .pin1" />
<trace from=".C1 > .pin2" to=".J1 .GND" />
<trace from=".U1 .VBUS" to=".C2 > .pin1" />
<trace from=".C2 > .pin2" to=".J1 .GND" />
<trace from=".U1 .VBUS" to=".J2 .VOUT" />
<trace from=".J1 .GND" to=".J2 .GND" />
<trace from=".HAT1_chip .V3_3_1" to=".R2 > .pin1" />
<trace from=".R2 > .pin2" to=".D1 > .pin1" />
<trace from=".D1 > .pin2" to=".U1 .PG" />
<trace from=".U1 .PG" to=".HAT1_chip .GPIO_23" />
</RaspberryPiHatBoard>
)
PCB Circuit Preview

Bring-Up Test

Before plugging the HAT into a Raspberry Pi, test it by itself:

  1. Set the voltage-select resistor network for the voltage you want.
  2. Connect a current-limited USB-C PD charger.
  3. Measure VOUT and GND at the terminal block.
  4. Confirm that the output voltage matches the expected PD profile.
  5. Attach a small load, such as a resistor or lamp, before connecting the real load.
  6. Check that the status LED changes state when the charger negotiates successfully.

After the standalone check passes, install the HAT and read the PG signal from Raspberry Pi GPIO 23:

from gpiozero import DigitalInputDevice
from signal import pause

pd_good = DigitalInputDevice(23, pull_up=True)

def ready():
print("USB PD output is ready")

def lost():
print("USB PD output was removed")

pd_good.when_activated = ready
pd_good.when_deactivated = lost

pause()

Safety Notes

  • Do not connect the PD output directly to the Raspberry Pi 5 V rail unless you have checked back-powering requirements for your exact Pi model.
  • Label the selected voltage on the silkscreen or with a removable sticker.
  • Use a fuse or current-limited power switch if users will connect external loads.
  • Keep 20 V outputs away from low-voltage GPIO signals on connectors and test points.

Next Steps

  • Add a jumper block for selecting 5 V, 9 V, 12 V, 15 V, or 20 V without changing resistors
  • Add a resettable fuse between the PD output and the terminal block
  • Add an ADC divider so the Raspberry Pi can measure the negotiated voltage
  • Add an EEPROM if you want the board to identify itself as a full Raspberry Pi HAT