molecule
Evan — Adom Molecule LED Nameplate
Public Made by Adomby adom
Evan's name in 66 green 0603 LEDs on a 5x7 dot-matrix grid, USB-C powered off the east edge. A real Adom molecule: four corner machine pins, 96x44 mm absolute, every part from the Adom Basic Parts catalog.
main
John Lauer
README.html with embedded 3D walkthrough viewer, full BOM and schematic, source bundle, build outputs
23c1d5e
2mo ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
import { Molecule } from "@tsci/adom-inc.molecule"
import { UsbCReceptacle, usbCPadRowForEdge } from "./UsbCReceptacle"
// "EVAN" desk nameplate molecule. 96 x 44 mm, USB-C powered from the
// EAST (right) edge, 66 green 0603 LEDs forming a 5 x 7 dot-matrix
// bitmap of each letter. Built as an Adom molecule so it fixtures into
// the standard workcell via 4 corner machine pins.
//
// Every part is an Adom Basic Part (wiki.adom.inc/adom/adom-basic-parts):
// LED IN-S63BTG green 0603, InGaN 527 nm, Vf 3.2 V @ 20 mA
// R CR0402-FX-3300GLF 330 Ω 1% 0402, Bourns
// R_CC CR0402-FX-4701GLF 4.7 kΩ 1% 0402, Bourns (USB-C Rd)
// C_BULK CL21A106KOQNNNG 10 µF X5R 0805, Samsung
// C_HF 0402B104J160CT 100 nF X7R 0402, Walsin
// J1 TYPE-C-31-M-12 wiki.adom.inc/adom/type-c-31-m-12 (LCSC C165948)
// 5x7 dot-matrix font. 1 = LED, 0 = empty. Row 0 is the top row.
// 5 columns wide (not 3) so N gets a real diagonal and V a real point.
// A 3-wide N degenerates into a blob that reads as H or M.
const FONT: Record<string, number[][]> = {
E: [
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 1, 1, 1, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 1, 1, 1, 1],
],
V: [
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[0, 1, 0, 1, 0],
[0, 0, 1, 0, 0],
],
A: [
[0, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
],
// The diagonal walks column 1 to 2 to 3 down the glyph, so the stroke
// reads unmistakably as N rather than as H with a filled middle.
N: [
[1, 0, 0, 0, 1],
[1, 1, 0, 0, 1],
[1, 1, 0, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 0, 1, 1],
[1, 0, 0, 1, 1],
[1, 0, 0, 0, 1],
],
}
const TEXT = "EVAN"
const FONT_COLS = 5
const FONT_ROWS = 7
const PIXEL_PITCH = 3.0
const LETTER_GAP = 3.0
const LETTER_W = FONT_COLS * PIXEL_PITCH // 15
const LETTER_PITCH = LETTER_W + LETTER_GAP // 18
const TEXT_WIDTH =
TEXT.length * LETTER_W + (TEXT.length - 1) * LETTER_GAP // 69 mm
// Absolute sizing so the real outer edge is a number we can trust: the
// molecule's wings would otherwise grow the board past the nominal size,
// and the USB-C mouth has to be positioned against a KNOWN edge.
// See ~/.claude/skills/adom-tsci/guides/adom-usbc.md.
const BOARD_W = 96
const BOARD_H = 44
const WING = 0.2 // nominal wing, per side, verified against the build log
const HALF_W = BOARD_W / 2 + WING // 48.2, the REAL east edge
const HALF_H = BOARD_H / 2 + WING // 22.2
// The east ~16 mm is reserved for the USB-C receptacle and its support
// parts, so the letters sit left of centre rather than centred.
const TEXT_LEFT_X = -40 // letters span x ∈ [-40, +29]
const TEXT_CENTER_Y = 1 // LED rows span y ∈ [-8, +10]
// Pad-row x for the receptacle. usbCPadRowForEdge() works back from the
// board edge through the shell so the mouth lands 0.4 mm proud: far
// enough for a cable to seat, not so far that the forward anchor holes
// fall off the board. Do not hand-tune this.
const USB_X = usbCPadRowForEdge(HALF_W, 0.4)
// IN-S63BTG is InGaN green: Vf 3.2 V typ at 20 mA, dropping to about
// 3.0 V at single-digit mA. 330 ohm from 5 V gives ~6 mA per LED.
// At 560 mcd @ 20 mA these are bright parts; 6 mA is a comfortable desk
// brightness and keeps the whole board at ~400 mA, inside what a USB-C
// source advertising Default USB Power will hand out.
const R_VALUE = "330"
const LED_COLOR = "green"
const LED_MPN = "IN-S63BTG"
const R_MPN = "CR0402-FX-3300GLF"
// ── Schematic placement ──────────────────────────────────────────────────
// tscircuit's auto-layout puts 141 symbols in ONE horizontal strip, which
// lint passes (nothing overlaps) but no human can read. So every part gets
// explicit schX/schY. Note the all-or-nothing rule: placing SOME parts
// disables auto-layout for the rest and stacks them at the origin, so once
// you start you must place everything you control.
const SCH_COLS = 8
const SCH_COL_PITCH = 8
const SCH_ROW_PITCH = 3
const SCH_LEFT = -28
const SCH_TOP = 30
/** LED/resistor pair slot for pixel `idx`. R sits left, its LED 3 units right. */
const schSlot = (idx: number) => ({
x: SCH_LEFT + (idx % SCH_COLS) * SCH_COL_PITCH,
y: SCH_TOP - Math.floor(idx / SCH_COLS) * SCH_ROW_PITCH,
})
type Pixel = { letterIdx: number; row: number; col: number; x: number; y: number; idx: number }
const PIXELS: Pixel[] = (() => {
const out: Pixel[] = []
let idx = 0
for (let li = 0; li < TEXT.length; li++) {
const bitmap = FONT[TEXT[li]]
const letterX0 = TEXT_LEFT_X + li * LETTER_PITCH
for (let row = 0; row < FONT_ROWS; row++) {
for (let col = 0; col < FONT_COLS; col++) {
if (!bitmap[row][col]) continue
const x = letterX0 + col * PIXEL_PITCH + PIXEL_PITCH / 2
const y = TEXT_CENTER_Y + (3 - row) * PIXEL_PITCH
out.push({ letterIdx: li, row, col, x, y, idx: idx++ })
}
}
}
return out
})()
export default () => (
<Molecule
type="4pin"
size={`${BOARD_W}x${BOARD_H} absolute`}
pinType="MachinePinMediumStandard"
wing="nominal"
roundEdges={true}
>
{/* ════════════════════ TOP-LAYER SILKSCREEN ════════════════════ */}
{/* The LEDs are the name, so the top silk stays out of their way. */}
<silkscreentext text="E V A N" fontSize={1.3} pcbX={-30} pcbY={17.0} layer="top" />
<silkscreentext text="his name in lights" fontSize={0.55} pcbX={-30} pcbY={15.5} layer="top" />
<silkscreentext text="ADOM * FORT WORTH TEXAS" fontSize={0.5} pcbX={-30} pcbY={-15.0} layer="top" />
{/* Point the user at the east-edge USB-C port */}
<silkscreentext text="5V IN" fontSize={0.8} pcbX={36} pcbY={13.5} layer="top" />
<silkscreentext text="USB-C >>" fontSize={0.55} pcbX={36} pcbY={12.2} layer="top" />
<silkscreentext text="any phone charger" fontSize={0.45} pcbX={36} pcbY={-12.2} layer="top" />
<silkscreentext text="works" fontSize={0.45} pcbX={36} pcbY={-13.2} layer="top" />
{/* Tiny corner labels for the workcell pins */}
<silkscreentext text="MP1" fontSize={0.4} pcbX={-HALF_W + 5} pcbY={HALF_H - 4.5} layer="top" />
<silkscreentext text="MP2" fontSize={0.4} pcbX={HALF_W - 5} pcbY={HALF_H - 4.5} layer="top" />
<silkscreentext text="MP3" fontSize={0.4} pcbX={HALF_W - 5} pcbY={-HALF_H + 4.5} layer="top" />
<silkscreentext text="MP4" fontSize={0.4} pcbX={-HALF_W + 5} pcbY={-HALF_H + 4.5} layer="top" />
{/* ════════════════════ BOTTOM-LAYER SILKSCREEN ════════════════════
The bottom is a documentation panel. Flip the board over and it
explains how it works, what is on it, and how to keep it alive. */}
{/* Header band */}
<silkscreentext layer="bottom" text="EVAN NAMEPLATE" fontSize={1.6} pcbX={0} pcbY={18.0} />
<silkscreentext layer="bottom" text="for Evan's desk * adom.inc 2026" fontSize={0.5} pcbX={0} pcbY={16.6} />
{/* HOW TO POWER. First thing read after unboxing */}
<silkscreentext layer="bottom" text="HOW TO POWER IT" fontSize={0.7} pcbX={-34} pcbY={14.2} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="1. Grab any USB-C cable (iPhone charger works)"
fontSize={0.45} pcbX={-34} pcbY={13.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="2. Plug one end into the RIGHT edge of this board"
fontSize={0.45} pcbX={-34} pcbY={12.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="3. Plug the other end into a 5V USB-C source"
fontSize={0.45} pcbX={-34} pcbY={11.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="4. EVAN lights up green - thats it"
fontSize={0.45} pcbX={-34} pcbY={10.0} anchorAlignment="center_left" />
{/* HOW IT WORKS */}
<silkscreentext layer="bottom" text="HOW IT WORKS" fontSize={0.7} pcbX={-34} pcbY={8.2} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Each letter = 5x7 LED dot-matrix bitmap"
fontSize={0.45} pcbX={-34} pcbY={7.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="66 green 0603 LEDs in parallel from VBUS"
fontSize={0.45} pcbX={-34} pcbY={6.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="One 330 ohm resistor per LED -> 6mA each"
fontSize={0.45} pcbX={-34} pcbY={5.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="No microcontroller - pure analog charm"
fontSize={0.45} pcbX={-34} pcbY={4.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Total draw: ~400mA at 5V (2.0W)"
fontSize={0.45} pcbX={-34} pcbY={3.0} anchorAlignment="center_left" />
{/* BOM. Every line is an Adom Basic Part */}
<silkscreentext layer="bottom" text="BILL OF MATERIALS (ADOM BASIC PARTS)" fontSize={0.7} pcbX={3} pcbY={14.2} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="D1-D66 * IN-S63BTG green 0603 * Inolux"
fontSize={0.45} pcbX={3} pcbY={13.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="R1-R66 * CR0402-FX-3300GLF 330R 1%"
fontSize={0.45} pcbX={3} pcbY={12.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="J1 * TYPE-C-31-M-12 * LCSC C165948"
fontSize={0.45} pcbX={3} pcbY={11.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="R_CC1/2 * CR0402-FX-4701GLF 4K7 * USB-C Rd"
fontSize={0.45} pcbX={3} pcbY={10.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="C_BULK * CL21A106KOQNNNG 10uF X5R 0805"
fontSize={0.45} pcbX={3} pcbY={9.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="C_HF * 0402B104J160CT 100nF X7R 0402"
fontSize={0.45} pcbX={3} pcbY={8.0} anchorAlignment="center_left" />
{/* HOW IT WAS BUILT */}
<silkscreentext layer="bottom" text="HOW IT WAS BUILT" fontSize={0.7} pcbX={3} pcbY={6.2} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Authored in tscircuit (TSX) - lib/index.tsx"
fontSize={0.45} pcbX={3} pcbY={5.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Each pixel is one map iteration"
fontSize={0.45} pcbX={3} pcbY={4.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Autorouted by the tscircuit autorouter"
fontSize={0.45} pcbX={3} pcbY={3.0} anchorAlignment="center_left" />
{/* WORKCELL FIXTURING */}
<silkscreentext layer="bottom" text="WORKCELL FIXTURING" fontSize={0.7} pcbX={-34} pcbY={1.2} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="4 machine pins MP1-MP4 at the corners"
fontSize={0.45} pcbX={-34} pcbY={0.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="No electrical function - mechanical only"
fontSize={0.45} pcbX={-34} pcbY={-1.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Adom 96x44 absolute 4pin molecule"
fontSize={0.45} pcbX={-34} pcbY={-2.0} anchorAlignment="center_left" />
{/* MAINTENANCE */}
<silkscreentext layer="bottom" text="IF A LED GOES DARK" fontSize={0.7} pcbX={3} pcbY={1.2} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Each LED is independently fused by its R"
fontSize={0.45} pcbX={3} pcbY={0.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="One LED dying does not affect the others"
fontSize={0.45} pcbX={3} pcbY={-1.0} anchorAlignment="center_left" />
<silkscreentext layer="bottom" text="Replace the LED + its 330 ohm R pair"
fontSize={0.45} pcbX={3} pcbY={-2.0} anchorAlignment="center_left" />
{/* SAFETY */}
<silkscreentext layer="bottom" text="Do not exceed 5.5V on VBUS - LEDs will burn"
fontSize={0.4} pcbX={0} pcbY={-5.0} />
<silkscreentext layer="bottom" text="ESD: handle by the edges, not the components"
fontSize={0.4} pcbX={0} pcbY={-6.0} />
{/* Footer credits */}
<silkscreentext layer="bottom" text="Evan-LED-Nameplate v1.0.0"
fontSize={0.5} pcbX={0} pcbY={-8.4} />
<silkscreentext layer="bottom" text="Built with adom-tsci on the Adom platform"
fontSize={0.5} pcbX={0} pcbY={-9.5} />
{/* Apple-style provenance line */}
<silkscreentext layer="bottom" text="Designed by Adom in Fort Worth, Texas"
fontSize={0.5} pcbX={0} pcbY={-10.6} />
<silkscreentext layer="bottom" text="2026-08-20"
fontSize={0.4} pcbX={0} pcbY={-11.7} />
{/* ════════════════════ COMPONENTS ════════════════════ */}
{/* USB-C receptacle on the EAST (right) edge. pcbRotation 90 fires the
mouth east; pcbX is the PAD ROW, not the shell. */}
<UsbCReceptacle name="J1" pcbX={USB_X} pcbY={0} pcbRotation={90} schX={-24} schY={-12} />
{/* CC pulldowns. 4K7 Rd tells the charger to turn VBUS on */}
<resistor name="R_CC1" resistance="4.7k" footprint="0402"
manufacturerPartNumber="CR0402-FX-4701GLF" pcbX={34} pcbY={7} schX={-8} schY={-9} />
<resistor name="R_CC2" resistance="4.7k" footprint="0402"
manufacturerPartNumber="CR0402-FX-4701GLF" pcbX={34} pcbY={-7} schX={-8} schY={-15} />
{/* Bulk + HF decoupling, smooths inrush when 66 LEDs light at once */}
<capacitor name="C_BULK" capacitance="10uF" footprint="0805"
manufacturerPartNumber="CL21A106KOQNNNG" pcbX={34} pcbY={0} schX={2} schY={-12} />
<capacitor name="C_HF" capacitance="100nF" footprint="0402"
manufacturerPartNumber="0402B104J160CT" pcbX={37.5} pcbY={0} schX={8} schY={-12} />
{/* ════════════════════ NETS ════════════════════ */}
<net name="VBUS" />
<net name="GND" />
<trace from="J1.VBUS1" to="net.VBUS" />
<trace from="J1.VBUS2" to="net.VBUS" />
<trace from="J1.GND1" to="net.GND" />
<trace from="J1.GND2" to="net.GND" />
<trace from="R_CC1.pin1" to="J1.CC1" />
<trace from="R_CC1.pin2" to="net.GND" />
<trace from="R_CC2.pin1" to="J1.CC2" />
<trace from="R_CC2.pin2" to="net.GND" />
<trace from="C_BULK.pin1" to="net.VBUS" />
<trace from="C_BULK.pin2" to="net.GND" />
<trace from="C_HF.pin1" to="net.VBUS" />
<trace from="C_HF.pin2" to="net.GND" />
{/* ════════════════════ THE EVAN LED MATRIX ════════════════════ */}
{PIXELS.map((p) => (
<resistor
key={`R${p.idx}`}
name={`R${p.idx}`}
resistance={R_VALUE}
footprint="0402"
manufacturerPartNumber={R_MPN}
pcbX={p.x}
pcbY={p.y - 1.65}
schX={schSlot(p.idx).x}
schY={schSlot(p.idx).y}
/>
))}
{PIXELS.map((p) => (
<led
key={`D${p.idx}`}
name={`D${p.idx}`}
color={LED_COLOR}
footprint="0603"
manufacturerPartNumber={LED_MPN}
pcbX={p.x}
pcbY={p.y}
schX={schSlot(p.idx).x + 3}
schY={schSlot(p.idx).y}
/>
))}
{PIXELS.map((p) => (
<trace key={`tv${p.idx}`} from={`R${p.idx}.pin1`} to="net.VBUS" />
))}
{PIXELS.map((p) => (
<trace key={`tr${p.idx}`} from={`R${p.idx}.pin2`} to={`D${p.idx}.anode`} />
))}
{PIXELS.map((p) => (
<trace key={`tg${p.idx}`} from={`D${p.idx}.cathode`} to="net.GND" />
))}
</Molecule>
)