
Quack core
HeyPCB/quack-core
Brain board for the Open Duck Mini: Pi Zero 2W carrier, 14-servo STS bus, fused 2S power path in stitched copper zones (15-18 A battery side), USB-C charging with balancing, IMU.

Iris Brainstem: power and servo hub of the Iris robot head. 9 V USB-C PD in, 6 V / 5 A servo rail in stitched copper zones (measured), 5 V rail, half-duplex servo bus with ten ports, speaker amp. 4-layer KiCad 10 board, DRC-clean, fab-ready.
Iris brainstem is an open-source printed circuit board by HeyPCB, from the HeyPCB/iris-brainstem repository on GitHub, published under the CERN-OHL-S-2.0 licence. It is a 4-layer board of 64 × 80 mm with 97 parts on 59 nets, routed with 770 tracks and 208 vias.
It is built around the SN74LVC1G125DBVR-TP, SN74LVC1G126DBVR-TP and CH224K, with the INA226AIDGSR, MAX98357AETE+T and TPS56339DDC among its other parts. Its parts include 28 capacitors, 22 resistors, 15 connectors, 9 ICs and 6 diodes. It belongs with the robots and motor control and audio and music boards of this library.
The power and servo hub in the base of Iris: 9 V USB-C PD in, a 6 V / 5 A servo rail laid in stitched copper zones, a 5 V rail, the half-duplex servo bus with ten ports, a speaker amp and a USB-C data port.
Part of Iris, the human-eyed robot head, HeyPCB's open robot boards. Designed end to end with the HeyPCB method on
KiCad 10 (headless pipeline, Freerouting 2.4.1); every number below is measured on the files in this repository.
Mentions of ./run.sh, docs/rules/, blocks/ or parts/ refer to the heypcb-kicad SDK that produced them.

| Layers | Outline | Parts | Nets | Connections routed | Vias | ERC errors | DRC errors / unconnected / parity |
|---|---|---|---|---|---|---|---|
| 4 | 64 x 80 mm, shaped | 97 | 48 | 230 -> 0 open | 208 | 0 | 0 / 0 / 0 |
Not fabricated, assembled or powered.
| KiCad project | kicad/ |
| Gerbers (unzipped and zipped), BOM, CPL, STEP, schematic PDF | fab/ |
| Mechanism CAD, fit check and system docs | Iris, the human-eyed robot head |
| Renders | top, bottom |
| Design process, every step as KiCad rendered it | media/design-process.mp4 |

