Builder guide
From an empty bench to a helmet on a head. It follows the design docs; the docs are the authority, and this page links to the section each step comes from. Nothing below has been done on a real helmet yet. Steps marked (unverified) are written from the design and will change when the first unit is built.
Before you start: nobody has ordered or built one yet. All 9 tile designs are routed and checked, and the two tile panels, the hub and the camera board have their Gerbers, BOMs and CPLs (boards § routing). They are on the site's build page. No board has been made yet, so the first order is also the first test of the files.
What you need
| what | |
|---|---|
| money | about $2,143 for one helmet, all parts, boards, assembly and fees, before shipping and import duty (ordering) |
| printer | an FDM printer that prints PETG; the settings are for an Ender-3 V3 SE with a 0.4 mm nozzle (shell § print settings) |
| tools | a soldering-iron tip for heat-set inserts (M2 × 3), a #1 Phillips and a Torx T6 driver (for the M2 and M3 screws; check the heads you got), flush cutters for supports and panel tabs, tweezers, epoxy for the splice tabs, Kapton or 0.2 mm double-sided PI tape (cameras) |
| programmers | a two-wire debug probe for the CH32V203 tiles (WCH-LinkE class) (unverified: the repo does not name one yet); a Raspberry Pi Debug Probe (or a USB cable to the RP2350 test pads); a 3.3 V USB-serial adapter for the hub's ESP32-S3 |
| a computer | to run the app (app/, Node 22.18 or later) and the flashing tools |
1. Order the parts
Follow ordering one helmet exactly. It is regenerated from the boards, so its numbers are current. Summary:
- JLCPCB, four orders: CAP-01 and CAP-02 (the tile panels), HUB and CAM. Every option on each order form is in that page's tables: layers, thickness, ENIG, via filling, assembly on both sides, PCBA quantity 2.
- On JLC's parts page, check every line against
out/sourcing/cost.json: the same LCSC number, stock green. In the placement preview, check pin 1 of every QFN, the SC70 parts, the FPC connectors' orientation, and that every pogo pin is on the scalp face. - LCSC cart: the FPC jumpers (all Type B, 12-way), the M2 screws and the inserts. Check the photo of the 400 mm cable (C55509681) before you buy: its part number says type B, its description says "Same Side".
- Other suppliers: five OV2640 160° camera modules (Probots), the battery, an Oddjob Big Beanie in XXL, 1 kg of PETG, and for the headband a micro-ratchet helmet buckle, 20 mm nylon webbing and a closed-cell neoprene foam strip. The battery is specified, not yet chosen: a 1S Li-ion pouch of at least 2,500 mAh, at least 5 A continuous, with its own protection circuit and a 10 kΩ B3435 NTC lead, at most 70 × 45 × 9 mm, on a JST-PH 3-pin plug (BAT+, NTC, BAT−), with IEC 62133-2 and UN 38.3 test reports (hub § power, ordering). Do not use a hobby RC pack: it has no protection circuit and no NTC.
JLC builds two of every panel, so the order makes one helmet plus a spare pair of each tile design, a spare hub and a spare camera board. Keep the spares; they are your repair stock.
2. Print the shell
- Print
out/stl/EXO-140.stltoEXO-145.stlin PETG (shell § print settings): 0.2 mm layers, 7 walls (so the 2.8 mm wall prints solid), 5 top and bottom layers, 20 % infill, 240 °C nozzle, 80 °C bed, 60 mm/s, 40 % fan, a brim. The crown, the two bands and the headband need tree supports; the tabs and the battery cover print flat without. - The parts are already in print orientation: the crown dome down, the bands upside down on the seam plane, the headband on its mean plane.
- Remove the supports. Check every standoff for stringing in its Ø1.7 mm pilot hole: the screws cut their own thread there.
- Epoxy the splice tabs (EXO-143) across the three seams on the inner face, clear of the boards.
- Heat-set the four M2 × 3 inserts for the battery cover.
3. Flash the boards
Boards arrive assembled and blank. Flash each before it goes into the shell: a tile buried under cables is hard to reach.
Tiles (128 CH32V203 microcontrollers: two per tile, one on each TA tile) (unverified).
- Build:
cd firmware/tile && make sdk && makegivesbuild/tile.bin(the whole flash: boot stub and application) (protocol § tile firmware). - Program each converter through its debug pads (TPD, TPC, TPR) with the probe. Power the tile through its IN connector's VIN and GND (3.6 V) or the probe's supply.
- After the first flash, every later update goes over the chain from the hub (FW_BEGIN / FW_DATA / FW_COMMIT to all converters on a port); you never need the probe again unless a converter is bricked.
A pogo-pin fixture that holds one tile and touches both sets of pads saves hours over 66 tiles. None is designed yet.
The hub (two RP2350B and one ESP32-S3) (hub firmware § flash):
- Build with
firmware/hub/build.sh. - RP2350 A: short
TPABOOTto GND, pulseTPARUNlow, release; the chip appears as a USB drive on its test pads (TPAUSBP/TPAUSBM); copyhub_a.uf2. Or program over SWD (TPASWCLK/TPASWDIO) with OpenOCD. RP2350 B the same with theTPB*pads andhub_b.uf2. - ESP32-S3: hold
TPWIO0low, pulseTPWEN, then flash overTPWTX/TPWRXwithesptool.py --chip esp32s3(the command is in the firmware README). - After this, the ESP32 updates both RP2350s and itself over the air or USB.
Cameras (five RP2350A boards, no radio) (camera § firmware notes):
- Power the board from its VSYS and GND test pads (3.4-4.4 V) and tie CAM_EN to VSYS.
- Program
exo_camera.elfover SWD (the SWCLK, SWDIO and RUN test pads) with OpenOCD or a Raspberry Pi Debug Probe. The camera has no USB. To force the RP2350's ROM boot loader, hold the QSPI_SS pad low while you pulse RUN low. - Later updates go through the hub, over the camera's cable (firmware target 64 + camera − 1).
4. Fit the cameras to their boards
For each of the five camera boards (camera § assembly):
- Open J1's flip lock.
- With the board face down, slide the camera's tail into J1 from the left edge, gold fingers towards the board.
- Close the lock.
- Fold the tail 180° round the left edge, and stick the camera body on the board's front, over the RP2350A, with 0.2 mm double-sided PI tape, lens out, centred on the lens mark.
5. Assemble
The order below goes from the inside out, so nothing you fit blocks a later screw (unverified).
- Tiles. Each tile has its place on the cap (design, the colour map;
out/cap_layout.jsongives every tile's position and design). Fix each with two M2 × 6 screws from the scalp side into its standoffs (shell § standoffs). Turn the screws until snug; the thread is cut in PETG, so do not over-tighten. - Chain cables. For each of the 16 chains, connect each tile's OUT (J102) to the next tile's IN (J101) with the
jumper of the length in
out/shell_v1_report.json→fpc. Each cable goes up through the slot behind its connector and lies in its channel on the outer face. Every cable is Type B: a cable of the other type swaps pin 1 and pin 12 and shorts the port's supply (the port's switch then latches off). - The hub. Mount it on its four standoffs in the pod with M2 × 6 screws. Its REF and BIAS pins face the scalp.
- Chain heads. Connect each chain's first tile (J101) to its hub port. Port n carries chain n of
out/pcb/cap/boards.json; the channel map (protocol/map.json) assumes it (protocol § hub procedures). - Cameras. Click each camera board into its cradle on the cuff, and connect its J2 to the hub's camera port with its cable.
- Battery. Connect the battery's JST-PH lead to the hub's battery connector (BAT+, NTC, BAT−). The charger reads the cell's NTC; with no NTC it will not charge (unverified). Put the cell in its pocket and close the cover (EXO-144) with four M2 × 5 screws.
- Headband (EXO-145, shell § headband). Stick the foam strip to its inner face. Fix the ratchet's receiver to the band's right end and the toothed tongue to its left end, each with a 20 mm webbing loop and two M3 × 6 screws. Fit the band's four bridges over the shell's four link bosses with M3 × 10 screws (unverified).
6. First power-on (on the bench, not on a head)
- Plug in USB-C. The hub charges the battery and holds the contacts' supply off while USB power is present: this is the interlock, and it is meant to be there (hub § isolation and faults).
- Install and start the app (
cd app && npm install && npm run build && npm start, or the desktop app). Under Settings › Sensors, choose USB,auto. The app finds the hub's FT2232H. - Check the hub's STATUS: battery voltage and charge, both RP2350s, the ESP32.
- Unplug USB. Now the tiles can be powered. Give the hub your Wi-Fi network (the HUB_WIFI command) and connect over Wi-Fi. The app does not send HUB_WIFI yet, nor the bring-up commands of steps 5 and 6 (ENUMERATE, MAP, START); until it does, a real hub needs the protocol tools (protocol).
- Enumerate all 16 ports. Each port must report the converters its tiles have (two per tile, one per TA tile; the
counts are in
protocol/map.json), and only the last converter in each chain reports SENSE high (protocol § hub procedures). If a port fails, see troubleshooting § a chain does not enumerate. - Start a recording with the helmet on the table, then with your hand on a few contacts: the head map should show those contacts change. On the table, every contact should show an open circuit; nothing should read as a perfect contact.
- Power the cameras one at a time (CAM_SET) and start them (CAM_STREAM; starting a recording session in the app sends both). The cameras have no radio: video and audio go up each camera's cable to the hub, then to the app with the EEG. Each privacy LED is on whenever its sensor has power.
Bench only: removing the 0 Ω link RJP1 lets the helmet measure with USB connected. Do that only with the helmet on a phantom (a saline-soaked sponge head), never on a person, and refit it before anyone wears the helmet. A sold unit will not have RJP1.
You are the builder. A helmet you build from the files is a home-built device under FCC § 15.23: it must not cause interference, and you may not sell it.
7. Put it on (unverified)
- Charge it fully. Unplug the cable.
- Part or flatten your hair as little as you can; the pins are made to go through it.
- Put the helmet on back first, then roll the front down over the forehead, as you put on a helmet with a low back (shell § seams and printing). The pins press at most 1 mm into the hair while it goes on.
- Pull the beanie over the shell. Its hem goes at least 4 mm under the shell's rim all round, and the cuff holds the hem against the head (beanie). The camera lenses come through the knit at their grommets.
- In the app, look at the contact quality (the 125 Hz tone each contact sees, hub § part choices, REF and bias). Wiggle the helmet gently until most contacts settle. Contacts that stay poor: see troubleshooting.
The headband holds the shell down. Close its ratchet at the nape, under the hub, with the beanie's hem lifted: push the tongue in one tooth at a time until the shell sits firmly; pull the buckle's tab to release it (shell § headband).
8. Runtime and heat
With all five cameras streaming, the battery lasts about 1.2 hours; with the cameras off, about 2 hours (hub § power budget, calculated for a cell of 2,500 mAh, not measured). The cameras are about 40 % of the power and most of the heat in the cuff. Stream them only when you need them. Take the helmet off if it feels warm.