From 9a4ac98917c0ab5d57637f5acb31ebcf9d59c5ae Mon Sep 17 00:00:00 2001 From: tungnguyentu Date: Fri, 15 May 2026 02:28:42 +0700 Subject: [PATCH 1/3] docs: add tutorial for drawing letters with LEDs using arc-length sampling Adds a step-by-step tutorial that teaches readers how to place LEDs along the outline of any capital letter using SVG path data from @tscircuit/alphabet and a custom arc-length parameterization function (samplePath). Co-Authored-By: Claude Sonnet 4.6 --- docs/tutorials/draw-any-letter-with-leds.mdx | 396 +++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 docs/tutorials/draw-any-letter-with-leds.mdx diff --git a/docs/tutorials/draw-any-letter-with-leds.mdx b/docs/tutorials/draw-any-letter-with-leds.mdx new file mode 100644 index 0000000..ea5cadc --- /dev/null +++ b/docs/tutorials/draw-any-letter-with-leds.mdx @@ -0,0 +1,396 @@ +--- +title: Draw Any Letter with LEDs +description: >- + Learn how to use tscircuit and the @tscircuit/alphabet package to + automatically place 0402 LEDs along the outline of any capital letter, + producing a reusable LedLetter component. +--- + +## Overview + +In this tutorial you will build a reusable `` component that draws +any capital letter (A–Z) by placing 0402 LEDs along the letter's outline path. +The layout is fully automatic — you supply a letter and a size, and math does +the rest. + +import TscircuitIframe from "@site/src/components/TscircuitIframe" + +## Step 1: Sample points along an SVG path + +The `@tscircuit/alphabet` package exports `svgAlphabet`, a map from each +character to a normalized SVG path string (coordinates in `[0, 1]`). We need +to convert that path into a list of evenly-spaced `{x, y}` points so we know +where to place each LED. + + ( + + {pts.map((p, i) => ( + + ))} + +) +`} /> + +## Step 2: Add current-limiting resistors + +Each LED string needs a resistor (typically 68–100 Ω for a red 0402 LED at +5 V). We add one resistor per LED wired in series. + + { + const pts = samplePath(LETTER_A, 10) + const W = 20 // letter width in mm + const H = 25 // letter height in mm + + return ( + + {pts.map((p, i) => { + const px = (p.x - 0.5) * W + const py = (0.5 - p.y) * H + return ( + <> + + + + ) + })} + + ) +} +`} /> + +## Step 3: Build the reusable LedLetter component + +Now we wrap everything in a component that accepts any capital letter and a +scale factor. All 26 letters (A–Z) are supported using the path data from +`@tscircuit/alphabet`. + + { + const path = svgAlphabet[letter.toUpperCase()] + if (!path) return null + const pts = samplePath(path, nLeds) + + return ( + <> + {pts.map((p, i) => { + const px = offsetX + (p.x - 0.3) * width + const py = offsetY + (0.6 - p.y) * height + const ledName = namePrefix + letter + \`_LED\${i + 1}\` + const resName = namePrefix + letter + \`_R\${i + 1}\` + const midNet = \`net.\${ledName}_A\` + return ( + <> + + + + ) + })} + + ) +} + +export default () => ( + + + + + + + +) +`} /> + +## Step 4: Complete usage example + +Here is the complete `` component with all 26 letters supported, +ready to copy into your own project. + +```tsx +import { svgAlphabet } from "@tscircuit/alphabet" + +function samplePath(pathStr: string, n: number) { + const points: { x: number; y: number }[] = [] + const tokens = pathStr.trim().split(/\s+/) + let i = 0 + while (i < tokens.length) { + const cmd = tokens[i++] + if (cmd === "M" || cmd === "L") { + points.push({ x: parseFloat(tokens[i]), y: parseFloat(tokens[i + 1]) }) + i += 2 + } + } + if (points.length < 2) return points + const arcLen = [0] + for (let j = 1; j < points.length; j++) { + const dx = points[j].x - points[j - 1].x + const dy = points[j].y - points[j - 1].y + arcLen.push(arcLen[j - 1] + Math.sqrt(dx * dx + dy * dy)) + } + const total = arcLen.at(-1)! + const result: { x: number; y: number }[] = [] + for (let k = 0; k < n; k++) { + const target = (k / (n - 1)) * total + let seg = 0 + while (seg < arcLen.length - 1 && arcLen[seg + 1] < target) seg++ + const segLen = arcLen[seg + 1] - arcLen[seg] + const t = segLen === 0 ? 0 : (target - arcLen[seg]) / segLen + result.push({ + x: points[seg].x + t * (points[seg + 1].x - points[seg].x), + y: points[seg].y + t * (points[seg + 1].y - points[seg].y), + }) + } + return result +} + +interface LedLetterProps { + letter: string // Any capital A–Z letter + power: string // Net name for VCC (e.g. "net.PWR") + gnd: string // Net name for GND (e.g. "net.GND") + offsetX?: number // PCB X offset in mm + offsetY?: number // PCB Y offset in mm + width?: number // Letter width in mm (default 18) + height?: number // Letter height in mm (default 24) + nLeds?: number // Number of LEDs (default 14) + namePrefix?: string // Prefix to avoid name collisions +} + +export const LedLetter = ({ + letter, + power, + gnd, + offsetX = 0, + offsetY = 0, + width = 18, + height = 24, + nLeds = 14, + namePrefix = "", +}: LedLetterProps) => { + const path = svgAlphabet[letter.toUpperCase() as keyof typeof svgAlphabet] + if (!path) return null + const pts = samplePath(path, nLeds) + + return ( + <> + {pts.map((p, i) => { + const px = offsetX + (p.x - 0.3) * width + const py = offsetY + (0.6 - p.y) * height + const ledName = `${namePrefix}${letter}_LED${i + 1}` + const resName = `${namePrefix}${letter}_R${i + 1}` + const midNet = `net.${ledName}_A` + return ( + <> + + + + ) + })} + + ) +} +``` + +Usage: + +```tsx +export default () => ( + + + + +) +``` From 5a9646d8cdae3d952bc527c4027d1c186085ee2e Mon Sep 17 00:00:00 2001 From: tungnguyentu Date: Fri, 15 May 2026 02:32:38 +0700 Subject: [PATCH 2/3] docs: add ESP32 PCB layout and routing tutorial Step-by-step tutorial covering module placement, antenna keepout, USB-C power with AMS1117-3.3 regulator, CH340G USB-UART bridge, auto-reset circuit, and EN/BOOT pushbuttons. Each step has a live TscircuitIframe PCB preview. Co-Authored-By: Claude Sonnet 4.6 --- .../esp32-pcb-layout-and-routing.mdx | 511 ++++++++++++++++++ 1 file changed, 511 insertions(+) create mode 100644 docs/tutorials/esp32-pcb-layout-and-routing.mdx diff --git a/docs/tutorials/esp32-pcb-layout-and-routing.mdx b/docs/tutorials/esp32-pcb-layout-and-routing.mdx new file mode 100644 index 0000000..21f23f3 --- /dev/null +++ b/docs/tutorials/esp32-pcb-layout-and-routing.mdx @@ -0,0 +1,511 @@ +--- +title: ESP32 PCB Layout and Routing +description: Learn how to place and route an ESP32 module board in tscircuit — module placement, antenna keepout, decoupling capacitors, USB power, and autorouting. +--- + +## Overview + +This tutorial builds a complete ESP32 development board PCB step by step. You will +place the ESP32-WROOM-32 module, add power circuitry, wire up a USB-to-UART +bridge for programming, and let the autorouter connect everything. + +Good PCB layout for an ESP32 follows three placement rules: +1. The module antenna must hang over the board edge with no copper beneath it. +2. The 3.3 V supply path (USB connector → regulator → module) should be short. +3. Programming controls (EN reset, IO0 boot) live next to the module with their + pull-up resistors and pushbuttons nearby. + +import TscircuitIframe from "@site/src/components/TscircuitIframe" + +## Step 1: Place the ESP32 Module + +The ESP32-WROOM-32 is a stamp-style module. In tscircuit it is modelled as a +`` with the `stampreceiver` footprint family. The footprint string encodes +the pad count and spacing: + +``` +stampreceiver_left14_right14_bottom10_top0_w18mm_p1.27mm +``` + +Place the module near the **top edge** of the board so the antenna side (the +rounded end of the WROOM module) points outward away from the rest of the +circuitry. + + ( + +) + +export default () => ( + + + +) +`} /> + +The `pcbY={8}` shifts the module toward the top of the 40 mm board, leaving +room below for power and programming components. + +## Step 2: Add USB Power and 3.3 V Regulation + +The ESP32 runs on 3.3 V but USB supplies 5 V. We need: +- A **USB-C connector** for power input +- An **AMS1117-3.3** LDO regulator (SOT-223 package) to step 5 V down to 3.3 V +- **Decoupling capacitors** on both sides of the regulator + +Place the USB connector at the left board edge and the regulator between it and +the module to keep the high-current 5 V path short. + + ( + +) + +export default () => ( + + + + {/* USB-C power input at the left board edge */} + + + {/* AMS1117-3.3 LDO: VIN=VBUS, VOUT=3V3 */} + + + {/* 10 uF input bulk cap (close to regulator VIN) */} + + + {/* 10 uF output bulk cap (close to regulator VOUT) */} + + + {/* 100 nF bypass cap right at the ESP32 3V3 pin */} + + + {/* Power rails to ESP32 */} + + + + + + +) +`} /> + +The regulator at `pcbX={-10}` sits between the USB connector (`pcbX={-22}`) and +the module (`pcbX={0}`), creating a straight left-to-right power flow that is +easy to review. + +## Step 3: Add the USB-to-UART Bridge + +To program the ESP32 over USB you need a serial bridge chip. The **CH340G** +(SOP-16) converts USB signals to the UART RX/TX lines the ESP32 bootloader uses. + +The bridge also drives the **DTR** and **RTS** hardware flow-control lines. +Those connect to the ESP32's EN and IO0 pins through 100 nF capacitors to +implement the automatic reset-into-bootloader sequence that the Arduino IDE and +`esptool` rely on. + + ( + +) + +export default () => ( + + + + + + + + {/* CH340G USB-UART bridge */} + + + {/* UART cross-connect: CH340 TX→ESP RX, CH340 RX←ESP TX */} + + + + {/* Auto-reset: DTR/RTS → 100nF caps → EN/IO0 */} + + + + + + {/* USB D+/D- to CH340 */} + + + + {/* Decoupling on CH340 VCC */} + + + + + + + + + + + + +) +`} /> + +The auto-reset capacitors on C4 and C5 implement the standard ESP32 reset +circuit: when a host asserts DTR and then RTS (or vice versa), the resulting +pulse drives EN low followed by IO0 low, putting the chip into download mode +without you pressing any buttons. + +## Step 4: EN Reset and BOOT Buttons + +Even with automatic reset, physical buttons are important for manual recovery. +Place the **EN** (reset) button and the **IO0** (boot mode) button near the +right edge of the board with their 10 kΩ pull-up resistors right beside them. + + ( + +) + +export default () => ( + + + + + + + + + + {/* 10k pull-up on EN */} + + + {/* EN reset button */} + + + {/* 10k pull-up on IO0 */} + + + {/* BOOT button */} + + + + + + + + + + + + + + + + + + + + + + +) +`} /> + +Pressing SW1 (EN) resets the ESP32. Pressing SW2 (IO0) while holding SW1 puts +it into download mode so you can flash firmware manually without needing the +auto-reset circuit. + +## Step 5: Autorouting + +Once component placement is done, tscircuit can route all the traces automatically. +Add `autorouter="auto-cloud"` to the `` element to use the cloud autorouter, +or `autorouter="sequential-trace"` for the local solver: + +```tsx + + ... + +``` + +The autorouter reads every `connections` prop and every `` you added, +so there is nothing extra to configure. After routing you can switch to the PCB +tab in the preview to inspect trace widths and clearances. + +### Placement tips that help the autorouter + +- **Short nets first**: the regulator-to-module 3V3 path and the UART TX/RX + crossover are the nets most affected by placement order. +- **Avoid crossing power nets**: keep VBUS traces on the left side of the board + and 3V3 traces in the middle so they do not create unnecessary crossings that + require vias. +- **Put bypass caps as close as possible**: C3 (module bypass) and C6 (CH340 + bypass) should be within 2–3 mm of their respective IC's power pin to minimize + the inductance the router must deal with. + +## Pre-fabrication checklist + +Before exporting Gerbers: + +- [ ] The antenna end of the ESP32 module hangs over the board edge, or at least + no copper, vias, or components appear within 3 mm of the antenna window. +- [ ] C1 is within 5 mm of the USB connector VBUS pin. +- [ ] C3 is within 3 mm of U1 pin 2 (3V3). +- [ ] C6 is within 3 mm of U3 pin 16 (VCC). +- [ ] All GND pins on U1 (pins 1, 15, 37, 38) connect to the same GND net. +- [ ] The UART crossover is correct: U3 TXD → U1 RXD0, U3 RXD ← U1 TXD0. +- [ ] Both pushbuttons are reachable from the board edge. From bf066a8844fa89b68f788eb3d4680dc61b2cb931 Mon Sep 17 00:00:00 2001 From: tungnguyentu Date: Fri, 15 May 2026 23:03:51 +0700 Subject: [PATCH 3/3] docs: add components BOM table and cost estimate Co-Authored-By: Claude Sonnet 4.6 --- .../esp32-pcb-layout-and-routing.mdx | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/tutorials/esp32-pcb-layout-and-routing.mdx b/docs/tutorials/esp32-pcb-layout-and-routing.mdx index 21f23f3..c578479 100644 --- a/docs/tutorials/esp32-pcb-layout-and-routing.mdx +++ b/docs/tutorials/esp32-pcb-layout-and-routing.mdx @@ -17,6 +17,23 @@ Good PCB layout for an ESP32 follows three placement rules: import TscircuitIframe from "@site/src/components/TscircuitIframe" +## Components + +| Ref | Part | Description | Footprint | +|-----|------|-------------|-----------| +| U1 | ESP32-WROOM-32 | Wi-Fi + BT module | stamp receiver 18 mm | +| U2 | AMS1117-3.3 | 3.3 V LDO regulator | SOT-223 | +| U3 | CH340C | USB-to-UART bridge | SOP-16 | +| J1 | USB-C receptacle | 5 V power + programming | SMD USB-C | +| SW1 | Pushbutton | EN (reset) | THT tactile | +| SW2 | Pushbutton | IO0 (boot mode) | THT tactile | +| R1 | 10 kΩ | EN pull-up | 0402 | +| R2 | 10 kΩ | IO0 pull-up | 0402 | +| R3, R4 | 10 kΩ | Auto-reset (EN + IO0 RC) | 0402 | +| C1 | 10 µF | VBUS bulk decoupling | 0805 | +| C2 | 10 µF | 3V3 bulk decoupling | 0805 | +| C3, C6 | 100 nF | Module / CH340C bypass | 0402 | + ## Step 1: Place the ESP32 Module The ESP32-WROOM-32 is a stamp-style module. In tscircuit it is modelled as a @@ -497,6 +514,23 @@ tab in the preview to inspect trace widths and clearances. bypass) should be within 2–3 mm of their respective IC's power pin to minimize the inductance the router must deal with. +## Cost Estimate + +| Component | Unit Cost | Qty | Total | +|-----------|-----------|-----|-------| +| ESP32-WROOM-32 | $2.20 | 1 | $2.20 | +| AMS1117-3.3 (SOT-223) | $0.10 | 1 | $0.10 | +| CH340C (SOP-16) | $0.25 | 1 | $0.25 | +| USB-C receptacle | $0.15 | 1 | $0.15 | +| Tactile pushbuttons | $0.05 | 2 | $0.10 | +| 10 kΩ resistors (0402) | $0.01 | 4 | $0.04 | +| 10 µF capacitors (0805) | $0.05 | 2 | $0.10 | +| 100 nF capacitors (0402) | $0.02 | 2 | $0.04 | +| PCB (2-layer, 5 pcs) | $0.50 | 1 | $0.50 | +| **Total** | | | **~$3.48** | + +*Prices based on LCSC/JLCPCB quantities of 10.* + ## Pre-fabrication checklist Before exporting Gerbers: