The system
The tooling is one part of it. This is the rest, written down for the version of you that comes back in two months having forgotten why any of it was decided — which is the only readership this page has.
scripts/rehome.mjs exists for exactly that
move. Until then, keeping it next to a real build is what stops it becoming aspirational.
1 · The bench
Ordered by what is missing, not by what is impressive. The greyed rows are already on the bench.
B2B-XH-A) that solders into the PCB. Plenty of kits sold as “JST-XH
connectors” are cable-end only, and you find out when you have a finished loom and nowhere
to plug it. The kit in the parts list has all three.
2 · What a Perma-Proto is
A circuit board wired to look exactly like a solderless breadboard: 30 rows of double five-hole columns, four power rails down the sides, the same silkscreen numbering, 51×81 mm, about $4.50. Thru-plated and gold-finished, so it takes rework without lifting pads.
Why it matters more than it sounds: the usual route from breadboard to permanent is to look at a working breadboard and rebuild the circuit on plain perfboard, which has no layout at all. That rebuild is a transcription, and transcriptions are where errors come from — you are copying a working thing into a different topology by eye, at night. A Perma-Proto has the same topology, so the move is hole-for-hole. What worked keeps working.
The two sets of pins
Yes — and it is worth being precise, because “headers” means two different things that get bought and soldered separately, and only one of them is on the shopping list.
- Male pins go on the module. Nearly every breakout ships the strip loose in the bag. Adafruit’s amplifier page says it plainly — “with a small piece of optional header. Some soldering is required to attach the header.” So soldering headers onto four modules is a real early task, and it is the one where the hold-it-square trick earns its keep.
- Female sockets go in the board. The Perma-Proto is bare — plated holes and silkscreen, no pins of any kind. These are the strips you buy, and you cut them to length with the flush cutters.
- The dev board is the exception. The ESP32-S3-DevKitC-1 arrives with its male pins already soldered on, so it only needs sockets to sit in.
Roughly 66 socket positions for all four modules — 44 for the dev board’s two rows, the rest for the reader, amplifier and SD breakout. A five-pack of 36-pin strips is 180 positions, so one pack covers this build with plenty spare for the next one.
3 · The interconnect standard
Three tiers. The rule is that you never think about this again — you look it up here and do what it says.
0.1″ headers. No cable.
Female sockets soldered to the board; modules plug in. A dead module is a swap, not a desoldering job, and the reader can be lifted out to test read range through different lid thicknesses without unwiring anything.
JST-XH.
Latching and polarised. Dupont is friction-fit only and not for anything that moves; this is a toy that gets shaken and carried by the wrong end.
XH is genuinely 2.5 mm pitch, not 2.54. Listings say “XH-2.54” constantly and it is wrong. At 0.04 mm per pin it drops into an 0.1″ grid happily up to about 6 ways; by 10 ways the accumulated 0.36 mm will not go. Our longest run is 3 pins, so it is a non-issue here — worth knowing before it is one.
JST-PH 2.0 mm.
Not a preference — it is what the battery ecosystem already ships. Cells and chargers arrive with it fitted, so the highest-current connection in the box needs no work and no decision.
Wire colours
Four, with one inviolable rule and one that earns its keep the first time a battery is involved. A six-spool set covers these with two spare.
| Colour | Means | Why |
|---|---|---|
| Black | Ground. Only ever ground. | The one rule that is never bent for convenience. If black is ever anything else, every future debugging session starts by re-deriving what it is this time. |
| Red | V+ upstream of the power switch. | Live off the cell whatever the switch is doing. |
| Blue | V+ downstream of the switch. | The useful one. With a battery there are two positive nets and only one of them goes dead when the box is off — telling them apart at a glance is worth a whole colour. |
| Yellow | Signal. | Buttons, pot wiper, LED, I²S. Anything that is neither power nor ground. |
Stranded, not solid. Solid core work-hardens and snaps inside something that gets carried, and it is wrong in a crimp barrel — the barrel wings are shaped to gather strands. Worth saying because the two are sold under near-identical names: Adafruit’s stranded set is 3111 and its solid twin is 1311. 22 AWG throughout: it is the fat end of XH’s 22–28 range, and it carries the speaker’s ~0.9 A RMS without thinking about it, so one gauge does the whole box.
Heat shrink goes on soldered joints, not crimped ones. Speaker tabs, switch lugs, pot lugs, LED legs — yes. A crimped contact gets none: it has to seat inside its housing and shrink on the barrel stops it going home. 3/32, 1/8 and 3/16 covers a single 22 AWG wire up to a small pair.
And on every cable that leaves the board: a zip tie through two holes, before the connector. A tug then pulls on the board and not on a solder joint. It is the step people skip, it costs nothing, and it is most of the difference between a box that survives a four-year-old and one that comes back in pieces.
4 · Tricks that replace tools
Written down because they are the kind of thing you work out once and then forget you knew.
Soldering a header in square, with no third hand
Plug the header’s pins into a solderless breadboard and set the board face-down on top. The breadboard holds everything square and level. Tack one corner pin, pick it up, check it is flush, reheat that single joint to correct it if not, then solder the rest. Correcting one joint is easy; correcting thirty-six is a new board.
Holding a wire while you tin it
A zip tie round the wire and a heavy mug on the tail. You have the zip ties.
Beeping a loom before it goes in
Not about crimp quality — about the two mistakes that survive a good crimp: a contact seated in the wrong housing cavity, and a whisker bridging two pins. Beep each way end to end, then beep each pin to its neighbours. Thirty seconds for the whole loom, and it is the check that catches a wiring error rather than a workmanship one.
Before powering anything for the first time
Beep between the power rails with everything unplugged. A short found by a meter costs nothing; a short found by a battery costs a module and possibly the board.
5 · The build loop
Breadboard → transfer → box, with a gate between every stage.
- Breadboard one subsystem at a time and prove it against its gate before adding the next. The whole reason the assembly page is staged that way is so a fault is always inside the one thing you just changed.
- Never add two things between tests. The moment you do, debugging becomes a search instead of a look.
- Transfer to the Perma-Proto hole-for-hole once the whole thing works loose on the bench. Not before — soldering a design you have not seen run is how an evening becomes a weekend.
- Box it last, and only after the full first-story flow works with wires everywhere.
6 · How this gets written down
This is the actual system, and it is the part that makes a second project fast. Four habits, each of which has already paid for itself here:
| Habit | Here | What it bought |
|---|---|---|
| Parts as data, not prose | parts.json → rendered by two pages |
One place to edit. A link checker that can verify the whole BOM in one command — and which caught that a 200 response proves nothing, because vendors reuse product ids. |
| Pin map as code, diagram generated from it | lib/pinmap.js → the schematic |
The drawing cannot lie about a pin number. It also holds the reserved list, so GPIO33–37 being PSRAM is caught by a test instead of by a multimeter at midnight. |
| Every hard-won constraint becomes a test | a full card still fits NTAG213 · no origin can both record and upload · the multimeter stays high on the bench list | A comment saying “don't do X” gets skimmed. A failing test gets read. Three times now a fact learned the hard way has been frozen this way, and one of them caught a real modelling error the same afternoon. |
| Decisions logged with their reasons | the decision log — eighteen rows, each with a because | In two months you remember what was decided and never why. Without the why you relitigate it, and usually arrive somewhere worse, because the reason was load-bearing and invisible. |
To start project two
Copy the shape, not the content: a parts.json, a pinmap.js, a
selftest that enforces the constraints you have already learned, and a design record whose
decision log has a because column. Then the bench, the interconnect tiers and the tricks
above are already answered and you start at the interesting part.
7 · Standing decisions
The forget-proof table. If future-you is about to do something on the left, the middle column is why not.
| Do this | Because | Enforced by |
|---|---|---|
| 0.1″ headers for anything module-shaped | Removes four interconnects and makes a dead module a swap | build |
| JST-XH panel-side, JST-PH for power | Latching and polarised; Dupont is not for things that move | this page |
| Zip tie every cable that leaves the board | The tug lands on the board, not a joint | this page |
| Beep the rails before first power-up | A short found by a meter is free | this page |
| Buy the board-side header too | A JST-XH connection is housing + contacts + shrouded header, and kits often omit the third | parts.json |
| XH is 2.5 mm, whatever the listing says | Fine to ~6 ways on an 0.1″ grid; not fine at 10 | this page |
| Black is ground and nothing else, ever | Otherwise every debug session starts by re-deriving what black means this time | the colours |
| Red is V+ before the switch, blue after it | A battery gives two positive nets and only one dies when the box is off | the colours |
| Stranded wire only | Solid work-hardens and snaps, and is wrong in a crimp barrel | parts.json |
| Heat shrink on soldered joints only | Shrink on a crimp barrel stops the contact seating in its housing | the colours |
| Never add two things between tests | Debugging becomes a search instead of a look | the stage gates |
| Transfer to protoboard only after it runs loose | Soldering an unproven design turns an evening into a weekend | this page |
| 13.56 MHz NFC, never 125 kHz | A phone can neither read nor write 125 kHz — it deletes the whole phone-side pipeline | design §3.2 |
| The tag holds a pointer, never audio | Off by ~4,000×. And pointers give playlists and re-binding for free | tape.selftest.mjs |
| Pulse the NFC field, 10 ms in 125 | A continuous field is 50–80 mA and ends the battery version alone | the budget |
| Volume is a pot with a physical end stop | A maximum a child cannot exceed. Buttons have no end stop | D9 |
Quote prices from parts.json, with the tier | The estimate has been revised upward three times; guesses do not survive contact with a checkout page | parts.json |