RITHESH LED Display
Public Unreviewedby Rithesh03
A 300 x 70 mm PCB that spells RITHESH with 107 WS2812B RGB LEDs, controlled over Wi-Fi.
1ed072d
12d ago
PCB layout notes
Plain-language record of the PCB layout, step by step. Screenshots are in layout-review/.
Status (2026-09-23): footprints, board outline and rules, four M3 holes, and the placement step are done: the ESP32, the USB-C connector and all 107 LEDs are placed. The other parts (power, protection, buttons, support parts) are not placed, and nothing is routed yet.
Step 1: Footprints
A footprint is the pattern of copper pads that a part is soldered onto.
ESP32-C3-MINI-1 (rithesh_fp:ESP32-C3-MINI-1)
- Source: Espressif's official KiCad footprint (espressif/kicad-libraries, CC-BY-SA 4.0 with the KiCad design exception, the same terms as KiCad's own libraries).
- One change: its silkscreen lines were 0.12 mm thick; JLCPCB needs at least 0.15 mm, so they were widened to 0.15 mm. Pads were not changed.
- Checked against the datasheet land pattern (Figure 11-1) by
tools/check_footprints.py:
| Measurement | Datasheet | Footprint |
|---|---|---|
| Module outline | 13.2 x 16.6 mm | 13.2 x 16.6 mm |
| Edge pads | 48 pads, 0.4 x 0.8 mm, 0.8 mm pitch, pointing inward | same |
| Left/right pad columns apart (centres) | 11.8 mm | 11.8 mm |
| Top/bottom pad rows apart | 9.8 mm | 9.8 mm |
| Corner pads | 4 x 0.7 x 0.7 mm, 11.9 x 9.9 mm apart | same |
| Centre ground pad (pin 49) | 9 squares 1.45 mm, block 5.4 mm, pin-1 corner chamfer 0.6 mm | same |
| Pin 1 | top-left, next to the antenna end | same |
| Antenna keep-out | antenna area must have no copper | 13.2 x 5.4 mm keep-out on all copper layers |
- Espressif's drawing also shows optional vias in the centre ground pad for cooling. They are not part of the footprint; we can add them during routing if wanted.
LED (rithesh_fp:LED_XL-5050RGBC-2812B)
- Source: drawn from the XL-5050RGBC-2812B datasheet's "Recommended Soldering Pattern".
- Pads: four 1.3 x 1.3 mm squares, 3.1 mm apart across and 1.8 mm apart down (pad centres at ±2.2 mm and ±1.55 mm from the middle).
- Pin order: 1 VDD (top-left), 2 data out (bottom-left), 3 GND (bottom-right), 4 data in (top-right), same as the schematic symbol.
- Silkscreen: body outline kept at least 0.22 mm away from the pads, 0.15 mm lines, and a dot next to pin 1 so the LED orientation can be checked by eye.
- Courtyard (the "keep other parts out" area): 6.2 x 5.6 mm. At our 7 mm LED spacing this leaves 0.8 mm between neighbours side by side and 1.4 mm between rows.
Can one footprint safely support both LED options? No, not confirmed.
See layout-review/led-pad-comparison.png.
| XL-5050RGBC-2812B | WS2812B-B/T | |
|---|---|---|
| Metal terminals fully on our pads? | Yes | Yes |
| How far the pad reaches past the terminal's outer end ("toe") | +0.15 mm, as its datasheet recommends | +0.15 mm, but its datasheet recommends +0.50 mm (1.5 x 0.9 mm pads) |
- The WS2812B would sit on the pads, but with a smaller solder fillet than its maker intends.
- JLCPCB's assembly terms say footprints must follow IPC-7351B medium/low density, and "If the component in the BOM does not match the footprint, this part will not be populated." Nothing published by JLCPCB approves a WS2812B on XL-sized pads.
- A larger "superset" pad covering both patterns was considered, but oversized pads can let a part float or rotate during soldering, and it would match neither manufacturer's pattern.
- Decision: the footprint is made for the XL LED only (the provisional selected part). Switching to the WS2812B-B/T would need its own footprint (a board change), on top of the 5.3 V issue already recorded in requirements.md.
Step 2: Board outline and JLCPCB design rules
Outline
| Item | Value | Why |
|---|---|---|
| Size | 300 x 70 mm | As decided in requirements.md. |
| Corners | 2 mm radius | Rounded corners are kinder to hands and less likely to chip. The overall 300 x 70 mm size is unchanged. |
| Layers | 2 copper layers (top + bottom) | Enough for this design; cheapest option. |
| Thickness | 1.6 mm FR4, 1 oz copper | JLCPCB's standard board. |
| Drawing origin | top-left board corner | Positions in later steps are measured from here. |
KiCad measures the outline as 300.05 x 70.05 mm because it includes the 0.05 mm drawing line; the actual cut line is 300 x 70 mm.
Design rules (checked by KiCad's DRC)
JLCPCB's published minimums for 2-layer boards are the absolute limits. We chose a margin above them so the board is easy to make at the standard price.
| Rule | Our value | JLCPCB minimum | Why our value |
|---|---|---|---|
| Track width (smallest allowed) | 0.15 mm | 0.10 mm | margin |
| Gap between copper (smallest allowed) | 0.15 mm | 0.10 mm | margin |
| Via (small plated hole joining the two layers) | 0.3 mm hole, 0.6 mm pad | 0.15 mm hole, 0.25 mm pad | JLCPCB: pad 0.1 mm (0.15 preferred) larger than the hole; holes under 0.25 mm cost extra |
| Hole to hole | 0.5 mm | 0.45 mm | margin |
| Hole to copper | 0.25 mm | 0.2 mm | margin |
| Copper to board edge | 0.5 mm | 0.2 mm | margin; protects tracks when the board is cut |
| Silkscreen line / text height | 0.15 mm / 1.0 mm | 0.15 mm / 1.0 mm | JLCPCB minimum |
| Solder mask bridge | 0.1 mm | 0.1 mm | JLCPCB minimum |
Track sizes by net (net classes)
| Class | Nets | Track width | Gap |
|---|---|---|---|
| Default | all signals | 0.25 mm | 0.2 mm |
| Power | VBUS, +5V, GND | 1.0 mm (plus wide copper areas later) | 0.25 mm |
| Supply3V3 | +3V3 | 0.5 mm | 0.2 mm |
| USB | USB_DP, USB_DN (and the ESP32 side) | 0.3 mm | 0.2 mm |
Checks run
| Check | Result |
|---|---|
tools/check_footprints.py (datasheet dimensions, JLCPCB pad gaps, silkscreen, courtyard) |
All passed. Also tested with a deliberately shifted LED pad, which it caught. |
| KiCad DRC on the board (outline + rules) | 0 violations, 0 unconnected, 0 footprint errors (drc-report.rpt) |
| DRC test with the new footprints placed (scratch copy) | 0 pad, clearance or courtyard problems. One silkscreen warning, see "Warnings" below. |
| DRC test with deliberate mistakes (scratch copy) | Caught all: overlapping LEDs, too-thin track, copper too close to the edge, clearance |
Schematic: check_netlist.py, check_pins.py, ERC |
All passed; ERC 0 errors, 0 warnings. Symbol pins now also match the ESP32 and LED footprint pads. |
Warnings and uncertainties
- LED reference labels will not fit. At 7 mm spacing, one LED's printed name (for example "LED3") lands 0.08 mm from the outline of the LED above it (DRC silkscreen warning). With 107 LEDs the labels would overlap everywhere.
- JLCPCB's 2.5 mm edge rule. JLCPCB's assembly terms require part bodies to be at least 2.5 mm from the board edge. The USB-C connector must sit at the edge, and Espressif wants the ESP32 antenna at (or past) the edge. This usually means JLCPCB adds removable "edge rails", which can add a small cost.
- Board height 70 mm = JLCPCB's minimum for its "Standard" assembly service (70 x 70 mm). We are exactly at the limit; do not make the board any shorter.
- IPC-7351B: the LED footprint follows the LED maker's recommended pattern; its IPC density class was not formally calculated. JLCPCB's DFM check at order time is the final confirmation.
- ESP32 thermal vias: optional per Espressif; not yet decided.
Decisions (approved 2026-09-23)
1. LED labels
- The 107 individual LED names (LED1 ... LED107) are hidden on the front silkscreen. They stay in KiCad and in the assembly (position) files JLCPCB uses, and on the assembly drawing layer.
- A clear "LED1" marker (1.5 mm text, 0.22 mm lines) sits in the top margin above the first LED, with an arrow pointing right, the direction the data chain starts along the top row of "R". It is 2.25 mm above the LED body and 1.75 mm from the board edge.
- More direction arrows (one per letter-to-letter step, in the empty columns between letters where there is room for 3 mm arrows) are added in the next step, once the chain path inside each letter is fixed. Arrows between individual LEDs would have to be under 0.9 mm long to fit between the pads, too small to read, so they are not used.
- Readable after assembly: all markers are printed outside the LED bodies and pads, so the 1.6 mm tall LEDs do not cover them; text is 1.5 mm (JLCPCB minimum 1.0 mm) and lines 0.22 mm (minimum 0.15 mm).
2. Four M3 mounting holes
| Item | Value |
|---|---|
| Hole | 3.2 mm, non-plated (no copper ring), KiCad standard M3 footprint |
| Positions (hole centres, from the board's top-left corner) | H1 (3.2, 3.2), H2 (296.8, 3.2), H3 (3.2, 66.8), H4 (296.8, 66.8) mm, i.e. 3.2 mm in from both edges at each corner (moved from 3.5 mm in the clearance review, see Step 3b) |
| Keep-out around each hole | 7 mm circle (3.5 mm radius) on both copper layers: no copper fill, tracks or vias. Fits an M3 washer (7 mm) or screw head (5.5-6 mm). |
| Hole edge to board edge | 1.6 mm (= board thickness) |
| Rounded corner | clear: the 2 mm corner curve ends 3.8 mm from the hole centre |
| Nearest LED (courtyard) | 0.61 mm outside the 3.5 mm keep-out (LED1) |
| Nearest LED copper pad | 1.12 mm outside a 7 mm washer, about 3 mm from the hole edge (JLCPCB needs 0.2 mm from a non-plated hole to copper) |
| ESP32 antenna area / USB-C | not near any hole (ESP32 at x = 40 mm, USB-C at x = 90 mm; nearest hole at x = 3.2 mm) |
3. JLCPCB edge rails
- JLCPCB recommends 5 mm process edges (rails) for SMT assembly, with 1 mm fiducials and 2 mm tooling holes on the rails. They are needed here because the USB-C connector and the ESP32 sit at the board edge (JLCPCB's terms ask for 2.5 mm from part bodies to the edge otherwise).
- Planned: one 5 mm rail on each long edge (top and bottom). The panel JLCPCB assembles is then 300 x 80 mm; the rails are snapped off afterwards, leaving the 300 x 70 mm board.
- JLCPCB's V-cut runs exactly along the board outline. Their V-cut rules: copper at least 0.4 mm from a V-cut edge (our rule is 0.5 mm, and the nearest USB-C copper is 1.8 mm from the edge); V-cut edge tolerance ±0.4 mm.
- Cost: JLCPCB does not publish a fixed rail price. The board area grows about 14 % (300 x 80 vs 300 x 70 mm), and panelised boards can have an engineering fee. The exact extra cost will be read from JLCPCB's quote page before manufacturing, and shown to you before any order.
- To confirm with JLCPCB at quote time: V-cuts are straight lines, but our corners are rounded (2 mm). JLCPCB may route the corners or use "mouse bite" tabs; mouse bites leave small bumps (a few tenths of a mm) that are sanded smooth. If that is a problem, square corners would give the cleanest V-cut.
Pre-placement checks (2026-09-23)
| Question | Answer |
|---|---|
| Does the ESP32 antenna keep-out cover every copper layer, with no parts or copper under it? | Yes. Espressif's footprint has a 13.2 x 5.4 mm rule area on all copper layers ("*.Cu") that forbids tracks, vias, pads, copper fill and footprints. When the ESP32 is placed, a board-level keep-out will also cover Espressif's 15 mm side clearance along the edge (planned area shown on the drawing layer). |
| Do the mounting-hole clearances meet JLCPCB's rules? | Yes. Nearest copper is about 3 mm from a hole (needs 0.2 mm); hole edge to board edge 1.6 mm (after Step 3b); hole is a standard 3.2 mm non-plated hole (JLCPCB minimum 0.5 mm, tolerance ±0.2 mm). |
| Can the USB-C connector sit at the edge without changing the board size? | Yes. Its body front (3.65 mm from its centre) is placed exactly on the bottom edge, so it does not stick out and the outline stays 300 x 70 mm. Its nearest copper is 1.8 mm inside the edge. |
| Will the LED1 marker and arrows stay readable after assembly? | Yes. They are printed outside LED bodies and pads, above JLCPCB's minimum sizes, and DRC found no silkscreen overlap. |
| Do the planned parts fit together? (scratch test: all 107 LEDs, ESP32, USB-C temporarily placed) | Yes: no courtyard overlaps, nothing in the antenna keep-out; ESP32 top edge 0.6 mm below the LED area. |
Scratch-test findings to handle when the parts are really placed:
- The ESP32 and USB-C footprints draw silkscreen right up to their front edge, which is the board edge. JLCPCB would clip it; those lines will be trimmed (cosmetic only).
- The USB-C footprint has shared pads (A1/B12 = GND, A4/B9 = VBUS); the scratch test showed them as "clearance" errors only because it had no nets. With the real nets they are the same net and correct.
Planning layer (User.Drawings, not manufactured)
The drawing shows grey outlines for: the 107 planned LED positions (they spell RITHESH), the LED courtyard envelope (x 6.9-293.1 mm, y 5.2-52.8 mm), the ESP32 module (centre x 40 mm, flush with the bottom edge), its antenna keep-out and 15 mm side clearance, the USB-C connector (centre x 90 mm, flush), and the two 5 mm JLCPCB rails. The ESP32 and USB-C positions are proposals for the next step.
Step 3: Placement of the ESP32, USB-C and 107 LEDs (2026-09-23)
Made by tools/place_parts.py (run after tools/make_board.py). Each placed part carries its
schematic reference, value, link to the schematic symbol and the schematic's nets on its pads,
the same as KiCad's "Update PCB from Schematic".
ESP32 and USB-C
| Part | Position (centre, from the board's top-left corner) | Notes |
|---|---|---|
| U4 ESP32-C3-MINI-1 | x = 40.0 mm, y = 61.7 mm, turned 180 deg | Antenna end exactly on the bottom edge. Its body is 1.1 mm from the LED above it (after Step 3b). |
| J1 USB-C | x = 90.0 mm, y = 66.35 mm, not turned | Opening faces the bottom edge; body front exactly on the edge, so nothing sticks out and the board stays 300 x 70 mm. |
- Antenna areas: the module's own keep-out (13.2 x 5.4 mm, all copper layers) plus two new board keep-outs of 14.8 mm on each side of it, along the bottom edge, on both copper layers. They forbid copper fill, tracks, vias, pads and parts. (They start at the module's 0.2 mm courtyard line, so they total 15 mm from the module body.)
- Edge silkscreen trimmed: the ESP32 and USB-C footprints' silkscreen lines that reached the
board edge were trimmed in the project library copies (ESP32: 3 removed, 3 shortened; USB-C:
1 removed, 2 shortened), so JLCPCB will not clip them. The USB-C footprint is now a project
copy (
rithesh_fp:USB_C_Receptacle_HRO_TYPE-C-31-M-12); the schematic points to it. - Power-net clearance: first lowered to 0.20 mm for the whole board because the USB-C connector's GND and VBUS pins are only 0.20 mm apart; in Step 3b this was replaced by a local rule (0.20 mm only inside the USB-C footprint, 0.25 mm everywhere else).
LED order and chain path
- LED1-LED107 follow the schematic exactly: R LED1-18, I 19-29, T 30-40, H 41-57, E 58-75, S 76-90, H 91-107. On the board, LED n's data-out and LED n+1's data-in share the same net for every n (checked).
- Inside each letter the chain snakes row by row (like reading a zig-zag): along one row, then back along the next.
- Letters alternate top-down and bottom-up, so each letter finishes right next to where the next letter starts:
| Letter | LEDs | Starts | Ends |
|---|---|---|---|
| R | 1-18 | top-left (LED1) | bottom-right |
| I | 19-29 | bottom row | top row |
| T | 30-40 | top-left | bottom of the stem |
| H | 41-57 | bottom-left | top-right |
| E | 58-75 | top-left | bottom-right |
| S | 76-90 | bottom-left | top-right |
| H | 91-107 | top-left | bottom-right (LED107, end of chain) |
- The red line in the review images (User.Comments layer, not manufactured) shows this path.
The per-LED list with positions and rotations is in
tools/led_chain.csv.
Rotated LEDs
- Each LED's data-in and data-out pads are on opposite corners. Each LED is turned (0, 90, 180 or 270 degrees) so its data-out pad faces the next LED and its data-in pad faces the previous one. This keeps the data tracks short in the routing step.
- Result: 0 deg x 26, 90 deg x 24, 180 deg x 42, 270 deg x 15. The LED lens is round and the body square, so this does not change how the letters look.
- 100 LEDs face both neighbours. 7 "turn" LEDs (LED5, LED15, LED21, LED27, LED34, LED62, LED65) are where the chain comes in and goes out on the same side (for example the end of a row in "R"). With opposite-corner pads no rotation can face both, so each uses the best of its four rotations; one data track will run a few millimetres around that LED.
LED1 marker and direction arrows
- "LED1" with a start arrow sits in the top margin above LED1 (from the previous step).
- 6 letter-to-letter arrows (6 mm long, 0.22 mm lines) are printed in the empty column between letters, at the row where the chain crosses: R to I (bottom), I to T (top), T to H (bottom), H to E (top), E to S (bottom), S to H (top). The nearest pad is 1.04 mm away.
- The 107 LED names are hidden on the silkscreen but kept in the board data.
Placement checks (tools/check_placement.py)
| Check | Result |
|---|---|
| Exactly 107 LEDs, LED1..LED107 | ✅ |
| Per letter R 18, I 11, T 11, H 17, E 18, S 15, H 17 | ✅ |
| Every LED on the 7 mm grid inside its letter's 5 x 7 pattern | ✅ |
| Chain order matches the schematic nets; LED107 data-out unconnected | ✅ |
| Every LED uses its best rotation (100 face both neighbours, 7 unavoidable turn LEDs) | ✅ |
| No LED overlaps another LED or a mounting-hole keep-out (closest: LED1, 0.61 mm outside after Step 3b) | ✅ |
| Nothing (copper, pad, via, part) in the antenna keep-out or its side clearance | ✅ |
| USB-C front exactly on the edge; no part within 6 mm beside or 12 mm behind it | ✅ |
| LED1 marker and arrows touch no part or board edge; text 1.5 mm, lines 0.22 mm | ✅ |
| KiCad DRC | ✅ 0 violations, 0 footprint errors |
- DRC also lists 359 "unconnected" pads. This is expected: no copper is routed yet and most parts are not placed. It is not a violation.
- The checker was tested on a scratch copy with one LED turned the wrong way and one LED pushed into its neighbour; it reported both.
Review images (layout-review/)
placement-full-board.png, placement-letter-1-R.png ... placement-letter-7-H.png,
placement-esp32-antenna.png, placement-usb-c.png, placement-led1-corner.png.
Colours: orange = copper pads (the mounting holes also show as orange dots: they are holes,
not copper), blue = printed silkscreen, red = data-chain path and screw-head outlines
(drawings only), grey = board outline, rails and notes.
Step 3b: Clearance review (2026-09-23)
Only the changes needed for the four review questions were made. Letters, the 7 mm grid, the chain order and the ESP32 / USB-C x positions are unchanged.
What changed
| Change | Before | After | Why |
|---|---|---|---|
| Mounting-hole centres | 3.5 mm in from each edge | 3.2 mm in from each edge | More room between the screw/washer and LED1 |
| Whole LED grid (all 107 LEDs, marker and arrows) | top row at y = 8.0 mm | y = 7.8 mm (moved up 0.2 mm, same 7 mm pitch) | More room between the ESP32 and the LED above it |
| Power-net clearance | 0.20 mm for the whole board | 0.25 mm everywhere, 0.20 mm only inside the USB-C footprint | Local rule instead of a board-wide change |
1. Mounting holes and LED1
| Measurement | Before | Now |
|---|---|---|
| Hole keep-out (7 mm circle) to LED1's courtyard | 0.30 mm | 0.61 mm |
| Edge of a 7 mm M3 washer to LED1's body | 0.97 mm | 1.29 mm |
| Edge of a 7 mm M3 washer to LED1's pads | 0.81 mm | 1.12 mm |
| Hole edge to board edge | 1.9 mm | 1.6 mm (= board thickness) |
Tolerances: JLCPCB's pick-and-place accuracy is a few hundredths of a millimetre, and hole position and board outline tolerances are about ±0.1-0.2 mm (±0.4 mm on a V-cut rail edge). Even with a worst-case 0.3 mm of stacked error, the washer stays about 1 mm clear of the LED body and the keep-out stays clear of LED1's courtyard.
Hardware that fits (front and back, around each hole):
| Item | Maximum diameter | Examples |
|---|---|---|
| Anything touching the board | 7.0 mm (the copper keep-out) | M3 washer DIN 125-A (7.0 mm) |
| To stay fully inside the board edge | 6.4 mm | M3 washer DIN 433 (6.0 mm); screw heads ISO 7380 button (5.7 mm), DIN 912 socket (5.5 mm), ISO 7045 pan (5.6 mm) |
| Hex standoffs | 5.5 mm across flats (6.35 mm across corners) or smaller | standard M3 brass or nylon standoffs |
A 7 mm washer overhangs the board edge by 0.3 mm at the new hole position. That is harmless, but a DIN 433 washer (6.0 mm) or no washer keeps it flush. Avoid large "wide" washers (DIN 9021, 9 mm).
2. ESP32 and the LED above it (LED18)
| Measurement | Before | Now |
|---|---|---|
| LED18 body to ESP32 body | 0.9 mm | 1.1 mm |
| LED18 pads to ESP32 body | 1.2 mm | 1.4 mm |
| Courtyards (assembly keep-out outlines) | 0.4 mm apart | 0.6 mm apart (no overlap) |
- JLCPCB's "Minimum Spacing for SMD Components" table recommends 1.0 mm between IC-type packages (QFN to QFN). Treating the ESP32 module and the LED that way, 1.1 mm now meets it.
- Only LED18 sits above the module; the next LEDs are 7 mm or more away.
- Repair: LED18 can still be replaced with a small hot-air nozzle, shielding the module with heat-resistant (Kapton) tape. The ESP32 itself can be removed without touching any LED pads.
3. Local clearance rule for the USB-C connector
File rithesh-led-display.kicad_dru (KiCad custom design rules, loaded automatically):
(rule "USB-C J1: 0.20 mm between items inside the connector footprint"
(condition "A.intersectsCourtyard('J1') && B.intersectsCourtyard('J1')")
(constraint clearance (min 0.2mm)))
- The Power net class is back to 0.25 mm.
- Only copper inside J1's courtyard (its pins and the short track stubs that will leave them) may be 0.20 mm apart. 0.20 mm is still twice JLCPCB's 0.10 mm minimum.
- Tested: without the rule file, DRC reports exactly the 8 USB-C pin pairs at 0.20 mm; with it they pass. A test GND track placed 0.22 mm from an LED's +5V pad (away from J1) was still flagged, so 0.25 mm applies everywhere else.
4. The 359 unconnected pads
Every one is a connection that routing (or placing the remaining parts) will make:
| Group | Count | What it is |
|---|---|---|
| +5V between LEDs, ESP32 and USB-C | 106 | Power rail, to be routed |
| GND between parts | 107 | Ground, to be routed / copper fill |
| LED data chain (LED n to LED n+1) plus CC1/CC2 from USB-C to ESP32 | 108 | 106 chain links + 2 CC lines |
| ESP32's own GND pads (22 pads incl. the 9-piece centre pad) | 29 | Tied together by ground copper under the module |
| USB-C's own pads: the two D+ pins, the two D- pins, VBUS pins, GND pins | 4 | Both plug orientations; joined by short tracks |
| USB-C shield tabs (4 x S1) to GND | 5 | Shield to ground copper |
- No pad is missing a net: every pad has its schematic net except the intended no-connect
pins (ESP32 spare pins and NC pads, USB-C SBU1/SBU2, LED107's data-out), the four M3 holes and
the USB-C's two plastic locating-peg holes (checked by
tools/check_placement.py). - Pads with the same number inside one footprint (ESP32 pad 49's nine pieces, USB-C shield S1) are shown as "unconnected" by KiCad until copper joins them. This is normal and will be done during routing.
Checks after the changes
| Check | Result |
|---|---|
| KiCad DRC | ✅ 0 violations, 0 footprint errors (359 unconnected pads, expected) |
tools/check_placement.py |
✅ all passed, including the new hole, ESP32-spacing and pad-net checks |
Close-ups: layout-review/placement-led1-corner.png, placement-esp32-led-spacing.png,
placement-usb-c-pins.png (all other placement images were re-rendered for the 0.2 mm shift).
Step 4: Parts chosen and all remaining components placed (2026-09-23)
All 264 schematic parts are on the board, plus the 4 mounting holes. Nothing is unplaced. No copper has been routed yet.
Parts list (JLCPCB/LCSC numbers, stock checked 2026-09-23)
| Refs | Part | LCSC | Footprint | Qty | Stock | Assembled? |
|---|---|---|---|---|---|---|
| J1 | HRO TYPE-C-31-M-12 USB-C, 5 A | C165948 | USB_C_Receptacle_HRO_TYPE-C-31-M-12 | 1 | ~90,000 | yes |
| U1 | USBLC6-2SC6 USB ESD | C7519 | SOT-23-6 | 1 | ~36,000 | yes |
| D1 | SMAJ5.0A surge diode | C2925443 | D_SMA | 1 | ~65,000 | yes |
| U2 | TPS259531DSGR eFuse | C2155674 | WSON-8 2x2 mm | 1 | ~2,000 | yes |
| U3 | TLV76733DRVR 3.3 V regulator | C2848334 | WSON-6 2x2 mm | 1 | ~17,000 | yes |
| U4 | ESP32-C3-MINI-1-N4 | C2838502 | ESP32-C3-MINI-1 (Espressif) | 1 | ~26,000 | yes |
| U5 | SN74AHCT1G125DBVR level shifter (TI) | C7484 | SOT-23-5 | 1 | ~23,000 | yes |
| LED1–LED107 | XL-5050RGBC-2812B (provisional) | C2843785 | LED_XL-5050RGBC-2812B | 107 | ~814,000 | yes |
| SW1–SW3 | XKB TS-1187A button, 5.1 mm | C318884 | SW_Push_1P1T_XKB_TS-1187A | 3 | ~1.7 M | yes |
| C301, C304 | 220 µF 16 V electrolytic | C72496 | CP_Elec_6.3x7.7 | 2 | ~106,000 | yes |
| C302, C303 | 220 µF 16 V (spare spots) | C72496 | CP_Elec_6.3x7.7 | 2 | – | no (DNP) |
| C10–C207 (LED + ESP32 + U5) | 100 nF 16 V X7R | C1525 | 0402 | 109 | ~16 M | yes |
| C2 | 100 nF 16 V X7R (eFuse soft-start) | C1525 | 0402 | 1 | ~16 M | yes |
| C1 | 4.7 µF 16 V X5R (USB input) | C19666 | 0603 | 1 | ~1.4 M | yes |
| C7, C8, C9 | 10 µF 25 V X5R | C15850 | 0805 | 3 | ~3.5 M | yes |
| C11 | 1 µF 25 V X5R (ESP32 enable delay) | C52923 | 0402 | 1 | ~4.5 M | yes |
| C13, C14 | USB D+/D- capacitor spots | – | 0402 | 2 | – | no (DNP) |
| R1, R2 | 5.1 kΩ 1 % (USB-C CC) | C25905 | 0402 | 2 | ~2.2 M | yes |
| R3 | 750 Ω 1 % (eFuse current limit) | C25132 | 0402 | 1 | ~44,000 | yes |
| R4, R6 | 100 kΩ 1 % | C25741 | 0402 | 2 | ~1.5 M | yes |
| R5 | 39 kΩ 1 % | C25783 | 0402 | 1 | ~106,000 | yes |
| R7–R12 | 10 kΩ 1 % | C25744 | 0402 | 6 | ~1.3 M | yes |
| R13 | 33 Ω (LED data) | C25105 | 0402 | 1 | ~970,000 | yes |
| R14, R15 | 22 Ω (USB D+/D-) | C25092 | 0402 | 2 | ~700,000 | yes |
| R16 | 499 Ω | C4125 | 0402 | 1 | ~262,000 | yes |
| TP1–TP10 | 1.5 mm bare test pads | – | TestPoint_Pad_D1.5mm | 10 | – | no (copper only) |
Fees and stock
- Basic vs extended: JLCPCB charges about $3 per "extended" part type on each order.
The Adom JLCPCB tool can't confirm basic status, so this is an estimate.
- The resistors and small capacitors are the common kind that are usually basic.
- The ICs, USB-C connector, surge diode, LEDs, buttons and 220 µF capacitor are probably extended: about 8–12 types, so roughly $24–36.
- Confirm the exact amount on the JLCPCB quote before ordering.
- Uncertain stock: only the TPS259531 eFuse (~2,000) is low. That is fine for a prototype batch, but check it again on the day you order. Every other part has 17,000 or more.
- Not assembled: C13, C14, C302 and C303 are marked "exclude from BOM and placement files", so JLCPCB leaves those spots empty. The test pads are bare copper. KiCad 7 has no separate "DNP" flag on the board. "DNP" is also printed above C302 and C303.
Where each group sits (all on the front, along the bottom strip below the letters)
| Group | Position | Why there |
|---|---|---|
| USB-C protection: U1, D1, C1, R1/R2 | Just above and beside J1 (x 86–100) | ESD and surge parts 7.7–10 mm from the connector pins, before anything else |
| eFuse U2 + R3–R6, C2 | x 104–112, right of D1 | Each support part 2.9–4.1 mm from its U2 pin |
| FLT / ILM test pads (TP7, TP8), 5V_OUT (TP2), GND (TP4) | x 113–119 | Next to the eFuse they measure |
| Regulator U3 + C7, C8 | x 51–58, just right of the ESP32 | 7.7 mm from the ESP32 3V3 pin; capacitors 1.8–3.2 mm from U3 |
| ESP32 capacitors C9–C11, R7, R10, 3V3 pad (TP3) | Beside the ESP32's right edge | 2.4–3.4 mm from the pins they serve |
| USB resistors R14/R15, DNP caps C13/C14, strap resistors R8/R9/R11/R16 | Left of the ESP32 (x 28–32) | Next to the ESP32 pins they connect to |
| Buttons SW1 RESET, SW2 BOOT, SW3 ON/OFF | x 64, 72, 80 | Easy to reach, with labels printed underneath (1.0 mm text) |
| UART pads RX, TX, GND (TP9, TP10, TP5) | Bottom-left corner | Labelled; room for 3 probe clips |
| Level shifter U5 + R12, R13 (33 Ω), C12, LED_DIN pad (TP6) | Left edge, beside LED1 | U5 → R13 4.0 mm, R13 → LED1 3.8 mm: a short, clean 5 V data path |
| 220 µF bulk | C301 x 13.5 (fitted), C302 x 140 (DNP), C303 x 212 (DNP), C304 x 283 (fitted) | Spread along the LED rail from one end to the other |
The antenna area and its two 15 mm side clearances stay empty. The checker confirms no pad or part is inside them.
How 107 LED capacitors fit in the 7 mm grid
- Each LED is 5 mm wide on a 7 mm grid, so there is a 2 mm gap between neighbouring LEDs. After each LED's courtyard (its "keep clear" outline) is counted, the gap is 0.8 mm side to side and 1.4 mm top to bottom.
- A 100 nF capacitor in 0402 size is only 1.0 × 0.5 mm (its courtyard is about 1.9 × 1.0 mm). It fits lengthwise in a 1.4 mm gap, or on the outer edge of a letter where there is no neighbour.
tools/place_parts.pytries the spots beside each LED's two power pads, starting with the closest. It takes the first spot that doesn't touch:- another part's courtyard
- a hole keep-out
- the antenna areas
- printed markings
- the LED pin-1 dots
- The capacitor is turned so its +5V end faces the LED's VDD pad.
- Result: all 107 fit. The +5V pad is on average 2.0 mm from the LED's VDD pad. The worst is 6.0 mm (LED97, where the neighbouring LEDs block the closer spots).
- Assembly spacing: no courtyard touches another. Each courtyard already includes a 0.25 mm margin around the part, so the pick-and-place machine has room. JLCPCB's own DFM check at quote time is the final word.
Polarity marks (checked against the nets)
- D1: the cathode band side (pad 1) is on VBUS.
- 220 µF capacitors: the "+" corner (pad 1) is on +5V for all four.
- U1, U2, U3, U5, U4 (ESP32) and every LED: the pin-1 dot or arrow is beside pin 1. U5 pin 1 (OE) goes to GND, which keeps it always on.
Checks after placement
| Check | Result |
|---|---|
| KiCad DRC | ✅ 0 violations, 0 footprint errors |
tools/check_placement.py (with NETLIST= for the new section 8) |
✅ all passed: 264/264 parts placed, all distances above, labels, test-pad spacing (closest 3.5 mm), bulk positions, DNP exclusion, antenna clear, holes clear (closest TP6, 0.34 mm outside the keep-out) |
| ERC (schematic changed: LCSC fields, capacitor values) | ✅ 0 errors, 0 warnings; schematic.pdf re-exported |
Unconnected pads (normal before routing):
- The DRC report says 499 and KiCad's connection count says 678. The two numbers measure in slightly different ways: the report doesn't list the LED data-chain links as separate items.
- A count by hand, if nothing is joined yet, gives about 682:
- +5V 224, GND 287, LED data chain 100, +3V3 12, VBUS 10, other signals 49
- The extra 4 are USB-C pins in the same spot that KiCad counts once.
- Every one is a link that routing will make. No pad is missing a net.
Review images (layout-review/)
placement-full-board.png- Close-ups:
parts-usb-power.png,parts-esp32-regulator.png,parts-buttons.pngparts-level-shifter.png,parts-led-capacitors.png(letter E)parts-bulk-left.png(C301 + UART pads),parts-bulk-right.png(C302 DNP),parts-bulk-far-right.png(C304)
Step 4b: Placement fixes before routing (2026-09-23)
| Request | What changed | Result |
|---|---|---|
| 1. USB ESD chip closer | U1 turned 270° and placed right above the USB-C data pins. D- enters pin 4 and leaves pin 3; D+ enters pin 6 and leaves pin 1 (straight through the chip, no branches). | U1's D+/D- pads are 1.58 mm from J1's D+/D- pads (about 2 mm of track). The old "7.7 mm" was measured from J1's centre point, not pad to pad. It can't go closer: the VBUS via for U1's pin 5 has to sit between U1 and the connector. |
| 2. TP6 away from the screw | TP6 moved down 1 mm; R13, U5, C12, R12 moved down with it. | Closest test pad is now 1.34 mm outside the screw/washer keep-out (was 0.34 mm). |
| 3. eFuse datasheet check | TI SLVSE57 section 11.1: the IN capacitor goes closest to IN/GND. RILM, CdVdT and the EN/UVLO resistors go next to their pins, with their other end straight to the chip's GND pin. The TVS goes close to the device it protects. The exposed pad must be tied to GND (vias optional). The old 2.9–4.1 mm spacing was looser than recommended, so the parts were moved. | Pad-to-pad gaps: C1 (IN cap) 0.83 mm, C2 (dVdt) 0.77 mm, R5 (EN) 0.86 mm, R4 0.45 mm from R5, R3 (ILM) 1.18 mm, D1 (TVS) 2.65 mm from the IN pins. R6 (FLT pull-up, not listed by TI) 2.42 mm. |
| 4. LED capacitors > 3 mm | For LED97, LED51 and LED28, the neighbouring LEDs (one of them turned 90°) leave only 1.07–1.08 mm between courtyards. The 0.94 mm capacitor courtyard fits there, but my 0.1 mm safety margin had rejected it. A "tight" spot (courtyards 0.07–0.12 mm apart, part bodies about 0.5 mm apart) is now allowed only for those three. | LED97 6.0 → 1.9 mm, LED51 5.1 → 1.4 mm, LED28 5.1 → 1.9 mm. All 107 are now ≤ 2.0 mm (average 1.8 mm). |
Other moves made for routing:
- Buttons SW1–SW3 moved to x = 62.3 / 70.6 / 78.1 so two signal tracks fit between SW1 and SW2, and wider lanes fit beside the USB-C connector.
- The BOOT, IO8 and ON/OFF pull-ups (R8, R11, R9) moved next to the tracks they pull up.
- C9 (10 µF) is now 6.3 mm from the ESP32 3V3 pin, so the USB pair can pass below it. The 100 nF (C10) is still 2.4 mm from the pin.
- CC resistors R1/R2 moved beside U1. TP1/TP7/TP8 moved next to the eFuse.
Checks: placement checker ✅ all passed; DRC ✅ 0 violations, 0 footprint errors (499 unconnected, nothing routed yet).
Step 5: Routing (2026-09-24)
Result: every connection is routed. KiCad DRC shows 0 violations, 0 unconnected pads, 0 footprint errors. The placement checker, ERC (0/0), the connection checker and the pin audit all pass.
How the board is built up
| Layer | What is on it |
|---|---|
| Back (B.Cu) | Solid ground plane over the whole board except the antenna area and its 15 mm side clearances. Only eight short planned jumps cut it (table below). None are under the LED area or near the antenna. |
| Front (F.Cu) | All parts and signal tracks. +5V copper fill over the whole LED area and the bottom strip right of the eFuse. Ground fill in the USB/ESP32 strip. |
The routing was done in stages. Each stage is saved and every step can be re-run with tools/route_board.py:
pre: critical copper by hand, each track checked against all other copper:- the USB pair and USB-C fan-out
- the eFuse and regulator pins
- the LED data line
- the ESP32 / button / USB-C strip lanes
- a ground via at every ground pad
- a direct +5V track from every LED to its capacitor
auto: Freerouting 1.9 routed the LED data chain, the UART lines, IO2 and the FLT/ILM test pads. Its output was checked: all 106 chain links are on the front layer with no vias, the worst at 1.36× the straight distance.import: those routes are imported. Nets that were routed by hand are skipped, so no extra stubs are added.finish: the ILM test-pad link is moved to a front-only path. Freerouting had used a back-layer jump there.zones: copper fills and planes are poured, with floating copper removed.
An earlier Freerouting attempt on the whole strip used 47 mm (CC1) and 41 mm (BOOT) of back-layer track. It was rejected and removed before this final routing.
Placement tweaks made for clean routing
These keep the LED grid, letters, holes, ESP32 and USB-C exactly where they were.
- Button order is now RESET, ON/OFF, BOOT (ON/OFF and BOOT swapped), 9 mm apart, 1.2 mm lower. The ESP32's top-edge pins are in the order BOOT, IO8, ON/OFF, CC2, CC1. With this button order the tracks can end one after another with no crossings.
- Pull-ups R11 (ON/OFF) and R9 (IO8) sit in the gaps between the buttons, and R8 (BOOT) sits above the BOOT button. 3.3 V reaches them on a track running under the buttons.
- R7 was turned 180° and C11 moved 0.6 mm down, so 3.3 V reaches R7 without crossing EN.
- The J1 label was moved 2.2 mm down (it touched the BOOT label).
The obstruction that blocked CC2 (investigated)
CC2 has to leave USB-C pin B5 northwards between the D+ track and the VBUS track at pin A9. The first VBUS track there was 0.8 mm wide, and its rounded end reached x = 92.05 mm. That left a 0.75 mm gap, while a 0.25 mm track needs 0.20 mm on one side plus 0.25 mm on the other (0.70 mm) with no margin at all. Freerouting had also put a VBUS via on that corner. Fix: the VBUS track starts 0.5 mm wide at x = 92.45 mm and only widens after it has passed the connector's ground pad. CC2 now passes with 0.255 mm and 0.225–0.275 mm on its two sides.
USB D+/D-
| Item | Value |
|---|---|
| Path | J1 → U1 (about 2 mm, straight in, flow-through pins 4→3 and 6→1) → west above the buttons → down beside J1 → west below the buttons → under the ESP32 on the back layer → up beside the module → R14/R15 (22 Ω) → ESP32 pins 26/27 |
| Why under the module | The ESP32's USB pins are on its left side and the USB-C is to its right. Passing over the top would cross six other ESP32 signals in a 1.7 mm gap under LED18. |
| Vias | D+ 2, D- 2 (the module crossing) + 2 for D- at the connector. The A7→B7 join sits under the connector body, as is normal for this 16-pin USB-C. |
| Track | 0.30 mm with 0.20 mm gap, routed side by side the whole way. The front parts are over the solid back plane, the back part under the module's front ground. |
| Length | D+ 79.9 mm, D- 81.5 mm including the unused-orientation stubs (difference well under 1 ns, far inside USB 2.0 Full-Speed limits) |
| Note | 2-layer 1.6 mm boards cannot reach 90 Ω differential impedance. This does not matter at 12 Mbit/s over a short track. |
Back-layer jumps (all deliberate, all short)
| Net | Back-layer length | Why |
|---|---|---|
| USB D+ / D- | 22 / 23 mm | Under the ESP32 (see above). The only long one; it sits under the module's ground, not under LEDs. |
| CC1 | 10.8 mm (2 jumps) | CC1 and CC2 must cross the BOOT/IO8/ON-OFF lines. Here CC1's second jump crosses under the USB-C fan-out, because its pin sits inside the USB pair. |
| VBUS (left pad) | 9.0 mm | The second VBUS pad of USB-C sits inside the USB pair. It joins U1's VBUS pin and the main VBUS track. |
| +5V (regulator feed) | 7.9 mm | +5V comes from the fill above the lanes, down to U3 / C7. |
| LED data (3.3 V) | 7.1 mm | ESP32 pin 16 is boxed in by the button lines. It jumps once and runs to the level shifter at the left edge. |
| CC2 | 3.5 mm | Same crossing as CC1 at the module edge. |
| +3V3 | 3.5 mm | 3.3 V to the eFuse FLT pull-up R6 crosses the CC lines once. |
Total non-ground back-layer copper: 87 mm, all in the bottom-left strip (x 29–96 mm, the USB-C/ESP32 area). Vias: 287 in total:
- 264 ground vias
- 9 thermal vias in the ESP32 pad, 2 in each of the eFuse and regulator pads (TI layout examples)
- 21 signal vias
LED capacitors
All 107 capacitors have a direct +5V track to their LED's VDD pad (about 1.8 mm on average). For ground, each capacitor pad and each LED ground pad has its own via straight into the solid ground plane (the LED's via sits under its body). That gives a shorter, lower-inductance loop than a surface track around the LED would, because the LED's ground pad is on the far corner from its VDD pad.
Voltage drop and current capacity (tools/power_analysis.py)
The filled copper is solved as a resistor network (1 oz copper, 0.49 mΩ per square), with the current spread evenly over all LEDs:
| Total LED current | Worst +5V drop | Worst GND rise | Worst total (LED96, far end) |
|---|---|---|---|
| 1.88 A (WLED limit) | 8 mV | 2 mV | 9 mV (11 mV with warm copper) |
| 2.9 A (eFuse maximum) | 12 mV | 3 mV | 14 mV (17 mV warm) |
Most of this drop is in the eFuse's own output pin (0.25 mm wide) and the few millimetres next to it. The 300 mm +5V fill and the ground plane add only about 1–3 mV. That is under 0.3 % of 5 V, so every LED gets essentially the same voltage. The larger drops are before the board: the eFuse switch (34 mΩ, about 64 mV at 1.88 A) and the USB cable.
Current capacity of the narrowest power copper (IPC-2221, outer 1 oz, long-track rule, so short tracks run cooler):
| Conductor | Width × length | ≈ 10 °C rise | ≈ 20 °C rise |
|---|---|---|---|
| VBUS main (J1 → TVS) | 1.2 mm × 7 mm (0.5–0.8 mm for the first 1.8 mm at the connector) | 2.7 A | 3.7 A |
| VBUS left pad jump | 0.5 mm × 7.5 mm (carries part of the current) | 1.4 A | 2.0 A |
| VBUS into eFuse IN (2 pins) | 0.6 mm × 1.5 mm | 1.7 A | 2.2 A |
| eFuse OUT (the chip's own pin width) | 0.25 mm × 1.2 mm | 0.9 A | 1.2 A (very short, heat sinks into the chip and wide copper) |
| 5 V out to fill | 0.8 mm × 3 mm | 2.0 A | 2.8 A |
| +5V fill and ground plane | 16,600 mm² / 20,250 mm² | far above 3 A |
At the design maximum (2.2 A including the ESP32) the rise is modest. At the eFuse's 2.9 A current limit the narrow parts next to the connector and the eFuse pin would get warm, but only briefly, until the eFuse limits the current.
Remaining warnings and uncertainties
- The button order changed to RESET, ON/OFF, BOOT (labels moved with the buttons). Please confirm this is fine.
- The eight back-layer jumps above are necessary with the approved ESP32 / USB-C positions. A future revision with the USB-C to the left of the ESP32 would remove the module crossing.
- Freerouting chose the LED chain, UART, IO2 and FLT test-pad tracks. They are DRC-clean and direct, but they were not hand-drawn.
- USB impedance is not controlled (not possible on a 2-layer 1.6 mm board). This is acceptable for Full-Speed USB.
- The voltage-drop figures assume the current is spread evenly over the LEDs. With one bright letter at the far end, the drop there is still only tens of millivolts.
- JLCPCB's own DFM check at quote time is still to be done. That includes the three "tight" LED-capacitor spots and the via-in-pad thermal vias under the ESP32, eFuse and regulator.
- Tools used only in the cloud container: OpenJDK 21, Freerouting 1.9.0, Shapely, numpy, scipy. Nothing was installed on the Mac.
Review images (layout-review/)
routed-full-board.png(with fills),routed-full-tracks.png(fills hidden),routed-front-copper.png,routed-back-copper.png- Close-ups (fills hidden):
routed-usb.png,routed-usb-pair.pngrouted-power.png,routed-esp32.png,routed-strip.pngrouted-led-rail.png,routed-far-end.png,routed-led1-shifter.png
- The older
placement-*andparts-*images show the placement before the button swap and are superseded by these.
Step 5b: Final checks before approval (2026-09-24)
Approved by the user: button order RESET, ON/OFF, BOOT; the small R/C and J1-label moves (electrical connections unchanged, confirmed by the connection checker and the pin audit).
1. USB routing
| Item | Result |
|---|---|
| Vias | D+ 2, D- 4. Both lines take the same 2 vias to pass under the ESP32. D- has 2 more at the USB-C connector: this 16-pin connector interleaves D-/D+/D-/D+ pads, so one of the two D- pads (A7) must cross over to the other (B7). The crossover is under the connector body and is only in the signal path for one plug orientation. |
| Can they be symmetrical? | Only by adding 2 unnecessary vias to D+. Each via is about 0.3 pF / 0.5 nH, a few picoseconds, which is irrelevant at 12 Mbit/s, so this was not done. |
| Ground return at layer changes | Ground stitching vias added beside every USB layer change. At the ESP32 up-point and at the connector crossover, each USB via has a ground via 0.85–0.92 mm away. At the ESP32 dive-point, D-'s via has one 0.87 mm away; D+'s nearest is 1.73 mm (no free spot closer: C10, the module pins and the back-layer pair fill the area). The front ground fill and back plane are continuous around both. Along the whole run the pair has solid ground on the other layer. |
Differential impedance (tools/usb_impedance.py, 2D field solve) |
Cross-section: JLCPCB 2-layer 1.6 mm, FR-4 1.53 mm (er 4.5), 1 oz copper, ~20 µm solder mask. Traces 0.30 mm, gap 0.20 mm. About 113 Ω differential where the ground fill runs 0.25 mm beside the pair (most of the route), about 122 Ω over the plane alone (common mode 57–93 Ω). Nominal is 90 Ω; hitting it would need about 1 mm wide traces, which do not fit the connector fan-out. At 12 Mbit/s the 8 cm route is electrically short (about 0.45 ns against 4–20 ns edges), so the mismatch does not matter. |
| Length difference | D+ 83.0 mm, D- 85.2 mm including the MCU side (the extra D- length is mostly the connector crossover stub). A 1.6–2.2 mm difference is about 10–12 ps, against USB Full-Speed edges of 4–20 ns and an 83 ns bit time. Acceptable. |
2. Vias in exposed pads: changed
The previous design had 13 open vias inside exposed pads (ESP32 9, eFuse 2, regulator 2). The pads have a solder-mask opening, so those holes would have been open and could pull solder away during reflow. They are replaced by ordinary tented vias beside the pads:
- ESP32: 6 vias under the module in the free bands left and right of its centre pad, each with a short track to the pad. The ground fill under the module also joins them.
- eFuse: 2 vias just outside the pad ends, with short tracks.
- Regulator: 1 via above its pad, plus its two ground pins and the fill.
The same scan found that many small ground vias (107 LEDs, some capacitors, D1, SW2, U5) had holes just touching a pad corner. Every via now keeps its drilled hole at least 0.1 mm clear of any pad's mask opening (via centre ≥ 0.25 mm from the pad). Checked on the final board: 287 vias, 0 holes inside a pad, closest hole edge 0.105 mm from a pad opening.
| Via | Value |
|---|---|
| Drill / pad | 0.30 mm / 0.60 mm (JLCPCB standard, no extra cost) |
| Solder mask | Tented (covered). KiCad plot option "plot vias on mask" is off, and JLCPCB's default for 2-layer boards is tented vias |
| Special process | None needed: no via-in-pad filling or capping |
3. Power entry, section by section (python3 tools/power_analysis.py sections)
Input current 2.2 A is the design maximum (LEDs at the WLED limit plus the ESP32); 2.9 A is the eFuse's highest possible current limit, held only briefly. Voltage drop is from 1 oz copper at 0.49 mΩ/square. "IPC" is the IPC-2221 long-track rule. "Short-neck" is a conduction estimate for pieces under 5 mm long that are held by pads or wide copper at both ends. The IPC rule greatly overstates heating for those.
| Section (width × length) | Current at 2.2 A / 2.9 A | Drop 2.2 / 2.9 A | Heat 2.9 A | Rise at 2.9 A |
|---|---|---|---|---|
| VBUS right pad stub (0.5 × 1.55 mm) | 1.9 / 2.5 A (58–87 % of the input) | 2.9 / 3.8 mV | 10 mW | 0.3 °C short-neck (IPC 35 °C) |
| VBUS left pad stub (0.3 × 0.75 mm) | 0.9 / 1.2 A | 1.1 / 1.5 mV | 2 mW | <0.1 °C |
| VBUS left, back-layer link (0.6 × 9.1 mm) | 0.9 / 1.2 A | 6.8 / 9.0 mV | 11 mW | 4.9 °C (IPC) |
| VBUS main, 0.8 mm part (0.8 × 1.1 mm) | 2.2 / 2.9 A | 1.5 / 2.0 mV | 6 mW | 0.1 °C |
| VBUS main to TVS (1.2 × 9.4 mm) | 2.2 / 2.9 A | 8.4 / 11.1 mV | 32 mW | 6.1 / 11.5 °C (IPC) |
| TVS → input capacitor (0.8 × 1.6 mm) | 2.2 / 2.9 A | 2.2 / 2.8 mV | 8 mW | 0.2 °C |
| Input capacitor → eFuse IN pins (0.6 × 1.45 mm) | 2.2 / 2.9 A | 2.6 / 3.4 mV | 10 mW | 0.2 °C |
| eFuse OUT pin neck (0.25 × 1.2 mm, the pin's own width) | 2.2 / 2.9 A | 5.2 / 6.8 mV | 20 mW | 0.5 / 0.9 °C short-neck |
| 5 V out → +5V fill (1.2 × 3.05 mm, widened from 0.8) | 2.2 / 2.9 A | 2.7 / 3.6 mV | 11 mW | 0.2 °C |
| eFuse switch itself (34 mΩ typ., RθJA 65.6 °C/W) | 2.2 / 2.9 A | 75 / 99 mV | 286 mW | chip +11 / +19 °C |
- USB-C VBUS contacts: the connector is rated 5 A over its four VBUS contacts, so 2.5 A per pad pair. The right pad carries 1.9 A at 2.2 A (within rating) and up to 2.5 A at the brief 2.9 A limit (at rating).
- Widened in this step: 5 V out to the fill (0.8 → 1.2 mm) and the left-VBUS back link (0.5 → 0.6 mm). The remaining narrow parts are set by pin widths (eFuse pins, USB-C pads) or by clearance to neighbouring pads, and they run cool because they are short.
- Board copper total: VBUS path about 18 mV and 5 V output about 8 mV at 2.2 A. The +5V fill and ground plane add 9–14 mV to the worst LED.
4. Copper-fill and assembly checks
- All 107 LED +5V pads and all 107 capacitor +5V pads touch the +5V fill and have their direct LED–capacitor track. All 214 LED/capacitor ground pads have a track to their own ground via.
- Thermal reliefs (0.30 mm gap, 0.50 mm spokes) are now used for all pads in all fills, so small 0402/0603 parts heat evenly during reflow (less risk of tombstoning). Solid connections are kept only for the ESP32 module's 30 ground pads and the eFuse/regulator exposed pads, which need full copper for heat. Rule file: a pad may resolve with one spoke, because every such pad also has its own via or track.
- Antenna keep-out: no copper, fill, via, track or part on either layer. Checked with exact shapes and the actual filled copper.
- Button labels vs connections after the swap: RESET = SW1 (EN), ON/OFF = SW3 (BTN_ONOFF), BOOT = SW2 (BOOT). All match.
5. Visual review
- 3D views (KiCad 3D viewer; models for this render only, in the cloud container):
3d-front.png,3d-back.png,3d-front-strip.png,3d-front-angled.png- Stand-ins and gaps:
- The XL-5050 LED is drawn with KiCad's WS2812B 5050 model (same size and pin layout).
- No 3D model exists for the XKB TS-1187A buttons or the HRO USB-C connector, so those show as footprint outlines only.
- The DNP capacitors C302/C303 are drawn in the render but will not be fitted.
- Polarity and pin 1: D1's cathode band on VBUS, "+" on the +5V pad of all four 220 µF capacitors, and pin-1 dots on U1–U5, J1 and every LED all match the nets. KiCad's silkscreen checks (overlap, silk on pads) are part of the DRC: 0 issues. The DNP labels sit above C302/C303, and the test-pad labels read 5V_IN, 5V_OUT, 3V3, GND, LED_DIN, FLT, ILM, RX, TX.
- The outdated
placement-*andparts-*images (old button order) were moved out of the project to a cloud scratch archive, so they cannot be published by mistake.
Checks after all corrections
| Check | Result |
|---|---|
| KiCad DRC | ✅ 0 violations, 0 unconnected pads, 0 footprint errors |
| ERC | ✅ 0 errors, 0 warnings |
| Placement checker | ✅ all passed (including exact antenna-area check with fills) |
| Connection checker | ✅ all expected connections, LED chain 1–107 continuous |
| Pin audit | ✅ passed |
| Voltage drop (fills) | worst LED 9 mV at 1.88 A, 14 mV at 2.9 A |
| Freerouting (final run) | LED chain, UART, IO2, FLT test pad: front layer only, no vias |
Step 6: Approval and manufacturing package (2026-09-24)
Approved for a prototype by the user on 2026-09-24. Accepted prototype risks, in addition to requirements.md risks 1–5:
- USB differential impedance about 113–122 Ω (see Step 5b)
- one USB-C VBUS pad pair at its 2.5 A contact rating only during the eFuse's brief 2.9 A limit
Required before ordering (not done yet):
- The XL LED timing pre-check passes (
firmware/README.md, section 1). - JLCPCB's DFM check, 3D placement preview (rotations / pin 1 of every part type), stock and final price are reviewed.
Manufacturing package (manufacturing/RITHESH-v1-PROTOTYPE/, made by tools/make_manufacturing.py)
| File | Content |
|---|---|
RITHESH-v1-PROTOTYPE-DO-NOT-ORDER-gerbers.zip |
The file JLCPCB asks for: 9 Gerber layers, PTH + NPTH drills, Gerber job file, do-not-order note |
gerber/ |
Same files unzipped, plus drill maps (PDF) |
assembly/BOM-JLCPCB.csv |
27 lines, 250 parts, all with LCSC numbers; DNP parts and test pads left out |
assembly/BOM-full.csv |
All 264 parts, with DNP (C13, C14, C302, C303) and bare test pads marked |
assembly/CPL-JLCPCB.csv |
250 placements: position (mm, from the bottom-left board corner), side (all Top), rotation |
assembly/assembly-front.pdf, assembly-back.pdf |
Assembly drawings (outline, fab layer with references, silkscreen) |
FABRICATION-NOTES.md |
Board options (300 × 70 mm, 2 layers, 1.6 mm, 1 oz, tented vias), holes, assembly notes |
Verification (2026-09-24):
- Gerber viewer: every layer, drill file and the outline were opened in gerbv (installed in the cloud workspace) and checked by eye:
- copper matches the design, with the back-layer plane and the planned short jumps
- mask openings only on pads (vias tented)
- silkscreen labels readable
- the antenna area is empty
- the outline is 300 × 70 mm with rounded corners
- Drills:
- plated file: 287 vias of 0.30 mm + 4 plated USB-C shield slots
- non-plated file: 4 × 3.2 mm mounting holes + 2 × 0.65 mm USB-C locating pegs
- BOM and CPL vs the PCB: 264 footprints compared by script. Every fitted part appears once in both, and values, footprints, positions and rotations match the board exactly. No mismatches.
- The board's drill/place origin was set to the bottom-left corner, and the title block now shows the prototype status. These are metadata only; DRC was re-run afterwards: 0 / 0 / 0.
# PCB layout notes
Plain-language record of the PCB layout, step by step. Screenshots are in
[layout-review/](layout-review/).
**Status (2026-09-23):** footprints, board outline and rules, four M3 holes, and the
**placement step** are done: the ESP32, the USB-C connector and all 107 LEDs are placed.
**The other parts (power, protection, buttons, support parts) are not placed, and nothing is
routed yet.**
## Step 1: Footprints
A footprint is the pattern of copper pads that a part is soldered onto.
### ESP32-C3-MINI-1 (`rithesh_fp:ESP32-C3-MINI-1`)
- **Source:** Espressif's official KiCad footprint (espressif/kicad-libraries, CC-BY-SA 4.0
with the KiCad design exception, the same terms as KiCad's own libraries).
- **One change:** its silkscreen lines were 0.12 mm thick; JLCPCB needs at least 0.15 mm, so
they were widened to 0.15 mm. Pads were not changed.
- **Checked against the datasheet land pattern (Figure 11-1)** by `tools/check_footprints.py`:
| Measurement | Datasheet | Footprint |
|-------------|-----------|-----------|
| Module outline | 13.2 x 16.6 mm | 13.2 x 16.6 mm |
| Edge pads | 48 pads, 0.4 x 0.8 mm, 0.8 mm pitch, pointing inward | same |
| Left/right pad columns apart (centres) | 11.8 mm | 11.8 mm |
| Top/bottom pad rows apart | 9.8 mm | 9.8 mm |
| Corner pads | 4 x 0.7 x 0.7 mm, 11.9 x 9.9 mm apart | same |
| Centre ground pad (pin 49) | 9 squares 1.45 mm, block 5.4 mm, pin-1 corner chamfer 0.6 mm | same |
| Pin 1 | top-left, next to the antenna end | same |
| Antenna keep-out | antenna area must have no copper | 13.2 x 5.4 mm keep-out on all copper layers |
- Espressif's drawing also shows optional vias in the centre ground pad for cooling. They are
not part of the footprint; we can add them during routing if wanted.
### LED (`rithesh_fp:LED_XL-5050RGBC-2812B`)
- **Source:** drawn from the XL-5050RGBC-2812B datasheet's "Recommended Soldering Pattern".
- **Pads:** four 1.3 x 1.3 mm squares, 3.1 mm apart across and 1.8 mm apart down
(pad centres at ±2.2 mm and ±1.55 mm from the middle).
- **Pin order:** 1 VDD (top-left), 2 data out (bottom-left), 3 GND (bottom-right), 4 data in
(top-right), same as the schematic symbol.
- **Silkscreen:** body outline kept at least 0.22 mm away from the pads, 0.15 mm lines, and a
dot next to pin 1 so the LED orientation can be checked by eye.
- **Courtyard** (the "keep other parts out" area): 6.2 x 5.6 mm. At our 7 mm LED spacing this
leaves 0.8 mm between neighbours side by side and 1.4 mm between rows.
### Can one footprint safely support both LED options? **No, not confirmed.**
See [layout-review/led-pad-comparison.png](layout-review/led-pad-comparison.png).
| | XL-5050RGBC-2812B | WS2812B-B/T |
|---|---|---|
| Metal terminals fully on our pads? | Yes | Yes |
| How far the pad reaches past the terminal's outer end ("toe") | +0.15 mm, as its datasheet recommends | +0.15 mm, but **its datasheet recommends +0.50 mm** (1.5 x 0.9 mm pads) |
- The WS2812B would sit on the pads, but with a smaller solder fillet than its maker intends.
- JLCPCB's assembly terms say footprints must follow IPC-7351B medium/low density, and
*"If the component in the BOM does not match the footprint, this part will not be
populated."* Nothing published by JLCPCB approves a WS2812B on XL-sized pads.
- A larger "superset" pad covering both patterns was considered, but oversized pads can let a
part float or rotate during soldering, and it would match neither manufacturer's pattern.
- **Decision:** the footprint is made for the **XL LED only** (the provisional selected part).
Switching to the WS2812B-B/T would need its own footprint (a board change), on top of the
5.3 V issue already recorded in requirements.md.
## Step 2: Board outline and JLCPCB design rules
### Outline
| Item | Value | Why |
|------|-------|-----|
| Size | **300 x 70 mm** | As decided in requirements.md. |
| Corners | **2 mm radius** | Rounded corners are kinder to hands and less likely to chip. The overall 300 x 70 mm size is unchanged. |
| Layers | **2 copper layers** (top + bottom) | Enough for this design; cheapest option. |
| Thickness | **1.6 mm FR4, 1 oz copper** | JLCPCB's standard board. |
| Drawing origin | top-left board corner | Positions in later steps are measured from here. |
KiCad measures the outline as 300.05 x 70.05 mm because it includes the 0.05 mm drawing line;
the actual cut line is 300 x 70 mm.
### Design rules (checked by KiCad's DRC)
JLCPCB's published minimums for 2-layer boards are the absolute limits. We chose a margin
above them so the board is easy to make at the standard price.
| Rule | Our value | JLCPCB minimum | Why our value |
|------|-----------|----------------|---------------|
| Track width (smallest allowed) | 0.15 mm | 0.10 mm | margin |
| Gap between copper (smallest allowed) | 0.15 mm | 0.10 mm | margin |
| Via (small plated hole joining the two layers) | 0.3 mm hole, 0.6 mm pad | 0.15 mm hole, 0.25 mm pad | JLCPCB: pad 0.1 mm (0.15 preferred) larger than the hole; holes under 0.25 mm cost extra |
| Hole to hole | 0.5 mm | 0.45 mm | margin |
| Hole to copper | 0.25 mm | 0.2 mm | margin |
| Copper to board edge | 0.5 mm | 0.2 mm | margin; protects tracks when the board is cut |
| Silkscreen line / text height | 0.15 mm / 1.0 mm | 0.15 mm / 1.0 mm | JLCPCB minimum |
| Solder mask bridge | 0.1 mm | 0.1 mm | JLCPCB minimum |
### Track sizes by net (net classes)
| Class | Nets | Track width | Gap |
|-------|------|-------------|-----|
| Default | all signals | 0.25 mm | 0.2 mm |
| Power | VBUS, +5V, GND | 1.0 mm (plus wide copper areas later) | 0.25 mm |
| Supply3V3 | +3V3 | 0.5 mm | 0.2 mm |
| USB | USB_DP, USB_DN (and the ESP32 side) | 0.3 mm | 0.2 mm |
## Checks run
| Check | Result |
|-------|--------|
| `tools/check_footprints.py` (datasheet dimensions, JLCPCB pad gaps, silkscreen, courtyard) | All passed. Also tested with a deliberately shifted LED pad, which it caught. |
| KiCad DRC on the board (outline + rules) | 0 violations, 0 unconnected, 0 footprint errors (`drc-report.rpt`) |
| DRC test with the new footprints placed (scratch copy) | 0 pad, clearance or courtyard problems. One silkscreen warning, see "Warnings" below. |
| DRC test with deliberate mistakes (scratch copy) | Caught all: overlapping LEDs, too-thin track, copper too close to the edge, clearance |
| Schematic: `check_netlist.py`, `check_pins.py`, ERC | All passed; ERC 0 errors, 0 warnings. Symbol pins now also match the ESP32 and LED footprint pads. |
## Warnings and uncertainties
1. **LED reference labels will not fit.** At 7 mm spacing, one LED's printed name (for
example "LED3") lands 0.08 mm from the outline of the LED above it (DRC silkscreen
warning). With 107 LEDs the labels would overlap everywhere.
2. **JLCPCB's 2.5 mm edge rule.** JLCPCB's assembly terms require part bodies to be at least
2.5 mm from the board edge. The USB-C connector must sit at the edge, and Espressif wants
the ESP32 antenna at (or past) the edge. This usually means JLCPCB adds removable "edge
rails", which can add a small cost.
3. **Board height 70 mm = JLCPCB's minimum** for its "Standard" assembly service
(70 x 70 mm). We are exactly at the limit; do not make the board any shorter.
4. **IPC-7351B:** the LED footprint follows the LED maker's recommended pattern; its IPC
density class was not formally calculated. JLCPCB's DFM check at order time is the
final confirmation.
5. **ESP32 thermal vias:** optional per Espressif; not yet decided.
## Decisions (approved 2026-09-23)
### 1. LED labels
- The 107 individual LED names (LED1 ... LED107) are **hidden on the front silkscreen**.
They stay in KiCad and in the assembly (position) files JLCPCB uses, and on the
assembly drawing layer.
- A clear **"LED1"** marker (1.5 mm text, 0.22 mm lines) sits in the top margin above the
first LED, with an **arrow pointing right**, the direction the data chain starts along the
top row of "R". It is 2.25 mm above the LED body and 1.75 mm from the board edge.
- **More direction arrows** (one per letter-to-letter step, in the empty columns between
letters where there is room for 3 mm arrows) are added in the next step, once the chain
path inside each letter is fixed. Arrows between individual LEDs would have to be under
0.9 mm long to fit between the pads, too small to read, so they are not used.
- **Readable after assembly:** all markers are printed outside the LED bodies and pads, so
the 1.6 mm tall LEDs do not cover them; text is 1.5 mm (JLCPCB minimum 1.0 mm) and lines
0.22 mm (minimum 0.15 mm).
### 2. Four M3 mounting holes
| Item | Value |
|------|-------|
| Hole | 3.2 mm, non-plated (no copper ring), KiCad standard M3 footprint |
| Positions (hole centres, from the board's top-left corner) | H1 (3.2, 3.2), H2 (296.8, 3.2), H3 (3.2, 66.8), H4 (296.8, 66.8) mm, i.e. 3.2 mm in from both edges at each corner (moved from 3.5 mm in the clearance review, see Step 3b) |
| Keep-out around each hole | 7 mm circle (3.5 mm radius) on both copper layers: no copper fill, tracks or vias. Fits an M3 washer (7 mm) or screw head (5.5-6 mm). |
| Hole edge to board edge | 1.6 mm (= board thickness) |
| Rounded corner | clear: the 2 mm corner curve ends 3.8 mm from the hole centre |
| Nearest LED (courtyard) | 0.61 mm outside the 3.5 mm keep-out (LED1) |
| Nearest LED copper pad | 1.12 mm outside a 7 mm washer, about 3 mm from the hole edge (JLCPCB needs 0.2 mm from a non-plated hole to copper) |
| ESP32 antenna area / USB-C | not near any hole (ESP32 at x = 40 mm, USB-C at x = 90 mm; nearest hole at x = 3.2 mm) |
### 3. JLCPCB edge rails
- JLCPCB recommends **5 mm process edges (rails)** for SMT assembly, with 1 mm fiducials and
2 mm tooling holes on the rails. They are needed here because the USB-C connector and the
ESP32 sit at the board edge (JLCPCB's terms ask for 2.5 mm from part bodies to the edge
otherwise).
- Planned: one 5 mm rail on each long edge (top and bottom). The panel JLCPCB assembles is then
300 x 80 mm; the rails are snapped off afterwards, leaving the **300 x 70 mm** board.
- JLCPCB's V-cut runs exactly along the board outline. Their V-cut rules: copper at least
0.4 mm from a V-cut edge (our rule is 0.5 mm, and the nearest USB-C copper is 1.8 mm from
the edge); V-cut edge tolerance **±0.4 mm**.
- **Cost:** JLCPCB does not publish a fixed rail price. The board area grows about 14 %
(300 x 80 vs 300 x 70 mm), and panelised boards can have an engineering fee. **The exact
extra cost will be read from JLCPCB's quote page before manufacturing, and shown to you
before any order.**
- **To confirm with JLCPCB at quote time:** V-cuts are straight lines, but our corners are
rounded (2 mm). JLCPCB may route the corners or use "mouse bite" tabs; mouse bites leave
small bumps (a few tenths of a mm) that are sanded smooth. If that is a problem, square
corners would give the cleanest V-cut.
## Pre-placement checks (2026-09-23)
| Question | Answer |
|----------|--------|
| Does the ESP32 antenna keep-out cover every copper layer, with no parts or copper under it? | **Yes.** Espressif's footprint has a 13.2 x 5.4 mm rule area on all copper layers ("*.Cu") that forbids tracks, vias, pads, copper fill and footprints. When the ESP32 is placed, a board-level keep-out will also cover Espressif's 15 mm side clearance along the edge (planned area shown on the drawing layer). |
| Do the mounting-hole clearances meet JLCPCB's rules? | **Yes.** Nearest copper is about 3 mm from a hole (needs 0.2 mm); hole edge to board edge 1.6 mm (after Step 3b); hole is a standard 3.2 mm non-plated hole (JLCPCB minimum 0.5 mm, tolerance ±0.2 mm). |
| Can the USB-C connector sit at the edge without changing the board size? | **Yes.** Its body front (3.65 mm from its centre) is placed exactly on the bottom edge, so it does not stick out and the outline stays 300 x 70 mm. Its nearest copper is 1.8 mm inside the edge. |
| Will the LED1 marker and arrows stay readable after assembly? | **Yes.** They are printed outside LED bodies and pads, above JLCPCB's minimum sizes, and DRC found no silkscreen overlap. |
| Do the planned parts fit together? (scratch test: all 107 LEDs, ESP32, USB-C temporarily placed) | **Yes:** no courtyard overlaps, nothing in the antenna keep-out; ESP32 top edge 0.6 mm below the LED area. |
Scratch-test findings to handle when the parts are really placed:
- The ESP32 and USB-C footprints draw silkscreen right up to their front edge, which is the
board edge. JLCPCB would clip it; those lines will be trimmed (cosmetic only).
- The USB-C footprint has shared pads (A1/B12 = GND, A4/B9 = VBUS); the scratch test
showed them as "clearance" errors only because it had no nets. With the real nets they
are the same net and correct.
### Planning layer (User.Drawings, not manufactured)
The drawing shows grey outlines for: the 107 planned LED positions (they spell RITHESH), the
LED courtyard envelope (x 6.9-293.1 mm, y 5.2-52.8 mm), the ESP32 module (centre x 40 mm,
flush with the bottom edge), its antenna keep-out and 15 mm side clearance, the USB-C
connector (centre x 90 mm, flush), and the two 5 mm JLCPCB rails. The ESP32 and USB-C
positions are proposals for the next step.
## Step 3: Placement of the ESP32, USB-C and 107 LEDs (2026-09-23)
Made by `tools/place_parts.py` (run after `tools/make_board.py`). Each placed part carries its
schematic reference, value, link to the schematic symbol and the schematic's nets on its pads,
the same as KiCad's "Update PCB from Schematic".
### ESP32 and USB-C
| Part | Position (centre, from the board's top-left corner) | Notes |
|------|------|------|
| U4 ESP32-C3-MINI-1 | x = 40.0 mm, y = 61.7 mm, turned 180 deg | Antenna end exactly on the bottom edge. Its body is 1.1 mm from the LED above it (after Step 3b). |
| J1 USB-C | x = 90.0 mm, y = 66.35 mm, not turned | Opening faces the bottom edge; body front exactly on the edge, so nothing sticks out and the board stays 300 x 70 mm. |
- **Antenna areas:** the module's own keep-out (13.2 x 5.4 mm, all copper layers) plus two new
board keep-outs of 14.8 mm on each side of it, along the bottom edge, on both copper layers.
They forbid copper fill, tracks, vias, pads and parts. (They start at the module's 0.2 mm
courtyard line, so they total 15 mm from the module body.)
- **Edge silkscreen trimmed:** the ESP32 and USB-C footprints' silkscreen lines that reached the
board edge were trimmed in the project library copies (ESP32: 3 removed, 3 shortened; USB-C:
1 removed, 2 shortened), so JLCPCB will not clip them. The USB-C footprint is now a project
copy (`rithesh_fp:USB_C_Receptacle_HRO_TYPE-C-31-M-12`); the schematic points to it.
- **Power-net clearance:** first lowered to 0.20 mm for the whole board because the USB-C
connector's GND and VBUS pins are only 0.20 mm apart; in Step 3b this was replaced by a local
rule (0.20 mm only inside the USB-C footprint, 0.25 mm everywhere else).
### LED order and chain path
- LED1-LED107 follow the schematic exactly: **R** LED1-18, **I** 19-29, **T** 30-40,
**H** 41-57, **E** 58-75, **S** 76-90, **H** 91-107. On the board, LED n's data-out and
LED n+1's data-in share the same net for every n (checked).
- Inside each letter the chain **snakes row by row** (like reading a zig-zag): along one row,
then back along the next.
- Letters **alternate top-down and bottom-up**, so each letter finishes right next to where the
next letter starts:
| Letter | LEDs | Starts | Ends |
|--------|------|--------|------|
| R | 1-18 | top-left (LED1) | bottom-right |
| I | 19-29 | bottom row | top row |
| T | 30-40 | top-left | bottom of the stem |
| H | 41-57 | bottom-left | top-right |
| E | 58-75 | top-left | bottom-right |
| S | 76-90 | bottom-left | top-right |
| H | 91-107 | top-left | bottom-right (LED107, end of chain) |
- The red line in the review images (User.Comments layer, not manufactured) shows this path.
The per-LED list with positions and rotations is in `tools/led_chain.csv`.
### Rotated LEDs
- Each LED's data-in and data-out pads are on opposite corners. Each LED is turned (0, 90, 180
or 270 degrees) so its **data-out pad faces the next LED and its data-in pad faces the previous
one**. This keeps the data tracks short in the routing step.
- Result: 0 deg x 26, 90 deg x 24, 180 deg x 42, 270 deg x 15. The LED lens is round and the
body square, so this does not change how the letters look.
- **100 LEDs** face both neighbours. **7 "turn" LEDs** (LED5, LED15, LED21, LED27, LED34,
LED62, LED65) are where the chain comes in and goes out on the same side (for example the
end of a row in "R"). With opposite-corner pads no rotation can face both, so each uses the
best of its four rotations; one data track will run a few millimetres around that LED.
### LED1 marker and direction arrows
- "LED1" with a start arrow sits in the top margin above LED1 (from the previous step).
- **6 letter-to-letter arrows** (6 mm long, 0.22 mm lines) are printed in the empty column
between letters, at the row where the chain crosses: R to I (bottom), I to T (top),
T to H (bottom), H to E (top), E to S (bottom), S to H (top). The nearest pad is 1.04 mm away.
- The 107 LED names are hidden on the silkscreen but kept in the board data.
### Placement checks (`tools/check_placement.py`)
| Check | Result |
|-------|--------|
| Exactly 107 LEDs, LED1..LED107 | ✅ |
| Per letter R 18, I 11, T 11, H 17, E 18, S 15, H 17 | ✅ |
| Every LED on the 7 mm grid inside its letter's 5 x 7 pattern | ✅ |
| Chain order matches the schematic nets; LED107 data-out unconnected | ✅ |
| Every LED uses its best rotation (100 face both neighbours, 7 unavoidable turn LEDs) | ✅ |
| No LED overlaps another LED or a mounting-hole keep-out (closest: LED1, 0.61 mm outside after Step 3b) | ✅ |
| Nothing (copper, pad, via, part) in the antenna keep-out or its side clearance | ✅ |
| USB-C front exactly on the edge; no part within 6 mm beside or 12 mm behind it | ✅ |
| LED1 marker and arrows touch no part or board edge; text 1.5 mm, lines 0.22 mm | ✅ |
| KiCad DRC | ✅ 0 violations, 0 footprint errors |
- DRC also lists **359 "unconnected" pads**. This is expected: no copper is routed yet and
most parts are not placed. It is not a violation.
- The checker was tested on a scratch copy with one LED turned the wrong way and one LED
pushed into its neighbour; it reported both.
### Review images (`layout-review/`)
`placement-full-board.png`, `placement-letter-1-R.png` ... `placement-letter-7-H.png`,
`placement-esp32-antenna.png`, `placement-usb-c.png`, `placement-led1-corner.png`.
Colours: orange = copper pads (the mounting holes also show as orange dots: they are holes,
not copper), blue = printed silkscreen, red = data-chain path and screw-head outlines
(drawings only), grey = board outline, rails and notes.
## Step 3b: Clearance review (2026-09-23)
Only the changes needed for the four review questions were made. Letters, the 7 mm grid, the
chain order and the ESP32 / USB-C x positions are unchanged.
### What changed
| Change | Before | After | Why |
|--------|--------|-------|-----|
| Mounting-hole centres | 3.5 mm in from each edge | **3.2 mm** in from each edge | More room between the screw/washer and LED1 |
| Whole LED grid (all 107 LEDs, marker and arrows) | top row at y = 8.0 mm | **y = 7.8 mm** (moved up 0.2 mm, same 7 mm pitch) | More room between the ESP32 and the LED above it |
| Power-net clearance | 0.20 mm for the whole board | **0.25 mm** everywhere, **0.20 mm only inside the USB-C footprint** | Local rule instead of a board-wide change |
### 1. Mounting holes and LED1
| Measurement | Before | Now |
|-------------|--------|-----|
| Hole keep-out (7 mm circle) to LED1's courtyard | 0.30 mm | **0.61 mm** |
| Edge of a 7 mm M3 washer to LED1's body | 0.97 mm | **1.29 mm** |
| Edge of a 7 mm M3 washer to LED1's pads | 0.81 mm | **1.12 mm** |
| Hole edge to board edge | 1.9 mm | **1.6 mm** (= board thickness) |
Tolerances: JLCPCB's pick-and-place accuracy is a few hundredths of a millimetre, and hole
position and board outline tolerances are about ±0.1-0.2 mm (±0.4 mm on a V-cut rail edge).
Even with a worst-case 0.3 mm of stacked error, the washer stays about 1 mm clear of the LED
body and the keep-out stays clear of LED1's courtyard.
**Hardware that fits** (front and back, around each hole):
| Item | Maximum diameter | Examples |
|------|------------------|----------|
| Anything touching the board | **7.0 mm** (the copper keep-out) | M3 washer DIN 125-A (7.0 mm) |
| To stay fully inside the board edge | **6.4 mm** | M3 washer DIN 433 (6.0 mm); screw heads ISO 7380 button (5.7 mm), DIN 912 socket (5.5 mm), ISO 7045 pan (5.6 mm) |
| Hex standoffs | 5.5 mm across flats (6.35 mm across corners) or smaller | standard M3 brass or nylon standoffs |
A 7 mm washer overhangs the board edge by 0.3 mm at the new hole position. That is harmless,
but a DIN 433 washer (6.0 mm) or no washer keeps it flush. Avoid large "wide" washers
(DIN 9021, 9 mm).
### 2. ESP32 and the LED above it (LED18)
| Measurement | Before | Now |
|-------------|--------|-----|
| LED18 body to ESP32 body | 0.9 mm | **1.1 mm** |
| LED18 pads to ESP32 body | 1.2 mm | **1.4 mm** |
| Courtyards (assembly keep-out outlines) | 0.4 mm apart | **0.6 mm apart** (no overlap) |
- JLCPCB's "Minimum Spacing for SMD Components" table recommends 1.0 mm between IC-type
packages (QFN to QFN). Treating the ESP32 module and the LED that way, 1.1 mm now meets it.
- Only LED18 sits above the module; the next LEDs are 7 mm or more away.
- **Repair:** LED18 can still be replaced with a small hot-air nozzle, shielding the module with
heat-resistant (Kapton) tape. The ESP32 itself can be removed without touching any LED
pads.
### 3. Local clearance rule for the USB-C connector
File `rithesh-led-display.kicad_dru` (KiCad custom design rules, loaded automatically):
```
(rule "USB-C J1: 0.20 mm between items inside the connector footprint"
(condition "A.intersectsCourtyard('J1') && B.intersectsCourtyard('J1')")
(constraint clearance (min 0.2mm)))
```
- The **Power** net class is back to **0.25 mm**.
- Only copper inside J1's courtyard (its pins and the short track stubs that will leave them) may
be 0.20 mm apart. 0.20 mm is still twice JLCPCB's 0.10 mm minimum.
- **Tested:** without the rule file, DRC reports exactly the 8 USB-C pin pairs at 0.20 mm; with
it they pass. A test GND track placed 0.22 mm from an LED's +5V pad (away from J1) was still
flagged, so 0.25 mm applies everywhere else.
### 4. The 359 unconnected pads
Every one is a connection that routing (or placing the remaining parts) will make:
| Group | Count | What it is |
|-------|-------|------------|
| +5V between LEDs, ESP32 and USB-C | 106 | Power rail, to be routed |
| GND between parts | 107 | Ground, to be routed / copper fill |
| LED data chain (LED n to LED n+1) plus CC1/CC2 from USB-C to ESP32 | 108 | 106 chain links + 2 CC lines |
| ESP32's own GND pads (22 pads incl. the 9-piece centre pad) | 29 | Tied together by ground copper under the module |
| USB-C's own pads: the two D+ pins, the two D- pins, VBUS pins, GND pins | 4 | Both plug orientations; joined by short tracks |
| USB-C shield tabs (4 x S1) to GND | 5 | Shield to ground copper |
- **No pad is missing a net:** every pad has its schematic net except the intended no-connect
pins (ESP32 spare pins and NC pads, USB-C SBU1/SBU2, LED107's data-out), the four M3 holes and
the USB-C's two plastic locating-peg holes (checked by `tools/check_placement.py`).
- Pads with the same number inside one footprint (ESP32 pad 49's nine pieces, USB-C shield S1)
are shown as "unconnected" by KiCad until copper joins them. This is normal and will be done
during routing.
### Checks after the changes
| Check | Result |
|-------|--------|
| KiCad DRC | ✅ 0 violations, 0 footprint errors (359 unconnected pads, expected) |
| `tools/check_placement.py` | ✅ all passed, including the new hole, ESP32-spacing and pad-net checks |
Close-ups: `layout-review/placement-led1-corner.png`, `placement-esp32-led-spacing.png`,
`placement-usb-c-pins.png` (all other placement images were re-rendered for the 0.2 mm shift).
## Step 4: Parts chosen and all remaining components placed (2026-09-23)
All **264 schematic parts** are on the board, plus the 4 mounting holes. **Nothing is unplaced.**
No copper has been routed yet.
### Parts list (JLCPCB/LCSC numbers, stock checked 2026-09-23)
| Refs | Part | LCSC | Footprint | Qty | Stock | Assembled? |
|------|------|------|-----------|-----|-------|------------|
| J1 | HRO TYPE-C-31-M-12 USB-C, 5 A | C165948 | USB_C_Receptacle_HRO_TYPE-C-31-M-12 | 1 | ~90,000 | yes |
| U1 | USBLC6-2SC6 USB ESD | C7519 | SOT-23-6 | 1 | ~36,000 | yes |
| D1 | SMAJ5.0A surge diode | C2925443 | D_SMA | 1 | ~65,000 | yes |
| U2 | TPS259531DSGR eFuse | C2155674 | WSON-8 2x2 mm | 1 | **~2,000** | yes |
| U3 | TLV76733DRVR 3.3 V regulator | C2848334 | WSON-6 2x2 mm | 1 | ~17,000 | yes |
| U4 | ESP32-C3-MINI-1-N4 | C2838502 | ESP32-C3-MINI-1 (Espressif) | 1 | ~26,000 | yes |
| U5 | SN74AHCT1G125DBVR level shifter (TI) | C7484 | SOT-23-5 | 1 | ~23,000 | yes |
| LED1–LED107 | XL-5050RGBC-2812B (provisional) | C2843785 | LED_XL-5050RGBC-2812B | 107 | ~814,000 | yes |
| SW1–SW3 | XKB TS-1187A button, 5.1 mm | C318884 | SW_Push_1P1T_XKB_TS-1187A | 3 | ~1.7 M | yes |
| C301, C304 | 220 µF 16 V electrolytic | C72496 | CP_Elec_6.3x7.7 | 2 | ~106,000 | yes |
| C302, C303 | 220 µF 16 V (spare spots) | C72496 | CP_Elec_6.3x7.7 | 2 | – | **no (DNP)** |
| C10–C207 (LED + ESP32 + U5) | 100 nF 16 V X7R | C1525 | 0402 | 109 | ~16 M | yes |
| C2 | 100 nF 16 V X7R (eFuse soft-start) | C1525 | 0402 | 1 | ~16 M | yes |
| C1 | 4.7 µF 16 V X5R (USB input) | C19666 | 0603 | 1 | ~1.4 M | yes |
| C7, C8, C9 | 10 µF 25 V X5R | C15850 | 0805 | 3 | ~3.5 M | yes |
| C11 | 1 µF 25 V X5R (ESP32 enable delay) | C52923 | 0402 | 1 | ~4.5 M | yes |
| C13, C14 | USB D+/D- capacitor spots | – | 0402 | 2 | – | **no (DNP)** |
| R1, R2 | 5.1 kΩ 1 % (USB-C CC) | C25905 | 0402 | 2 | ~2.2 M | yes |
| R3 | 750 Ω 1 % (eFuse current limit) | C25132 | 0402 | 1 | ~44,000 | yes |
| R4, R6 | 100 kΩ 1 % | C25741 | 0402 | 2 | ~1.5 M | yes |
| R5 | 39 kΩ 1 % | C25783 | 0402 | 1 | ~106,000 | yes |
| R7–R12 | 10 kΩ 1 % | C25744 | 0402 | 6 | ~1.3 M | yes |
| R13 | 33 Ω (LED data) | C25105 | 0402 | 1 | ~970,000 | yes |
| R14, R15 | 22 Ω (USB D+/D-) | C25092 | 0402 | 2 | ~700,000 | yes |
| R16 | 499 Ω | C4125 | 0402 | 1 | ~262,000 | yes |
| TP1–TP10 | 1.5 mm bare test pads | – | TestPoint_Pad_D1.5mm | 10 | – | no (copper only) |
**Fees and stock**
- **Basic vs extended:** JLCPCB charges about **$3 per "extended" part type** on each order.
The Adom JLCPCB tool can't confirm basic status, so this is an estimate.
- The resistors and small capacitors are the common kind that are usually basic.
- The ICs, USB-C connector, surge diode, LEDs, buttons and 220 µF capacitor are probably
extended: about **8–12 types, so roughly $24–36**.
- Confirm the exact amount on the JLCPCB quote before ordering.
- **Uncertain stock:** only the **TPS259531 eFuse (~2,000)** is low. That is fine for a
prototype batch, but check it again on the day you order. Every other part has 17,000 or more.
- **Not assembled:** C13, C14, C302 and C303 are marked "exclude from BOM and placement
files", so JLCPCB leaves those spots empty. The test pads are bare copper. KiCad 7 has no
separate "DNP" flag on the board. "DNP" is also printed above C302 and C303.
### Where each group sits (all on the front, along the bottom strip below the letters)
| Group | Position | Why there |
|-------|----------|-----------|
| USB-C protection: U1, D1, C1, R1/R2 | Just above and beside J1 (x 86–100) | ESD and surge parts 7.7–10 mm from the connector pins, before anything else |
| eFuse U2 + R3–R6, C2 | x 104–112, right of D1 | Each support part 2.9–4.1 mm from its U2 pin |
| FLT / ILM test pads (TP7, TP8), 5V_OUT (TP2), GND (TP4) | x 113–119 | Next to the eFuse they measure |
| Regulator U3 + C7, C8 | x 51–58, just right of the ESP32 | 7.7 mm from the ESP32 3V3 pin; capacitors 1.8–3.2 mm from U3 |
| ESP32 capacitors C9–C11, R7, R10, 3V3 pad (TP3) | Beside the ESP32's right edge | 2.4–3.4 mm from the pins they serve |
| USB resistors R14/R15, DNP caps C13/C14, strap resistors R8/R9/R11/R16 | Left of the ESP32 (x 28–32) | Next to the ESP32 pins they connect to |
| Buttons SW1 RESET, SW2 BOOT, SW3 ON/OFF | x 64, 72, 80 | Easy to reach, with labels printed underneath (1.0 mm text) |
| UART pads RX, TX, GND (TP9, TP10, TP5) | Bottom-left corner | Labelled; room for 3 probe clips |
| Level shifter U5 + R12, R13 (33 Ω), C12, LED_DIN pad (TP6) | Left edge, beside LED1 | U5 → R13 4.0 mm, R13 → LED1 3.8 mm: a short, clean 5 V data path |
| 220 µF bulk | C301 x 13.5 (fitted), C302 x 140 (DNP), C303 x 212 (DNP), C304 x 283 (fitted) | Spread along the LED rail from one end to the other |
The antenna area and its two 15 mm side clearances stay empty. The checker confirms no pad
or part is inside them.
### How 107 LED capacitors fit in the 7 mm grid
- Each LED is 5 mm wide on a 7 mm grid, so there is a **2 mm gap** between neighbouring LEDs.
After each LED's courtyard (its "keep clear" outline) is counted, the gap is 0.8 mm side to side
and 1.4 mm top to bottom.
- A 100 nF capacitor in 0402 size is only **1.0 × 0.5 mm** (its courtyard is about 1.9 × 1.0 mm).
It fits lengthwise in a 1.4 mm gap, or on the outer edge of a letter where there is no
neighbour.
- `tools/place_parts.py` tries the spots beside each LED's two power pads, starting with the
closest. It takes the first spot that doesn't touch:
- another part's courtyard
- a hole keep-out
- the antenna areas
- printed markings
- the LED pin-1 dots
- The capacitor is turned so its **+5V end faces the LED's VDD pad**.
- Result: all 107 fit. The +5V pad is on average **2.0 mm** from the LED's VDD pad. The worst is
6.0 mm (LED97, where the neighbouring LEDs block the closer spots).
- **Assembly spacing:** no courtyard touches another. Each courtyard already includes a
0.25 mm margin around the part, so the pick-and-place machine has room. JLCPCB's own DFM
check at quote time is the final word.
### Polarity marks (checked against the nets)
- D1: the cathode band side (pad 1) is on **VBUS**.
- 220 µF capacitors: the "+" corner (pad 1) is on **+5V** for all four.
- U1, U2, U3, U5, U4 (ESP32) and every LED: the pin-1 dot or arrow is beside pin 1. U5 pin 1
(OE) goes to GND, which keeps it always on.
### Checks after placement
| Check | Result |
|-------|--------|
| KiCad DRC | ✅ **0 violations, 0 footprint errors** |
| `tools/check_placement.py` (with `NETLIST=` for the new section 8) | ✅ all passed: 264/264 parts placed, all distances above, labels, test-pad spacing (closest 3.5 mm), bulk positions, DNP exclusion, antenna clear, holes clear (closest TP6, 0.34 mm outside the keep-out) |
| ERC (schematic changed: LCSC fields, capacitor values) | ✅ 0 errors, 0 warnings; `schematic.pdf` re-exported |
**Unconnected pads (normal before routing):**
- The DRC report says **499** and KiCad's connection count says **678**. The two numbers
measure in slightly different ways: the report doesn't list the LED data-chain links as
separate items.
- A count by hand, if nothing is joined yet, gives about 682:
- +5V 224, GND 287, LED data chain 100, +3V3 12, VBUS 10, other signals 49
- The extra 4 are USB-C pins in the same spot that KiCad counts once.
- **Every one is a link that routing will make. No pad is missing a net.**
### Review images (`layout-review/`)
- `placement-full-board.png`
- Close-ups:
- `parts-usb-power.png`, `parts-esp32-regulator.png`, `parts-buttons.png`
- `parts-level-shifter.png`, `parts-led-capacitors.png` (letter E)
- `parts-bulk-left.png` (C301 + UART pads), `parts-bulk-right.png` (C302 DNP),
`parts-bulk-far-right.png` (C304)
## Step 4b: Placement fixes before routing (2026-09-23)
| Request | What changed | Result |
|---------|--------------|--------|
| 1. USB ESD chip closer | U1 turned 270° and placed right above the USB-C data pins. D- enters pin 4 and leaves pin 3; D+ enters pin 6 and leaves pin 1 (straight through the chip, no branches). | U1's D+/D- pads are **1.58 mm** from J1's D+/D- pads (about 2 mm of track). The old "7.7 mm" was measured from J1's centre point, not pad to pad. It can't go closer: the VBUS via for U1's pin 5 has to sit between U1 and the connector. |
| 2. TP6 away from the screw | TP6 moved down 1 mm; R13, U5, C12, R12 moved down with it. | Closest test pad is now **1.34 mm** outside the screw/washer keep-out (was 0.34 mm). |
| 3. eFuse datasheet check | TI SLVSE57 section 11.1: the IN capacitor goes closest to IN/GND. R<sub>ILM</sub>, C<sub>dVdT</sub> and the EN/UVLO resistors go next to their pins, with their other end straight to the chip's GND pin. The TVS goes close to the device it protects. The exposed pad must be tied to GND (vias optional). **The old 2.9–4.1 mm spacing was looser than recommended, so the parts were moved.** | Pad-to-pad gaps: C1 (IN cap) 0.83 mm, C2 (dVdt) 0.77 mm, R5 (EN) 0.86 mm, R4 0.45 mm from R5, R3 (ILM) 1.18 mm, D1 (TVS) 2.65 mm from the IN pins. R6 (FLT pull-up, not listed by TI) 2.42 mm. |
| 4. LED capacitors > 3 mm | For LED97, LED51 and LED28, the neighbouring LEDs (one of them turned 90°) leave only 1.07–1.08 mm between courtyards. The 0.94 mm capacitor courtyard fits there, but my 0.1 mm safety margin had rejected it. A "tight" spot (courtyards 0.07–0.12 mm apart, part bodies about 0.5 mm apart) is now allowed only for those three. | LED97 6.0 → 1.9 mm, LED51 5.1 → 1.4 mm, LED28 5.1 → 1.9 mm. **All 107 are now ≤ 2.0 mm** (average 1.8 mm). |
Other moves made for routing:
- Buttons SW1–SW3 moved to x = 62.3 / 70.6 / 78.1 so two signal tracks fit between SW1 and SW2, and wider lanes fit beside the USB-C connector.
- The BOOT, IO8 and ON/OFF pull-ups (R8, R11, R9) moved next to the tracks they pull up.
- C9 (10 µF) is now 6.3 mm from the ESP32 3V3 pin, so the USB pair can pass below it. The 100 nF (C10) is still 2.4 mm from the pin.
- CC resistors R1/R2 moved beside U1. TP1/TP7/TP8 moved next to the eFuse.
Checks: placement checker ✅ all passed; DRC ✅ 0 violations, 0 footprint errors (499 unconnected, nothing routed yet).
## Step 5: Routing (2026-09-24)
**Result:** every connection is routed. KiCad DRC shows **0 violations, 0 unconnected pads, 0 footprint
errors**. The placement checker, ERC (0/0), the connection checker and the pin audit all pass.
### How the board is built up
| Layer | What is on it |
|-------|---------------|
| **Back (B.Cu)** | **Solid ground plane** over the whole board except the antenna area and its 15 mm side clearances. Only eight short planned jumps cut it (table below). None are under the LED area or near the antenna. |
| **Front (F.Cu)** | All parts and signal tracks. **+5V copper fill** over the whole LED area and the bottom strip right of the eFuse. **Ground fill** in the USB/ESP32 strip. |
The routing was done in stages. Each stage is saved and every step can be re-run with `tools/route_board.py`:
1. `pre`: critical copper by hand, each track checked against all other copper:
- the USB pair and USB-C fan-out
- the eFuse and regulator pins
- the LED data line
- the ESP32 / button / USB-C strip lanes
- a ground via at every ground pad
- a direct +5V track from every LED to its capacitor
2. `auto`: Freerouting 1.9 routed the LED data chain, the UART lines, IO2 and the FLT/ILM test pads. Its output was checked: all 106 chain links are on the front layer with no vias, the worst at 1.36× the straight distance.
3. `import`: those routes are imported. Nets that were routed by hand are skipped, so no extra stubs are added.
4. `finish`: the ILM test-pad link is moved to a front-only path. Freerouting had used a back-layer jump there.
5. `zones`: copper fills and planes are poured, with floating copper removed.
An earlier Freerouting attempt on the whole strip used 47 mm (CC1) and 41 mm (BOOT) of back-layer track. It was rejected and removed before this final routing.
### Placement tweaks made for clean routing
These keep the LED grid, letters, holes, ESP32 and USB-C exactly where they were.
- **Button order is now RESET, ON/OFF, BOOT** (ON/OFF and BOOT swapped), 9 mm apart, 1.2 mm lower. The
ESP32's top-edge pins are in the order BOOT, IO8, ON/OFF, CC2, CC1. With this button order the tracks can end one after
another with no crossings.
- Pull-ups R11 (ON/OFF) and R9 (IO8) sit in the gaps between the buttons, and R8 (BOOT) sits above the BOOT button.
3.3 V reaches them on a track running under the buttons.
- R7 was turned 180° and C11 moved 0.6 mm down, so 3.3 V reaches R7 without crossing EN.
- The J1 label was moved 2.2 mm down (it touched the BOOT label).
### The obstruction that blocked CC2 (investigated)
CC2 has to leave USB-C pin B5 northwards between the D+ track and the VBUS track at pin A9. The first VBUS
track there was 0.8 mm wide, and its rounded end reached x = 92.05 mm. That left a 0.75 mm gap, while a 0.25 mm track needs
0.20 mm on one side plus 0.25 mm on the other (0.70 mm) with no margin at all. Freerouting had also put a VBUS via on
that corner. Fix: the VBUS track starts 0.5 mm wide at x = 92.45 mm and only widens after it has passed the
connector's ground pad. CC2 now passes with 0.255 mm and 0.225–0.275 mm on its two sides.
### USB D+/D-
| Item | Value |
|------|-------|
| Path | J1 → U1 (about 2 mm, straight in, flow-through pins 4→3 and 6→1) → west above the buttons → down beside J1 → west below the buttons → **under the ESP32 on the back layer** → up beside the module → R14/R15 (22 Ω) → ESP32 pins 26/27 |
| Why under the module | The ESP32's USB pins are on its left side and the USB-C is to its right. Passing over the top would cross six other ESP32 signals in a 1.7 mm gap under LED18. |
| Vias | D+ 2, D- 2 (the module crossing) + 2 for D- at the connector. The A7→B7 join sits under the connector body, as is normal for this 16-pin USB-C. |
| Track | 0.30 mm with 0.20 mm gap, routed side by side the whole way. The front parts are over the solid back plane, the back part under the module's front ground. |
| Length | D+ 79.9 mm, D- 81.5 mm including the unused-orientation stubs (difference well under 1 ns, far inside USB 2.0 Full-Speed limits) |
| Note | 2-layer 1.6 mm boards cannot reach 90 Ω differential impedance. This does not matter at 12 Mbit/s over a short track. |
### Back-layer jumps (all deliberate, all short)
| Net | Back-layer length | Why |
|-----|-------------------|-----|
| USB D+ / D- | 22 / 23 mm | Under the ESP32 (see above). The only long one; it sits under the module's ground, not under LEDs. |
| CC1 | 10.8 mm (2 jumps) | CC1 and CC2 must cross the BOOT/IO8/ON-OFF lines. Here CC1's second jump crosses under the USB-C fan-out, because its pin sits inside the USB pair. |
| VBUS (left pad) | 9.0 mm | The second VBUS pad of USB-C sits inside the USB pair. It joins U1's VBUS pin and the main VBUS track. |
| +5V (regulator feed) | 7.9 mm | +5V comes from the fill above the lanes, down to U3 / C7. |
| LED data (3.3 V) | 7.1 mm | ESP32 pin 16 is boxed in by the button lines. It jumps once and runs to the level shifter at the left edge. |
| CC2 | 3.5 mm | Same crossing as CC1 at the module edge. |
| +3V3 | 3.5 mm | 3.3 V to the eFuse FLT pull-up R6 crosses the CC lines once. |
Total non-ground back-layer copper: **87 mm**, all in the bottom-left strip (x 29–96 mm, the USB-C/ESP32 area). Vias: 287 in total:
- 264 ground vias
- 9 thermal vias in the ESP32 pad, 2 in each of the eFuse and regulator pads (TI layout examples)
- 21 signal vias
### LED capacitors
All 107 capacitors have a **direct +5V track** to their LED's VDD pad (about 1.8 mm on average). For ground, each capacitor pad and each LED
ground pad has **its own via straight into the solid ground plane** (the LED's via sits under its body). That gives a shorter,
lower-inductance loop than a surface track around the LED would, because the LED's ground pad is on the far corner from its VDD pad.
### Voltage drop and current capacity (`tools/power_analysis.py`)
The filled copper is solved as a resistor network (1 oz copper, 0.49 mΩ per square), with the current spread evenly over all LEDs:
| Total LED current | Worst +5V drop | Worst GND rise | **Worst total (LED96, far end)** |
|-------------------|----------------|----------------|----------------------------------|
| 1.88 A (WLED limit) | 8 mV | 2 mV | **9 mV** (11 mV with warm copper) |
| 2.9 A (eFuse maximum) | 12 mV | 3 mV | **14 mV** (17 mV warm) |
Most of this drop is in the eFuse's own output pin (0.25 mm wide) and the few millimetres next to it. The 300 mm +5V fill and
the ground plane add only about 1–3 mV. That is under 0.3 % of 5 V, so every LED gets essentially the same voltage.
The larger drops are before the board: the eFuse switch (34 mΩ, about 64 mV at 1.88 A) and the USB cable.
Current capacity of the narrowest power copper (IPC-2221, outer 1 oz, long-track rule, so short tracks run cooler):
| Conductor | Width × length | ≈ 10 °C rise | ≈ 20 °C rise |
|-----------|----------------|--------------|--------------|
| VBUS main (J1 → TVS) | 1.2 mm × 7 mm (0.5–0.8 mm for the first 1.8 mm at the connector) | 2.7 A | 3.7 A |
| VBUS left pad jump | 0.5 mm × 7.5 mm (carries part of the current) | 1.4 A | 2.0 A |
| VBUS into eFuse IN (2 pins) | 0.6 mm × 1.5 mm | 1.7 A | 2.2 A |
| eFuse OUT (the chip's own pin width) | 0.25 mm × 1.2 mm | 0.9 A | 1.2 A (very short, heat sinks into the chip and wide copper) |
| 5 V out to fill | 0.8 mm × 3 mm | 2.0 A | 2.8 A |
| +5V fill and ground plane | 16,600 mm² / 20,250 mm² | far above 3 A | |
At the design maximum (2.2 A including the ESP32) the rise is modest. At the eFuse's 2.9 A current limit
the narrow parts next to the connector and the eFuse pin would get warm, but only briefly, until the eFuse limits the current.
### Remaining warnings and uncertainties
- The button order changed to RESET, ON/OFF, BOOT (labels moved with the buttons). Please confirm this is fine.
- The eight back-layer jumps above are necessary with the approved ESP32 / USB-C positions. A future revision
with the USB-C to the left of the ESP32 would remove the module crossing.
- Freerouting chose the LED chain, UART, IO2 and FLT test-pad tracks. They are DRC-clean and direct, but they were not hand-drawn.
- USB impedance is not controlled (not possible on a 2-layer 1.6 mm board). This is acceptable for Full-Speed USB.
- The voltage-drop figures assume the current is spread evenly over the LEDs. With one bright letter at the far end, the drop
there is still only tens of millivolts.
- JLCPCB's own DFM check at quote time is still to be done. That includes the three "tight" LED-capacitor spots and the via-in-pad thermal vias under the ESP32, eFuse and regulator.
- Tools used only in the cloud container: OpenJDK 21, Freerouting 1.9.0, Shapely, numpy, scipy. Nothing was installed on the Mac.
### Review images (`layout-review/`)
- `routed-full-board.png` (with fills), `routed-full-tracks.png` (fills hidden), `routed-front-copper.png`, `routed-back-copper.png`
- Close-ups (fills hidden):
- `routed-usb.png`, `routed-usb-pair.png`
- `routed-power.png`, `routed-esp32.png`, `routed-strip.png`
- `routed-led-rail.png`, `routed-far-end.png`, `routed-led1-shifter.png`
- The older `placement-*` and `parts-*` images show the placement **before** the button swap and are superseded by these.
## Step 5b: Final checks before approval (2026-09-24)
Approved by the user: button order RESET, ON/OFF, BOOT; the small R/C and J1-label moves (electrical
connections unchanged, confirmed by the connection checker and the pin audit).
### 1. USB routing
| Item | Result |
|------|--------|
| Vias | **D+ 2, D- 4.** Both lines take the same 2 vias to pass under the ESP32. D- has 2 more at the USB-C connector: this 16-pin connector interleaves D-/D+/D-/D+ pads, so one of the two D- pads (A7) must cross over to the other (B7). The crossover is under the connector body and is only in the signal path for one plug orientation. |
| Can they be symmetrical? | Only by adding 2 unnecessary vias to D+. Each via is about 0.3 pF / 0.5 nH, a few picoseconds, which is irrelevant at 12 Mbit/s, so this was not done. |
| Ground return at layer changes | Ground stitching vias added beside every USB layer change. At the ESP32 up-point and at the connector crossover, each USB via has a ground via 0.85–0.92 mm away. At the ESP32 dive-point, D-'s via has one 0.87 mm away; D+'s nearest is 1.73 mm (no free spot closer: C10, the module pins and the back-layer pair fill the area). The front ground fill and back plane are continuous around both. Along the whole run the pair has solid ground on the other layer. |
| Differential impedance (`tools/usb_impedance.py`, 2D field solve) | Cross-section: JLCPCB 2-layer 1.6 mm, FR-4 1.53 mm (er 4.5), 1 oz copper, ~20 µm solder mask. Traces 0.30 mm, gap 0.20 mm. **About 113 Ω differential** where the ground fill runs 0.25 mm beside the pair (most of the route), about 122 Ω over the plane alone (common mode 57–93 Ω). Nominal is 90 Ω; hitting it would need about 1 mm wide traces, which do not fit the connector fan-out. At 12 Mbit/s the 8 cm route is electrically short (about 0.45 ns against 4–20 ns edges), so the mismatch does not matter. |
| Length difference | D+ 83.0 mm, D- 85.2 mm including the MCU side (the extra D- length is mostly the connector crossover stub). A 1.6–2.2 mm difference is about 10–12 ps, against USB Full-Speed edges of 4–20 ns and an 83 ns bit time. **Acceptable.** |
### 2. Vias in exposed pads: changed
The previous design had 13 open vias inside exposed pads (ESP32 9, eFuse 2, regulator 2). The pads have a solder-mask
opening, so those holes would have been open and could pull solder away during reflow. They are replaced by
**ordinary tented vias beside the pads**:
- **ESP32:** 6 vias under the module in the free bands left and right of its centre pad, each with a short track to the pad. The ground fill under the module also joins them.
- **eFuse:** 2 vias just outside the pad ends, with short tracks.
- **Regulator:** 1 via above its pad, plus its two ground pins and the fill.
The same scan found that many small ground vias (107 LEDs, some capacitors, D1, SW2, U5) had holes just touching a pad corner.
Every via now keeps its **drilled hole at least 0.1 mm clear of any pad's mask opening** (via centre ≥ 0.25 mm from the pad).
Checked on the final board: 287 vias, 0 holes inside a pad, closest hole edge 0.105 mm from a pad opening.
| Via | Value |
|-----|-------|
| Drill / pad | 0.30 mm / 0.60 mm (JLCPCB standard, no extra cost) |
| Solder mask | Tented (covered). KiCad plot option "plot vias on mask" is off, and JLCPCB's default for 2-layer boards is tented vias |
| Special process | None needed: no via-in-pad filling or capping |
### 3. Power entry, section by section (`python3 tools/power_analysis.py sections`)
Input current 2.2 A is the design maximum (LEDs at the WLED limit plus the ESP32); 2.9 A is the eFuse's highest possible current limit, held only
briefly. Voltage drop is from 1 oz copper at 0.49 mΩ/square. "IPC" is the IPC-2221 long-track rule. "Short-neck" is a conduction estimate for pieces
under 5 mm long that are held by pads or wide copper at both ends. The IPC rule greatly overstates heating for those.
| Section (width × length) | Current at 2.2 A / 2.9 A | Drop 2.2 / 2.9 A | Heat 2.9 A | Rise at 2.9 A |
|--------------------------|--------------------------|------------------|------------|---------------|
| VBUS right pad stub (0.5 × 1.55 mm) | 1.9 / 2.5 A (58–87 % of the input) | 2.9 / 3.8 mV | 10 mW | 0.3 °C short-neck (IPC 35 °C) |
| VBUS left pad stub (0.3 × 0.75 mm) | 0.9 / 1.2 A | 1.1 / 1.5 mV | 2 mW | <0.1 °C |
| VBUS left, back-layer link (0.6 × 9.1 mm) | 0.9 / 1.2 A | 6.8 / 9.0 mV | 11 mW | 4.9 °C (IPC) |
| VBUS main, 0.8 mm part (0.8 × 1.1 mm) | 2.2 / 2.9 A | 1.5 / 2.0 mV | 6 mW | 0.1 °C |
| VBUS main to TVS (1.2 × 9.4 mm) | 2.2 / 2.9 A | 8.4 / 11.1 mV | 32 mW | 6.1 / 11.5 °C (IPC) |
| TVS → input capacitor (0.8 × 1.6 mm) | 2.2 / 2.9 A | 2.2 / 2.8 mV | 8 mW | 0.2 °C |
| Input capacitor → eFuse IN pins (0.6 × 1.45 mm) | 2.2 / 2.9 A | 2.6 / 3.4 mV | 10 mW | 0.2 °C |
| eFuse OUT pin neck (0.25 × 1.2 mm, the pin's own width) | 2.2 / 2.9 A | 5.2 / 6.8 mV | 20 mW | 0.5 / 0.9 °C short-neck |
| 5 V out → +5V fill (1.2 × 3.05 mm, widened from 0.8) | 2.2 / 2.9 A | 2.7 / 3.6 mV | 11 mW | 0.2 °C |
| eFuse switch itself (34 mΩ typ., RθJA 65.6 °C/W) | 2.2 / 2.9 A | 75 / 99 mV | 286 mW | chip +11 / +19 °C |
- **USB-C VBUS contacts:** the connector is rated 5 A over its four VBUS contacts, so 2.5 A per pad pair. The right pad carries
1.9 A at 2.2 A (within rating) and up to 2.5 A at the brief 2.9 A limit (at rating).
- **Widened in this step:** 5 V out to the fill (0.8 → 1.2 mm) and the left-VBUS back link (0.5 → 0.6 mm). The remaining narrow parts
are set by pin widths (eFuse pins, USB-C pads) or by clearance to neighbouring pads, and they run cool because they are short.
- **Board copper total:** VBUS path about 18 mV and 5 V output about 8 mV at 2.2 A. The +5V fill and ground plane add 9–14 mV to the worst LED.
### 4. Copper-fill and assembly checks
- All 107 LED +5V pads and all 107 capacitor +5V pads touch the +5V fill **and** have their direct LED–capacitor track.
All 214 LED/capacitor ground pads have a track to their own ground via.
- **Thermal reliefs** (0.30 mm gap, 0.50 mm spokes) are now used for all pads in all fills, so small 0402/0603 parts heat evenly during reflow
(less risk of tombstoning). **Solid connections** are kept only for the ESP32 module's 30 ground pads and the eFuse/regulator exposed
pads, which need full copper for heat. Rule file: a pad may resolve with one spoke, because every such pad also has its own via or track.
- Antenna keep-out: no copper, fill, via, track or part on either layer. Checked with exact shapes and the actual filled copper.
- Button labels vs connections after the swap: RESET = SW1 (EN), ON/OFF = SW3 (BTN_ONOFF), BOOT = SW2 (BOOT). All match.
### 5. Visual review
- 3D views (KiCad 3D viewer; models for this render only, in the cloud container):
- `3d-front.png`, `3d-back.png`, `3d-front-strip.png`, `3d-front-angled.png`
- Stand-ins and gaps:
- The XL-5050 LED is drawn with KiCad's WS2812B 5050 model (same size and pin layout).
- No 3D model exists for the XKB TS-1187A buttons or the HRO USB-C connector, so those show as footprint outlines only.
- The DNP capacitors C302/C303 are drawn in the render but will not be fitted.
- Polarity and pin 1: D1's cathode band on VBUS, "+" on the +5V pad of all four 220 µF capacitors, and pin-1 dots on U1–U5, J1 and every LED
all match the nets. KiCad's silkscreen checks (overlap, silk on pads) are part of the DRC: 0 issues. The DNP labels sit above C302/C303,
and the test-pad labels read 5V_IN, 5V_OUT, 3V3, GND, LED_DIN, FLT, ILM, RX, TX.
- The outdated `placement-*` and `parts-*` images (old button order) were **moved out of the project** to a cloud scratch archive, so they
cannot be published by mistake.
### Checks after all corrections
| Check | Result |
|-------|--------|
| KiCad DRC | ✅ 0 violations, 0 unconnected pads, 0 footprint errors |
| ERC | ✅ 0 errors, 0 warnings |
| Placement checker | ✅ all passed (including exact antenna-area check with fills) |
| Connection checker | ✅ all expected connections, LED chain 1–107 continuous |
| Pin audit | ✅ passed |
| Voltage drop (fills) | worst LED 9 mV at 1.88 A, 14 mV at 2.9 A |
| Freerouting (final run) | LED chain, UART, IO2, FLT test pad: front layer only, no vias |
## Step 6: Approval and manufacturing package (2026-09-24)
**Approved for a prototype** by the user on 2026-09-24. Accepted prototype risks, in addition to requirements.md risks 1–5:
- USB differential impedance about 113–122 Ω (see Step 5b)
- one USB-C VBUS pad pair at its 2.5 A contact rating only during the eFuse's brief 2.9 A limit
**Required before ordering** (not done yet):
1. The XL LED timing pre-check passes (`firmware/README.md`, section 1).
2. JLCPCB's DFM check, 3D placement preview (rotations / pin 1 of every part type), stock and final price are reviewed.
### Manufacturing package (`manufacturing/RITHESH-v1-PROTOTYPE/`, made by `tools/make_manufacturing.py`)
| File | Content |
|------|---------|
| `RITHESH-v1-PROTOTYPE-DO-NOT-ORDER-gerbers.zip` | The file JLCPCB asks for: 9 Gerber layers, PTH + NPTH drills, Gerber job file, do-not-order note |
| `gerber/` | Same files unzipped, plus drill maps (PDF) |
| `assembly/BOM-JLCPCB.csv` | 27 lines, 250 parts, all with LCSC numbers; DNP parts and test pads left out |
| `assembly/BOM-full.csv` | All 264 parts, with DNP (C13, C14, C302, C303) and bare test pads marked |
| `assembly/CPL-JLCPCB.csv` | 250 placements: position (mm, from the bottom-left board corner), side (all Top), rotation |
| `assembly/assembly-front.pdf`, `assembly-back.pdf` | Assembly drawings (outline, fab layer with references, silkscreen) |
| `FABRICATION-NOTES.md` | Board options (300 × 70 mm, 2 layers, 1.6 mm, 1 oz, tented vias), holes, assembly notes |
**Verification (2026-09-24):**
- **Gerber viewer:** every layer, drill file and the outline were opened in gerbv (installed in the cloud workspace) and checked by eye:
- copper matches the design, with the back-layer plane and the planned short jumps
- mask openings only on pads (vias tented)
- silkscreen labels readable
- the antenna area is empty
- the outline is 300 × 70 mm with rounded corners
- **Drills:**
- plated file: 287 vias of 0.30 mm + 4 plated USB-C shield slots
- non-plated file: 4 × 3.2 mm mounting holes + 2 × 0.65 mm USB-C locating pegs
- **BOM and CPL vs the PCB:** 264 footprints compared by script. Every fitted part appears once in both, and values, footprints,
positions and rotations match the board exactly. **No mismatches.**
- The board's drill/place origin was set to the bottom-left corner, and the title block now shows the prototype status. These are
metadata only; DRC was re-run afterwards: 0 / 0 / 0.