Writing USBC psu post

This commit is contained in:
Tom 2024-09-09 18:12:37 +02:00
parent a2f0eb0ca1
commit cb06885ab7
6 changed files with 8522 additions and 5 deletions

View File

@ -1,11 +1,12 @@
---
title: USB-C Power Station
title: USB-C Power Book
layout: post
excerpt: One charging station to rule them all!
excerpt: An ongoing quest to fix a problem I don't have.
permalink: /projects/usbc_charging_station
assets: /assets/projects/usbc_power_supply
img:
src: /assets/projects/usbc_power_supply/thumbnail.svg
alt: A line rendered CAD model of a laser-cut, book shaped device with exposed internal parts. It wouldn't be obvious without reading the description but it's a USB-C power supply.
class: invertable
@ -26,9 +27,93 @@ head: |
<script src="/assets/js/outline-model-viewer/index.js" type="module"></script>
<script type="module" src="/assets/js/kicanvas.js"></script>
<script src="/assets/blog/micropython/micropython.min.mjs" type="module"></script>
<script src="/assets/blog/micropython/cm6.bundle.min.js"></script>
<script src="/assets/blog/micropython/simulator.js" type = "module"></script>
---
{% include mastodon_post.html post_id = "111813225328398667" %}
{% include mastodon_post.html post_id = "111816310882560850" %}
<!-- {% include mastodon_post.html post_id = "111813225328398667" %}
{% include mastodon_post.html post_id = "111816310882560850" %} -->
<kicanvas-embed src="https://raw.githubusercontent.com/TomHodson/pcbs/main/usb-c%20psu/usb-c%20psu.kicad_sch" controls="basic"> </kicanvas-embed>
I'm kinda fascinated by USB-C. It has it's issues but I can't help but love this magical omni-cable that holds the promise of hundreds of watts of power and gigagbits per second of bandwidth. It's reversible, you can negotiate the supply voltage (PD), send power in either direction, pipe PCIe or DisplayPort and talk to the cable itself.
USB PD lets you ask for different supply voltages, roughly you can ask for, the voltage is fixed and the amps and power column are the max you're allowed to pull for that profile.
| Power | Voltage | Current |
|-------|---------|---------|
| 15W | 5 V | 3A |
| 27W | 9 V | 3A |
| 45W | 15 V | 3A |
| 60W | 20 V | 3A |
| 100W* | 20V | 5A |
100W mode requires the cable to have a special E-marker that reports that it supports the extra current. Later revision of the standard have added higher voltages (EPR) and fully adjustable supply voltage (PPS) but I won't go into that here.
I'm going to be using a cheap 60W and 100W USB modules from AliExpress. These boards take 24V input and have a DC-DC converter and IC onboard to negotiate and generate the requested voltage. So the basic idea is to connect a bunch of these connect to a 24V power supply.
I had a look online to see what the maximum charging rate of some common devices are:
| Device | Max Charge Rate |
|----------------|--------------------|
| Framework | 180W |
| Some Macbooks | 140W |
| Most Laptops | 100W* |
| Beefy Battery | 60W |
| Steam Deck | 40W |
| iPhone | 27W |
| Airpods | 5W |
I'll be using 100W modules so let's ignore anything above that say the most I could reasonable want to charge at once would be two phones, two wireless headphones, a portable battery, a laptop and a steamdeck. That sums to about 300W total. I'm going to go for 3 100W modules and 5 60W modules for a theoretical maximum draw of 600W but I don't have enough devices to achieve that.
This project has been the subject of a ridiculous amount of scope creep. What follows is basically my notes on what I've done so far.
## Case Design
After initially thinking I would do some kind of charging tray type design I eventually decided to model the PSU into a book-like form factor so that it can hide on the bookshelf in our living room, nestled between real books. The cables will then snake out of the back and emerge from between the books. This keeps the cables nicely separated and hides the extra cable length well. I'll need to be careful about cooling though.
This is what I've come up with so far, it's lasercut from 3mm ply (but I need to switch to 4mm because 3mm is a bit flimsy)
<figure style="max-width: 250px;">
<img src="{{page.img.src}}">
</figure>
I've put a 240x240 pixel colour screen on the front to show metrics like total charge power, temperature and maybe daily energy use.
## Electronics
Because I am taking this way to far, I wanted to do per port enable/disable and current monitoring. To implement this I'm designing a PCB with 5 channels where each channel consists of this schematic.
<figure style="max-width: 350px;">
<img src="{{page.assets}}/channel_sch.png">
</figure>
There's an INA219 and a shunt resistor for current and voltage monitoring and a chunky MOSFET for enabling and disabling the channel.
TODO:
Check the power dissipated in the MOSFET when the gate is driven at 3.3V
Check the inrush current when the MOSFET switches on and off, could potentially limit this by using a larger gate resistor to turn the MOSFET on more slowly.
<figure class="two-wide">
<img src="{{page.assets}}/channel_board.png">
<img src="{{page.assets}}/channel_3d.png">
</figure>
## Software
In other posts I've described how I made this simulator the test out possible GUIs for this thing.
TODO: Add some knobs to the simulator so you can test different conditions such as overcurrent, overtemp, sleep, nightmode etc.
<usbc-power-supply-simulator disable-console disable-editor code="/assets/blog/micropython/demo.py"></usbc-power-supply-simulator>
<!-- <outline-model-viewer model = "{{page.model}}" camera='{"position":[5.148,4.038,8.952],"rotation":[-0.4169,0.4809,0.2021],"zoom":1248.587161014231,"target":[0.03319,0.06938,-0.01135]}'>
<img class="outline-model-poster no-wc" src = "{{page.img.src}}">
<p class="has-wc">Loading model...</p>
</outline-model-viewer> -->
<!-- <kicanvas-embed src="/assets/projects/usbc_power_supply/usb-c_psu.kicad_sch" controls="basic"> </kicanvas-embed> -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,326 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="100%"
height="100%"
viewBox="0 0 400 300"
version="1.1"
xml:space="preserve"
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"
id="svg12223"
sodipodi:docname="usbc.svg"
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs12227" /><sodipodi:namedview
id="namedview12225"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="0.78666667"
inkscape:cx="-36.864407"
inkscape:cy="150"
inkscape:window-width="1309"
inkscape:window-height="456"
inkscape:window-x="0"
inkscape:window-y="35"
inkscape:window-maximized="0"
inkscape:current-layer="svg12223" />
<g
id="g12454"
transform="translate(0,49.9999)"><g
transform="translate(-23.0032,50.0051)"
id="g12117">
<path
d="m 353.003,-0.005 c 27.596,0 50,22.404 50,50 0,27.595 -22.404,49.999 -50,50 h -260 c -27.596,0 -50,-22.404 -50,-50 0,-27.596 22.404,-50 50,-50 z"
style="fill:#b3b3b3;stroke:#000000;stroke-width:8px"
id="path12115" />
</g><g
transform="translate(-30.0033,12.5)"
id="g12121">
<path
d="m 100.003,52.5 h 260 c 19.318,0 35,15.683 35,35 0,19.317 -15.683,35 -35,35 0,0 -260,0 -260,0 -19.317,0 -35,-15.683 -35,-35 0,-19.317 15.683,-35 35,-35 z"
style="fill:#e6e6e6;stroke:#000000;stroke-width:2px"
id="path12119" />
</g><g
transform="matrix(9.36582,0,0,9.36582,-1496.02,-1136.58)"
id="g12171">
<g
transform="matrix(1.00002,0,0,0.976295,0.141729,11.9059)"
id="g12125">
<rect
x="193.537"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12123" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.128439,11.9059)"
id="g12129">
<rect
x="191.133"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12127" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.115154,11.9059)"
id="g12133">
<rect
x="188.73"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12131" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.101869,11.9059)"
id="g12137">
<rect
x="186.327"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12135" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0885845,11.9059)"
id="g12141">
<rect
x="183.924"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12139" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0752997,11.9059)"
id="g12145">
<rect
x="181.521"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12143" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0620094,11.9059)"
id="g12149">
<rect
x="179.117"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12147" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0487246,11.9059)"
id="g12153">
<rect
x="176.714"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12151" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0354399,11.9059)"
id="g12157">
<rect
x="174.311"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12155" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0221551,11.9059)"
id="g12161">
<rect
x="171.908"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12159" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0088703,11.9059)"
id="g12165">
<rect
x="169.505"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12163" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,-0.00441448,11.9059)"
id="g12169">
<rect
x="167.10201"
y="125.886"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12167" />
</g>
</g><g
transform="matrix(9.36582,0,0,9.36582,-1496.02,-1111.08)"
id="g12221">
<g
transform="matrix(1.00002,0,0,0.976295,0.141729,6.44282)"
id="g12175">
<rect
x="193.537"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12173" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.128439,6.44282)"
id="g12179">
<rect
x="191.133"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12177" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.115154,6.44282)"
id="g12183">
<rect
x="188.73"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12181" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.101869,6.44282)"
id="g12187">
<rect
x="186.327"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12185" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0885845,6.44282)"
id="g12191">
<rect
x="183.924"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12189" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0752997,6.44282)"
id="g12195">
<rect
x="181.521"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12193" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0620094,6.44282)"
id="g12199">
<rect
x="179.117"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12197" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0487246,6.44282)"
id="g12203">
<rect
x="176.714"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12201" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0354399,6.44282)"
id="g12207">
<rect
x="174.311"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12205" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0221551,6.44282)"
id="g12211">
<rect
x="171.908"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12209" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,0.0088703,6.44282)"
id="g12215">
<rect
x="169.505"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12213" />
</g>
<g
transform="matrix(1.00002,0,0,0.976295,-0.00441448,6.44282)"
id="g12219">
<rect
x="167.10201"
y="121.803"
width="1.388"
height="1.2029999"
style="fill:#fcee21;stroke:#000000;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4"
id="rect12217" />
</g>
</g></g>
</svg>

After

Width:  |  Height:  |  Size: 9.8 KiB