Study: standard tiles, cheap converters, cheap pins (2026-11)


A record of the study as it was run. "Today" here is the October 2026 design it started from (48 boards, 1,273
contacts). The design it led to has 66 tiles of 9 designs and 1,118 contacts (out/pcb/cap, boards).
Can one exocortex cost hundreds instead of $11,784? The October design has 48 contact boards and 16 controllers,
every one a different polygon (66 PCB designs), one ADS131M08 per eight contacts and a Mill-Max spring pin on every
contact. This study priced the alternatives with the repo's own JLC fee model (exo/cost.py, out/sourcing/fees.json)
and live JLC price tiers, on the real headform (exo/head.py), and picked the layout the redesign is built on.
The interactive page with every layout in 3D is tile_study.html.
Where the $11,784 went
| JLC setup fees: 66 designs × $51.12 | $3,374 |
| 358 ADS131M08 (two sets: JLC assembles at least 2 of every panel) | $2,372 |
| 2,610 Mill-Max 0919 spring pins | $2,278 |
| bare boards, stencils, loading, joints, other fees | $1,922 |
| optics, op-amps, everything else | $1,838 |
The bare boards were only ~$640. The money went on design count, the converter, the pin, and building two of everything.
The cost levers (from the ChatGPT discussion, checked against our designs)
- Few board designs. Setup is per design ($51.12 double-sided), so 66 → ~10 designs saves ~$2,900 alone.
- One order, not two helmets. JLC's PCBA minimum is 2 of a panel. Lay half a helmet on a customer panel (every design, plus a spare pair of each) and have it assembled twice: two panels = one helmet, not two.
- A cheap converter. CH32V203G6U6 (12-bit SAR, ~$0.5 at volume, 10 inputs) per ≤ 9 contacts instead of the ADS131M08 ($6.62). Quantization is fixed by gain ahead of it: TLV333 zero-drift op-amp per contact at gain 200, its feedback returned to a buffered REF (so electrode DC offset is referred to REF, not amplified to the rail), and the ADC oversampled ~200× to 500 SPS. Referred to the input, one 12-bit LSB at 3.3 V is 4.0 µV; ideal quantization noise is 1.2 µV rms per sample and ~0.1 µV after averaging 200 (~0.6 µV with a realistic 2 LSB rms of converter noise), against the TLV333's own ~0.55 µV rms (55 nV/√Hz over 100 Hz). (CH32V003 10-bit at $0.15 would cost ~3 dB more; not chosen.)
- A cheap pin. One commodity ball-tip SMD pogo pin (KH-205580-DZ, JLC C530677, ~$0.10 at volume, placed by JLC) instead of the Mill-Max ($0.87 + hand placement). A rigid gold post is ~$0.02 but only works where the board-to-scalp spread is under ~0.5 mm, i.e. tiles smaller than ~15 mm; at our 25-30 mm tiles the spread reaches 1.3 mm and a spring is needed.
- No controller boards. Each tile is one board: pins, op-amps, its own CH32V203s, an LDO and two 7-way chain connectors (VIN, GND, REF, CLK, SYNC, RX, TX). Tiles daisy-chain over UART into the hub's 16 ports; the shell holds each tile's pose.
- Lower contact force. The commodity pin's spring is lighter than the Mill-Max's 25-85 gf; over ~1,100 contacts the summed force is what matters for comfort. To be measured.
Layouts tried (one helmet, all in, one JLC order)
| layout | designs (+ hub, camera) | boards | contacts | worst pin spread | pin | one helmet |
|---|---|---|---|---|---|---|
| today: 48 bespoke boards + 16 controllers | 66 | 48 | 1,273 | 2.6 mm | Mill-Max | $11,784 |
| one 3×3 square | 3 | 136 | 1,224 | 0.43 | rigid post | $1,313 |
| one 4×4 square, 5.0 mm pitch | 3 | 84 | 1,344 | 0.82 | pogo | $1,464 |
| one 7-pin hexagon | 3 | 189 | 1,323 | 0.22 | rigid post | $1,457 |
| one 19-pin hexagon | 3 | 70 | 1,330 | 0.88 | pogo | $1,428 |
| one 37-pin hexagon | 3 | 35 | 1,295 | 1.97 | pogo | $1,455 |
| trapezoid cap: 5 rings of ~32 mm trapezoids | 12 | 66 | 1,059 | 1.31 | pogo | $2,086 |
| trapezoid cap: 3 rings + hand-laid top | 9 | 66 | 1,124 | 1.31 | pogo | $1,851 |
| trapezoid cap: 3 rings + territory top (chosen) | 11 | 66 | 1,119 | 1.31 | pogo | $2,066 |
Single-shape tilings (squares, hexagons) are the cheapest on paper, but they leave a ragged edge at the cuff and gaps between neighbours on the curved head. The trapezoid cap is the shape in the launch video: rings of trapezoids parallel to the cuff, edge to edge, closed by a top. It is chosen for coverage of the cuff line and a clean, buildable shell, at ~$640 more than the cheapest hexagon tiling. Every board in it is at least 0.8 mm from its neighbours in 3D, and every pin is at least 2.4 mm from its board's edge.
How the chosen cap is made
- Rings 1-3 (
cap3.py,cap5.py): a distance field from the cuff (Dijkstra on a θ/φ grid of the headform) gives level curves parallel to the cuff; the seam is rolled to the front. Each ring is a band one board high, divided at equal arc length into facets ~32 mm wide; each facet's top corners are the nearest points on the next level. One trapezoid per ring (the largest that fits most facets) plus a steeper end trapezoid for the facets at the front and back where the rings bend hardest. Each board is checked to lie inside its facet less the gap. - The top (
terr.py): the opening above ring 3 is flattened (azimuthal equidistant map about its centre; the top is nearly flat), made symmetric left-right and under a half turn, then cut by territory lines: two long rows of cells down the middle, a fanned row of four cells along each side, and an end cell at each corner. Each cell, less the gap, is one board. Edge cells are trimmed to their own mirror line, so a cell and its mirror twin take the same PCB (a PCB can't be flipped). The middle double strip is stretched 4.5 % and centred so both its ends sit ~1.2 mm from ring 3. ~2,000 line placements were searched (tsearch*.py); the lines are drawn 1.2 mm apart on the map to get 0.8 mm in 3D. - Pins per design: laid out in the board's own plane, in the outline common to every copy of that design (the copies are aligned to maximise it), on a 5.3 mm hexagonal or square lattice searched over offset and rotation.
Dead ends worth knowing: equal-angle (φ) division of rings and row-quantised bands lose pins; meridian-distance levels give a crown that is too big; the first automatic caps overlapped at the front and back of the top rings (44-48 pairs) until facets got closest-point tops and end shapes; a hand-laid top got 1,124 contacts only by letting gaps fall to 0.19 mm; laying pins out on the flattened map instead of each board's plane overstated contacts by ~20 %.
Files
Run any script from results/ (cd results && uv run python ../gen.py): inputs and outputs live there.
| file | what |
|---|---|
jlcs.py, tiers.py |
JLC part search and live price tiers → results/tiers.json |
costs.py, combined.py, tcost.py |
per-layout BOM and fees; the one-order-two-panels pricing → results/combined.json |
tiles*.py, shapes.py |
square and hexagon tilings → results/lay_*.json |
rings*.py |
early ring studies (gravity-stacked, shared shapes) → results/ring_*.json |
cap.py, cap2.py, cap3.py, cap4.py, cap5.py, collide.py |
the trapezoid caps → results/cap_*.json |
top_*.py, spec_*.py, hand_to_cap.py |
the hand-laid top (2D map tool, lift, optimiser) |
terr.py, terr_to_cap.py, tsearch*.py |
the territory top (chosen) → results/cap_terr_r3.json |
gen.py, template.html → tile_study.html |
the interactive page |
figures/ |
2D maps and 3D checks of the tops |
The redesign itself (exo/cap.py onward) re-implements the chosen layout as part of the build; this folder is the
record of how it was found.