Iris Brainstem is board B2 of Iris, a robot head with human-like eyes. It sits flat in the base of
the head and is the head's power, USB and servo hub. It takes 9 V from a USB-C PD charger, makes a
6.0 V / 5 A rail for the ten eye, lid and brow servos and a 5 V rail for the head controller (B1
Cortex), measures the input with an INA226, drives the servos' half-duplex serial bus and the
speaker, and passes a second USB-C port's data up to B1. It was designed with the HeyPCB method on
KiCad 10 (10.0.6), by heypcb-kicad's headless pipeline with Freerouting 2.4.1, from the brief in
board.json and section 4.2 of the Iris design spec v0.1 (not published; its binding interconnect and mounting
contracts are in the Iris system docs).
This board has not been fabricated, assembled or powered, and no firmware for it has been written. Everything below is what KiCad, the pipeline and the copper scripts measured on the design files. Nothing here has been tested on hardware or in the head.
Iris has four boards (spec 4): B1 Cortex (ESP32-S3, camera, on the eye cradle), B2 Brainstem (this board, in the head's base), B3 Iris ring (two LED rings) and B4 Brow (forehead sensors). B2 is where power enters the head and where every servo plugs in:
flowchart LR
J1["J1 USB-C PWR"] -->|"VBUS_PD 9 V"| D1["D1 SMAJ15A"]
J1 -->|"CC, D+/D-"| U1["U1 CH224K<br/>CFG = 9 V"]
U1 -->|PG| LED["D6 PD OK"]
J1 -->|VBUS_PD| F1["F1 5 A"] --> R1["R1 10 mOhm"]
R1 -->|VIN| C3["C3 470 uF"]
R1 -.->|Kelvin| U2["U2 INA226 0x40"]
R1 -->|VIN| U3["U3 TPS565208<br/>6V0 5 A"]
R1 -->|VIN| U4["U4 TPS56339<br/>5V2 3 A"]
U3 -->|6V0_SERVO| PORTS["J10-J19 servo ports<br/>C1, C2 470 uF"]
U4 -->|5V2| D2["D2 SS34"] --> SYS(("5V_SYS"))
J2["J2 USB-C DATA"] -->|VBUS_DATA| D3["D3 SS34"] --> SYS
J2 -->|"D+/D-"| U5["U5 USBLC6"] --> H1["J5 H1 SH-10 to B1"]
SYS --> H1
SYS --> U6["U6 AP2112K 3V3_B2"]
SYS --> U9["U9 MAX98357A"] --> J7["J7 SPK"]
H1 -->|"BUS_TX / BUS_RX"| BUS["U7, U8, Q1<br/>half-duplex driver"] -->|BUS_DATA| PORTS
H1 -->|SERVO_EN| U3
H2["J6 H2 SH-7 to B1"] -->|I2C| U2
U2 -->|"ALERT = nINT"| H2
H2 -->|I2S| U9J1 VBUS_PD, 9 V ─┬─ D1 SMAJ15A to GND
└─ F1 5 A ─ R1 10 mOhm (INA226) ─ VIN ─┬─ C3 470 uF
├─ U3 TPS565208 ─ 6V0_SERVO ─ C1, C2 470 uF ─ J10-J19 pin 2
└─ U4 TPS56339 ─ 5V2 ─ D2 SS34 ─┐
J2 VBUS_DATA, 5 V ─ D3 SS34 ────────────────────────────────────────────────────────────┴─ 5V_SYS
5V_SYS ─┬─ H1 pins 1-2 (to B1)
├─ FB1 ─ U9 MAX98357A ─ J7 speaker
└─ U6 AP2112K ─ 3V3_B2The input enters at the rear left (J1), and F1, R1 and C3 stand in one column above it. The servo buck sits in the middle of the board, with its output node (L1, three 22 uF and C1) on the left, and the ten ports run down both side edges. The 5V2 buck and the two diodes are at the rear right, beside J2.
Load figures (spec 6, all estimates, none measured): VIN 0.68 A typical, about 4.3 A for milliseconds (39 W); 6V0_SERVO 0.58 A typical, a 7-servo burst of 4.6 A for milliseconds, 9 A if every servo stalls (beyond the buck's 5 A by design: firmware must cut torque); 5V_SYS 0.41 A typical, 1.56 A peak. A 27 W (9 V, 3 A) PD charger is the spec's supply.
Net classes (from the brief; a class with a current is never narrowed by the routing ladder): PDIN 0.6 mm (VBUS_PD, VIN_F, VIN; 0.6 mm is the receptacle's VBUS pads and the bucks' VIN pins), SERVO 0.8 mm with 0.8 / 0.4 mm vias (6V0_SERVO), SWNODE 0.6 mm (the two switch nodes), RAIL5V 0.6 mm (5V2, 5V_SYS), USBVBUS 0.6 mm (VBUS_DATA). The tracks only connect the path. The current is carried by the zones below.
After routing reaches 0 open, the pour stage lays the plan pours (GND on F.Cu, B.Cu and In1,
6V0_SERVO on In2) and then the brief's board.zones: each a named net's copper over a region on
chosen layers, above the plan pours, with every pad joined solid, and where the zone has a
stitch pitch, its own 0.6 / 0.3 mm via lattice. Board coordinates are mm from the outline's
top-left corner (y = 0 is the front edge). Every reason is also in board.json.
| Zone | Net | Layers | Region | Priority | Vias placed |
|---|---|---|---|---|---|
vbus_pd | VBUS_PD | F.Cu, B.Cu | J1's VBUS pads, D1's cathode, F1's input pad (x 9.6-21.6, y 64.4-71.7) | 1 | 20 at 1.2 mm |
vin_f | VIN_F | F.Cu | F1's output pad to R1, and the INA226's IN+ resistor (x 14.6-19.7, y 57.6-62.7) | 2 | - |
vin_col | VIN | F.Cu, B.Cu | R1's VIN pad, C3's + pad, the INA226's IN- / VBUS taps (polygon in x 5.4-19.7, y 51.6-63.4) | 3 | 27 at 1.2 mm |
vin_band | VIN | B.Cu | from the input column to both buck inputs (x 9.6-44.8, y 44.9-57.4) | 2 | - |
vin_u3, vin_u4 | VIN | F.Cu, B.Cu | each buck's VIN pin and input capacitors | 10 | 4 and 5 at 1.2 mm |
v6_b | 6V0_SERVO | B.Cu | a U: the left bank strip, a bar along the front (y 7.3-12.5), the right bank strip | 5 | - |
v6_node | 6V0_SERVO | F.Cu, B.Cu | L1's output pad, the three 22 uF and C1 (x 14.6-23.0, y 31.6-44.7) | 6 | 8 at 1.2 mm |
v6_bank_l, v6_bank_r, v6_c2 | 6V0_SERVO | F.Cu | the V pins of each bank (x 4.6-7.45 and 56.55-59.4, y 12.5-57.0) and C2 | 7, 8 | - |
gnd_out6, gnd_in6, gnd_in5 | GND | F.Cu | the GND sides of the servo buck's output and input capacitors and of the 5V2 buck's input | 9 | 12, 5 and 0 at 1.2 mm |
gnd_front, gnd_mid, gnd_rear | GND | F.Cu, B.Cu | the front strip, the middle and the rear right, where the plan pour would otherwise have no vias | 0 | 16, 21 and 51 at 2.4 mm |
v5_spine | 5V_SYS | B.Cu | from D2 / D3 at the rear, up the right of the middle (x 45.4-50.8) to H1 | 12 | - |
v5_front, v5_link_* | 5V_SYS | F.Cu (+ B.Cu) | H1's pins 1-2, and the three places the spine meets F.Cu (D2, D3, H1) | 12, 13 | 3, 5 and 3 at 1.2 mm |
sw_6v0, sw_5v2 | SW_6V0, SW_5V2 | F.Cu | the gap between each buck's SW pin and its inductor | 11 | - |
v5v2_out | 5V2 | F.Cu | L2's output pad, the two 22 uF and D2's anode (polygon in x 30.4-36.6, y 51.6-60.4), left of VIN's F.Cu track to U4 | 14 | - |
B.Cu is kept free of signal tracks under these zones by seven board.keepouts rectangles
(bcu_*), and In2 is kept free of tracks where the VBUS_PD, VIN and the servo buck's via fields
need room (in2_*): a stitch via must clear other nets' tracks on every layer. gnd_in5 found no
via site (U4's GND pins reach In1 through the plan's own vias). Any GND zone stops the plan's GND
stitcher, so the plan's stitching count is 0 and the GND zones stitch themselves. The silkscreen
then displaced 25 GND stitching vias under its text, which leaves 208 vias on the board (read
off the board: 206 of 0.6 / 0.3 mm and 2 of 0.8 / 0.4 mm; 53 of them are routing vias).
copper.py (KiCad's Python) lists every track, via and pour of each power net on the final board
and exports the copper (tracks, pads, plan pours and zones) as polygons. copper_cut.py (any
Python with numpy and scipy) rasterises that copper on a 0.1 mm grid and finds, for each link of
the path, the narrowest cross-section the link's whole current must pass: a max-flow / min-cut
from the link's source pads to its sink pads, over every layer, with tracks, zones and via barrels
together, in parallel. Outer copper is taken as 35 um, inner as 17.5 um (JLCPCB's standard 4-layer
build), via plating as 25 um. Each cut is rated with heypcb_kicad.route.ipc2221_amps (IPC-2221,
I = k dT^0.44 A^0.725), per layer, summed. Each link is cut a second time with the copper within
1 mm of its pads counted as the pads ("beyond the pads"): that rates the board's own copper between
the parts, apart from the parts' fixed lands. Both scripts are copies of quack_core's, adapted.
| Link | From, to | Narrowest cross-section (35 um equivalent) | 10 C rise | 20 C rise | Beyond the pads, 10 C / 20 C |
|---|---|---|---|---|---|
| VBUS_PD | J1 VBUS pads (A4, A9, B4, B9) to F1.1 | 1.15 mm of F.Cu, at the receptacle's VBUS pads | 2.6 A | 3.6 A | 9.0 A / 12.2 A (6.23 mm) |
| VIN_F | F1.2 to R1.1 | 4.24 mm of F.Cu | 6.8 A | 9.2 A | pads adjacent |
| VIN, both bucks | R1.2 to U3 and U4 VIN pins and their input capacitors | 5.09 mm of F.Cu | 7.8 A | 10.6 A | 9.3 A / 12.6 A (In2 0.25, barrels 6.06) |
| VIN, servo buck | R1.2 to U3.3, C7.1, C8.1 | 3.08 mm: In2 0.39, 4 via barrels 2.69 | 5.5 A | 7.5 A | 5.5 A / 7.5 A |
| SW_6V0 | U3.2 to L1.1 | 0.80 mm of F.Cu: U3's SW pin | 2.0 A | 2.8 A | pads adjacent |
| 6V0_SERVO, all ports | L1.2 to J10-J19 pin 2 | 6.09 mm: F.Cu 0.70, 8 via barrels 5.39 | 10.0 A | 13.5 A | 10.0 A / 13.5 A |
| 6V0_SERVO, each bank | L1.2 (with C11-C13, C1) to J10-J14 or J15-J19 pin 2 | 6.09 mm, the same section | 10.0 A | 13.5 A | 10.0 A / 13.5 A |
| 6V0_SERVO, bank to bank | J10-J14 pin 2 to J15-J19 pin 2 | 7.61 mm: In2 2.82, B.Cu 4.78 | 10.0 A | 13.5 A | 13.4 A / 18.2 A |
| GND, ports to servo buck | J10-J19 pin 3 to U3.1, C11-C13 pin 2 | 8.63 mm of F.Cu | 11.4 A | 15.5 A | 13.3 A / 18.0 A |
| GND, servo buck to input | U3.1, C7.2, C8.2 to J1 GND pads | 2.97 mm of F.Cu | 5.3 A | 7.1 A | 13.4 A / 18.2 A (F.Cu 5.74, barrels 2.69) |
| 5V2 | L2.2 to D2.2 (anode) | 1.04 mm of F.Cu | 2.5 A | 3.3 A | 2.5 A / 3.3 A |
| 5V_SYS | D2.1, D3.1 (cathodes) to J5 pins 1-2 | 0.99 mm of F.Cu | 2.4 A | 3.2 A | 2.4 A / 3.2 A |
Read off the board (copper_cut.json, copper.json) after the full run with
media. "Pads adjacent" means the two terminals are within 2 mm of each other, so the link is the
pads' own gap.
What this says against spec 6. At a 10 C rise on 1 oz outer copper:
v6_node; past that
the current spreads over the B.Cu U, the In2 pour and the F.Cu bank strips. The GND return from
the ports to the buck's output capacitors rates 11.4 A.Nothing here is a measured temperature. Measure F1, R1, J1, U3, L1 and the port headers under the real servo load before trusting any of it. The routed widths of the rest of the power nets, read off the board: VBUS_DATA 0.6 mm (0.45 mm necks at pads, 2 vias), SW_5V2 0.6 mm plus its zone, VIN's routed tracks 0.6 mm.
Every connector follows spec 5 (binding). "Pin n" is pad n of the KiCad footprint. Both harness cables are double-ended, same direction (pin n to pin n), 28 AWG, 150 mm. The SH headers are side-entry with their mouths at the front edge; the board's header pin counts (10, 7, 2) all differ, so no cable fits a wrong header.
| Pin | Net | Direction | Level / type | Notes |
|---|---|---|---|---|
| 1 | 5V_SYS | B2 -> B1 | 4.85 V nominal (5V2 - SS34), <= 1.6 A total on pins 1-2 | source B2 |
| 2 | 5V_SYS | B2 -> B1 | as pin 1 | |
| 3 | GND | - | ||
| 4 | GND | - | ||
| 5 | USB_DN | both | USB 2.0 FS D-, 90 Ohm pair with 6 | ESD on B2 (U5); B1 GPIO19 |
| 6 | USB_DP | both | USB 2.0 FS D+ | B1 GPIO20 |
| 7 | GND | - | separates the USB pair from the UART | |
| 8 | BUS_TX | B1 -> B2 | 3.3 V UART, 1 Mbps, 8N1, idle high | B1 GPIO42 -> U7 A + Q1 base network (10 k pull-up on B2) |
| 9 | BUS_RX | B2 -> B1 | 3.3 V UART | U8 Y -> B1 GPIO44; 10 k pull-up on B2 |
| 10 | SERVO_EN | B1 -> B2 | 3.3 V CMOS, active high | -> U3 EN via 1 k; 100 k pull-down on B2 |
The board's nets carry the spec's names (USB_DN, USB_DP, BUS_TX and so on). The USB pair is routed as two plain signals, without an impedance class (USB full speed). The mounting tabs are grounded.
| Pin | Net | Direction | Level / type | Notes |
|---|---|---|---|---|
| 1 | GND | - | ||
| 2 | I2C_SDA | both | 3.3 V open drain, 400 kHz | pull-ups 2.2 k on B1 only (none on B2) |
| 3 | I2C_SCL | B1 -> | 3.3 V open drain | |
| 4 | nINT | B2 -> B1 | open drain, active low | INA226 ALERT; 10 k pull-up on B1 (GPIO3) |
| 5 | I2S_BCLK | B1 -> B2 | 3.3 V, 3.072 MHz (48 kHz x 64) | 33 Ohm series at B1; -> U9 BCLK |
| 6 | I2S_WS | B1 -> B2 | 3.3 V, 48 kHz | 33 Ohm series at B1; -> U9 LRCLK |
| 7 | I2S_AMP_SD | B1 -> B2 | 3.3 V I2S data | -> U9 DIN |
The mounting tabs are grounded.
Pin 1 OUTP (SPK_P, marked "+" on the silkscreen), pin 2 OUTN (SPK_N). A bridge-tied load: neither wire is ground. 4-8 Ohm, about 1 W speaker (spec 5). The mounting tabs are grounded.
| Pad | Net | Silkscreen | Notes |
|---|---|---|---|
| 1 | BUS_DATA | D | 3.3 V half-duplex, 1 Mbps; 10 k pull-up to 3V3_B2; ESD5Z5.0 at each bank |
| 2 | 6V0_SERVO | V | source B2 (U3); at most 1 A per port (stall) |
| 3 | GND | G |
Watch the numbering: Feetech numbers the servo's own plug "1 GND, 2 Vcc, 3 Signal"; Waveshare numbers the mating header "1 DATA, 2 VCC, 3 GND". The board follows Waveshare (pad 1 = DATA), as spec 5 binds, and prints D / V / G beside every port. Pad 1 (square) is the outboard pin in both banks.
Port to servo ID (binding for firmware, spec 5), printed beside each port:
| Port | J10 | J11 | J12 | J13 | J14 | J15 | J16 | J17 | J18 | J19 |
|---|---|---|---|---|---|---|---|---|---|---|
| Servo | ID 2 pan L | ID 5 upper lid L | ID 7 lower lid L | ID 9 brow L | ID 3 tilt | ID 1 pan R | ID 4 upper lid R | ID 6 lower lid R | ID 8 brow R | spare |
| Silk | J10 ID2 PAN L | J11 ID5 ULID L | J12 ID7 LLID L | J13 ID9 BROW L | J14 ID3 TILT | J15 ID1 PAN R | J16 ID4 ULID R | J17 ID6 LLID R | J18 ID8 BROW R | J19 SPARE |
| Pad | Net | Silkscreen | Board position (x, y) |
|---|---|---|---|
| TP1 | VIN | VIN | 12.80, 58.30 |
| TP2 | 6V0_SERVO | 6V0 | 21.55, 33.00 |
| TP3 | 5V2 | 5V2 | 28.00, 50.30 |
| TP4 | 5V_SYS | 5V | 40.90, 68.55 |
| TP5 | 3V3_B2 | 3V3 | 48.35, 62.35 |
| TP6 | BUS_DATA | BUS | 26.00, 17.10 |
| TP7 | SERVO_EN | EN | 29.40, 18.85 |
| TP8 | GND | GND | 22.60, 16.60 |
Board coordinates are mm from the outline's top-left corner, F face up; y = 0 is the front edge
(toward the face). The head frame H follows spec 4.2 (binding): F face at Z = -60.0, Y = 32 - x,
X = -30 - y. Read off the board with KiCad 10.0.6's pcbnew.
| Part | Board centre (x, y), rotation | H (X, Y) of the centre | Extent on the board | Faces |
|---|---|---|---|---|
| J1 USB-C PWR | (17.00, 76.30), 0 | (-106.30, +15.00) | body x 12.53-21.47, y 72.65-79.95 | rear: mouth at the rear edge (H X -110), facing -X |
| J2 USB-C DATA | (47.00, 76.30), 0 | (-106.30, -15.00) | body x 42.53-51.47, y 72.65-79.95 | rear, as J1 |
| J5 H1 SH-10 | (38.50, 3.40), 180 | (-33.40, -6.50) | courtyard x 31.56-45.44, y 0.08-6.72; pin 1 at (43.00, 5.40) | front: mouth toward the front edge, facing +X |
| J6 H2 SH-7 | (23.50, 3.40), 180 | (-33.40, +8.50) | courtyard x 18.06-28.94, y 0.08-6.72; pin 1 at (26.50, 5.40) | front, as J5 |
| J7 SPK SH-2 | (13.00, 3.40), 180 | (-33.40, +19.00) | courtyard x 10.06-15.94, y 0.08-6.72; pin 1 at (13.50, 5.40) | front, as J5 |
| J10-J14 (left bank) | pin 1 at x 3.50, y 16.50 / 26.00 / 35.50 / 45.00 / 54.50 | pin 1 at Y +28.50, X -46.50 / -56.00 / -65.50 / -75.00 / -84.50 | pins at x 3.5, 6.0, 8.5; courtyards x 0.50-11.50, 6.0 mm deep in y | up (+Z), vertical headers |
| J15-J19 (right bank) | pin 1 at x 60.50, y 15.20 / 24.70 / 34.20 / 43.70 / 53.20 | pin 1 at Y -28.50, X -45.20 / -54.70 / -64.20 / -73.70 / -83.20 | pins at x 60.5, 58.0, 55.5; courtyards x 52.50-63.50 | up (+Z) |
| C1, C2 (470 uF, 6.3 x 7.7 mm cans) | (16.00, 31.00), (48.00, 31.00) | (-61.00, +16.00), (-61.00, -16.00) | courtyards 7.2 x 9.5 mm | |
| C3 (470 uF can) | (7.00, 64.00) | (-94.00, +25.00) | courtyard x 3.41-10.59, y 59.25-68.75 | |
| L1, L2 (FXL0630, 7 x 6.6 mm) | (24.30, 41.00), (38.30, 53.50) | (-71.00, +7.70), (-83.50, -6.30) | courtyards about 9 x 7.2 mm |
Every part is on the F side. The tallest are the 5264 headers, the 470 uF cans and the
inductors; the spec allows 12 mm on F (Z -48). The through-hole tails of J10-J19 and the USB-C
receptacles' shell legs come through to the B side, where the spec allows 2 mm; their length below
the board was not checked. The pipeline's STEP (fab/iris_brainstem.step)
uses generated bodies, not vendor models, so take heights from the parts' drawings.
| Spec | On the board | Why |
|---|---|---|
| U5 USBLC6-2SC6 C2687116 (UMW) | C7519, STMicroelectronics' own USBLC6-2SC6 | The pinned table prefers ST's part over the clone; same pinout, same KiCad symbol |
| "PD OK" LED from 3V3_B2 through a resistor into PG | LED (D6) and 2.2 kOhm from the CH224K's own VDD into PG | With only J2 plugged in, 3V3_B2 is up while the CH224K is unpowered; an LED from 3V3_B2 into PG would back-feed the unpowered chip. From VDD it draws about 0.6 mA of the 5.7 mA the 1 kOhm VDD resistor supplies at 9 V |
| C1-C3 "470 uF 16 V polymer", C2977552 | the spec's own C2977552, which is RVT1C471M0607, a general-purpose aluminium electrolytic (185 mA ripple at 120 Hz, catalogue row) | Kept the spec's part number. TI's TPS565208 table assumes 20-68 uF of ceramics; the 940 uF of electrolytic bulk on 6V0 is outside it (see Check before ordering) |
| Layers "F / GND / 6V0 + 5V pours / B" | F.Cu / In1 GND / In2 signal + 6V0_SERVO pour / B.Cu power zones | The 5 V rails need little copper (1.6 A); B.Cu carries the 6V0_SERVO U, the VIN band and the 5V_SYS spine, with signal tracks kept off those zones, and In2 carries signals |
| Test pads VIN, 6V0, 5V2, 5V_SYS, 3V3_B2, BUS_DATA, SERVO_EN | the same plus GND (TP8) | A probe needs a ground next to the bus pads |
| (not specified) | SH header mounting tabs grounded; 10 Ohm / 100 nF INA226 input filter; 1 uF on J2's VBUS | Data sheet practice (INA226: 10 Ohm or less per line) |
Everything else follows spec 4.2's parts table and spec 5's contracts: the same reference
designators (U1-U9, D1-D5, C1-C3, F1, R1, J1, J2, J5-J7, J10-J19), the same parts and the same
pinouts. Part numbers came from the pinned table or from live jlcsearch lookups on 2026-10-03,
pinned in parts/lcsc_pinned.json with that date.
A full run with media on 2026-10-03 (./run.sh --board boards/iris_brainstem, KiCad 10.0.6,
Freerouting 2.4.1). Gate numbers are from report.json. Anything marked read
off the board was measured on kicad/iris_brainstem.kicad_pcb with pcbnew.
| Gate | Result |
|---|---|
| Composition | 97 parts, 48 nets (13 block instances of 12 new brainstem_* blocks) |
| Part binding | 85 of 97 parts bound to an LCSC number, 0 unsourced, 0 identity conflicts. The other 12 are not BOM parts: the four mounting holes and the eight test pads. 24 distinct Extended parts, about $72 in JLC loading fees |
ERC (kicad-cli sch erc --severity-all) | 0 errors, 1 warning (pin_to_pin: the MAX98357A's exposed pad, typed "unspecified" in KiCad's symbol, on GND) |
| Netlist round trip | identical, 48 nets |
| Routing, rung 1, fanout on | 230 -> 0 open by Freerouting alone, 28.3 s, 53 vias. This solve is kept |
| Routing, rung 1, fanout off | 0 open after the last-mile router closed one 3V3_B2 connection (4 vias), 89.8 s |
| Net classes | none narrowed (every power class carries a current) |
| Copper | 770 tracks, 2001.4 mm (F.Cu 1318.6, In2 581.2, B.Cu 101.5), 53 routing vias |
| Pours and zones (laid only after a measured 0 open) | Plan: GND on F.Cu, B.Cu and In1, 6V0_SERVO on In2. The 25 board.zones above them, with 180 zone vias (GND 105, VIN 36, VBUS_PD 20, 5V_SYS 11, 6V0_SERVO 8). 0 open after the pours and after stitching, 0 island-repair vias |
| Silkscreen | 55 words and marks placed (24 words, 30 port letters, the speaker's "+"), 39 designators seated and 34 hidden, the 6 back-side title lines placed as one block (offset 5.0, -3.0 mm from the brief's spot). The text displaced 25 GND stitching vias; 6 footprint silk strokes at or past the edge were dropped |
DRC (kicad-cli pcb drc --severity-all --schematic-parity) | fresh, 0 errors, 0 unconnected, 0 parity issues, 2 warnings (lib_footprint_mismatch on J1 and J2: the silk clip dropped 3 of each receptacle's 5 silk strokes at the rear edge, read off the board). One repair before the final check: J13 pin 3's starved thermal became a solid zone connection |
DFM (jlcpcb_4layer) | 0 errors, 1 warning: 330 stock-footprint silk strokes at 0.12 mm, which the fab prints at its 0.15 mm minimum |
| Fab gate | ready, no blockers. 4 copper gerbers and a gerber job with LayerNumber 4, 1.6 mm; drill, BOM, JLC CPL (9 rotations corrected), schematic PDF, STEP |
| 3D, renders, video | all ran: 63 3D frames, the renders (492.7 s, on a machine shared with other boards' runs) and the design-process video (225 stills; 151.4 s at 1920 x 1080 by ffprobe) |
Nothing on the board was edited by hand: every track came from Freerouting, every pour and stitching via from the pipeline.
Measured on the runs of 2026-10-03; each reason is also in board.json beside its key.
vin_col (stitched, F.Cu and B.Cu) placed 0 vias under the B.Cu VIN band until
the band went one priority below it; then 29 (27 after the last placement changes).v5v2_out zone, added on the same route, took it to
1.04 mm (2.5 A).silk.switches entry, because
silk.polarity would also print "-" beside the grounded mounting tabs.copper_cut.py sums duplicate graph edges in 64 bits. J1's A4 / B9 and A9 / B4 VBUS pads
overlap, and two infinite-capacity edges summed in 32 bits wrapped negative and read as a flow of
0. quack_core's copy has the same line.Each value is cited where it is used, in the block files' notes. Data sheets were read for values and are not stored in this repository.
The Iris Brainstem design files in this folder (board.json, copper.py, copper_cut.py, this
README) and the brainstem_* blocks are released under the CERN Open Hardware Licence Version 2 -
Strongly Reciprocal (CERN-OHL-S-2.0). KiCad's symbol, footprint and 3D libraries keep their own
licence (CC-BY-SA-4.0 with the KiCad library exception). Part numbers and stock figures are
catalogue facts.
board.json: the brief. Blocks, net classes, keep-outs, power zones, placement (with a reason per
lock), routing and silk settings.copper.py (KiCad's Python) and copper_cut.py (numpy and scipy): the copper measurement above.
They write build/iris_brainstem/copper.json, copper_geom.json and copper_cut.json.../../blocks/brainstem_*.json: the 12 blocks written for this board. Each block's notes give the
KiCad 10 symbol pinout it was wired from and the data sheet its values came from.../../parts/lcsc_pinned.json: the 7 parts and 3 resistor values this board added, each with its
2026-10-03 lookup.build/iris_brainstem/ (not committed): report.json, the KiCad
project, fab/ (gerbers, drill, BOM, JLC CPL, schematic PDF, STEP), the renders and the video.To rebuild, from the repository root:
./run.sh --board boards/iris_brainstem # the pipeline, with renders and video (5-15 min)
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 \
boards/iris_brainstem/copper.py # power copper -> build/iris_brainstem/copper*.json
python boards/iris_brainstem/copper_cut.py # a Python with numpy and scipy| Qty | Value | Footprint | References |
|---|---|---|---|
| 10 | SERVO | Connector_Molex:Molex_SPOX_5267-03A_1x03_P2.50mm_Vertical | J10, J11, J12, J13, J14, J15, J16, J17, J18, J19 |
| 9 | 100nF | Capacitor_SMD:C_0603_1608Metric | C5, C6, C9, C10, C16, C17, C24, C25, C27 |
| 7 | 10k | Resistor_SMD:R_0603_1608Metric | R3, R9, R14, R17, R18, R20, R21 |
| 6 | 10uF | Capacitor_SMD:C_0805_2012Metric | C7, C8, C14, C15, C26, C28 |
| 6 | 22uF | Capacitor_SMD:C_0805_2012Metric | C11, C12, C13, C18, C19, C20 |
| 4 | 1uF | Capacitor_SMD:C_0603_1608Metric | C4, C21, C22, C23 |
| 4 | M2 | MountingHole:MountingHole_2.2mm_M2 | H1, H2, H3, H4 |
| 3 | 10 | Resistor_SMD:R_1206_3216Metric | R5, R6, R7 |
| 3 | 470uF 16V | Capacitor_SMD:CP_Elec_6.3x7.7 | C1, C2, C3 |
| 2 | 1k | Resistor_SMD:R_0603_1608Metric | R2, R10 |
| 2 | 5.1k | Resistor_SMD:R_0603_1608Metric | R15, R16 |
| 2 | ESD5Z5.0 | Diode_SMD:D_SOD-523 | D4, D5 |
| 2 | SS34 | Diode_SMD:D_SMA | D2, D3 |
| 1 | 100k | Resistor_SMD:R_0603_1608Metric | R11 |
| 1 | 10m | Resistor_SMD:R_1206_3216Metric | R1 |
| 1 | 120R@100MHz | Inductor_SMD:L_0603_1608Metric | FB1 |
| 1 | 1M | Resistor_SMD:R_0603_1608Metric | R22 |
| 1 | 2.2k | Resistor_SMD:R_0603_1608Metric | R4 |
| 1 | 20k | Resistor_SMD:R_0603_1608Metric | R19 |
| 1 | 3.3uH | Inductor_SMD:L_Changjiang_FXL0630 | L1 |
| 1 | 33 | Resistor_SMD:R_0603_1608Metric | R12 |
| 1 | 3V3_B2 | TestPoint:TestPoint_Pad_D1.5mm | TP5 |
| 1 | 5.6uH | Inductor_SMD:L_Changjiang_FXL0630 | L2 |
| 1 | 54.9k | Resistor_SMD:R_0603_1608Metric | R13 |
| 1 | 5A | Fuse:Fuse_Littelfuse-NANO2-451_453 | F1 |
| 1 | 5V2 | TestPoint:TestPoint_Pad_D1.5mm | TP3 |
| 1 | 5V_SYS | TestPoint:TestPoint_Pad_D1.5mm | TP4 |
| 1 | 68k | Resistor_SMD:R_0603_1608Metric | R8 |
| 1 | 6V0 | TestPoint:TestPoint_Pad_D1.5mm | TP2 |
| 1 | 74LVC1G125 | Package_TO_SOT_SMD:SOT-23-5 | U8 |
| 1 | 74LVC1G126 | Package_TO_SOT_SMD:SOT-23-5 | U7 |
| 1 | AP2112K-3.3 | Package_TO_SOT_SMD:SOT-23-5 | U6 |
| 1 | BUS_DATA | TestPoint:TestPoint_Pad_D1.5mm | TP6 |
| 1 | CH224K | Package_SO:SSOP-10-1EP_3.9x4.9mm_P1mm_EP2.1x3.3mm | U1 |
| 1 | GND | TestPoint:TestPoint_Pad_D1.5mm | TP8 |
| 1 | H1 | Connector_JST:JST_SH_SM10B-SRSS-TB_1x10-1MP_P1.00mm_Horizontal | J5 |
| 1 | H2 | Connector_JST:JST_SH_SM07B-SRSS-TB_1x07-1MP_P1.00mm_Horizontal | J6 |
| 1 | INA226 | Package_SO:TSSOP-10_3x3mm_P0.5mm | U2 |
| 1 | MAX98357A | Package_DFN_QFN:TQFN-16-1EP_3x3mm_P0.5mm_EP1.23x1.23mm | U9 |
| 1 | MMBT3906 | Package_TO_SOT_SMD:SOT-23 | Q1 |
| 1 | Red (PD OK) | LED_SMD:LED_0603_1608Metric | D6 |
| 1 | SERVO_EN | TestPoint:TestPoint_Pad_D1.5mm | TP7 |
| 1 | SMAJ15A | Diode_SMD:D_SMA | D1 |
| 1 | SPK | Connector_JST:JST_SH_SM02B-SRSS-TB_1x02-1MP_P1.00mm_Horizontal | J7 |
| 1 | TPS56339 | Package_TO_SOT_SMD:SOT-23-6 | U4 |
| 1 | TPS565208 | Package_TO_SOT_SMD:SOT-23-6 | U3 |
| 1 | USB-C DATA | Connector_USB:USB_C_Receptacle_HRO_TYPE-C-31-M-12 | J2 |
| 1 | USB-C PWR | Connector_USB:USB_C_Receptacle_HRO_TYPE-C-31-M-12 | J1 |
| 1 | USBLC6-2SC6 | Package_TO_SOT_SMD:SOT-23-6 | U5 |
| 1 | VIN | TestPoint:TestPoint_Pad_D1.5mm | TP1 |

HeyPCB/quack-core
Brain board for the Open Duck Mini: Pi Zero 2W carrier, 14-servo STS bus, fused 2S power path in stitched copper zones (15-18 A battery side), USB-C charging with balancing, IMU.

HeyPCB/iris-cortex
Iris Cortex: head controller of the Iris robot head. ESP32-S3 (16 MB flash, 8 MB PSRAM), OV2640 eye-camera FPC, iris-ring LED drivers, harness hub.

2468shrm/M4_CAN_Feather_Carrier_v6
Sixth version of the M4 Feather CAN Express carrier board. Hopefully, "the last".


enkhbold470/ice-core
iCE40UP5K FPGA board with 8 MB PSRAM and three Pmods, programmed over USB-C by an RP2040. 6-layer KiCad 10 board.



It measures 64 × 80 mm and has 4 copper layers, 1.6 mm thick.
97 parts, built around the SN74LVC1G125DBVR-TP, SN74LVC1G126DBVR-TP, CH224K and INA226AIDGSR. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the HeyPCB/iris-brainstem repository on GitHub, at the commit this page was made from: the board is kicad/iris_brainstem.kicad_pcb and its schematic kicad/iris_brainstem.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the CERN-OHL-S-2.0 licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).