diff --git a/codetestingplayground/__snapshots__/esp32-wifi-test-board.circuit-schematic.snap.svg b/codetestingplayground/__snapshots__/esp32-wifi-test-board.circuit-schematic.snap.svg new file mode 100644 index 00000000..96cbd5e1 --- /dev/null +++ b/codetestingplayground/__snapshots__/esp32-wifi-test-board.circuit-schematic.snap.svg @@ -0,0 +1,12 @@ +112233445566AABBCCDD \ No newline at end of file diff --git a/codetestingplayground/esp32-wifi-test-board.circuit.tsx b/codetestingplayground/esp32-wifi-test-board.circuit.tsx new file mode 100644 index 00000000..41020155 --- /dev/null +++ b/codetestingplayground/esp32-wifi-test-board.circuit.tsx @@ -0,0 +1,566 @@ +import { SmdUsbC } from "@tsci/seveibar.smd-usb-c" + +const cp2102PinLabels = { + pin1: "DCD", + pin2: "RI", + pin3: "GND", + pin4: "D_PLUS", + pin5: "D_MINUS", + pin6: "VDD", + pin7: "REGIN", + pin8: "VBUS", + pin9: "RST", + pin10: "NC1", + pin11: "SUSPENDb", + pin12: "SUSPEND", + pin13: "NC2", + pin14: "NC3", + pin15: "NC4", + pin16: "NC5", + pin17: "NC6", + pin18: "NC7", + pin19: "NC8", + pin20: "NC9", + pin21: "NC10", + pin22: "NC11", + pin23: "CTS", + pin24: "RTS", + pin25: "RXD", + pin26: "TXD", + pin27: "DSR", + pin28: "DTR", + pin29: "PGND", +} + +const esp32PinLabels = { + pin1: "GND", + pin2: "3V3", + pin3: "EN", + pin4: "SENSOR_VP", + pin5: "SENSOR_VN", + pin6: "IO34", + pin7: "IO35", + pin8: "IO32", + pin9: "IO33", + pin10: "IO25", + pin11: "IO26", + pin12: "IO27", + pin13: "IO14", + pin14: "IO12", + pin15: "GND", + pin16: "IO13", + pin17: "SD2", + pin18: "SD3", + pin19: "CMD", + pin20: "CLK", + pin21: "SD0", + pin22: "SD1", + pin23: "IO15", + pin24: "IO2", + pin25: "IO0", + pin26: "IO4", + pin27: "IO16", + pin28: "IO17", + pin29: "IO5", + pin30: "IO18", + pin31: "IO19", + pin32: "NC", + pin33: "IO21", + pin34: "RXD0", + pin35: "TXD0", + pin36: "IO22", + pin37: "IO23", + pin38: "GND", +} + +const jlc = (part: string) => ({ jlcpcb: [part] }) + +const ledPinLabels = { + pin1: ["anode", "pos"], + pin2: ["cathode", "neg"], +} + +const DeterministicTrace = (props: { from: string; to: string }) => ( + +) + +export default () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/docs/tutorials/esp32-wifi-test-board-schematic.mdx b/docs/tutorials/esp32-wifi-test-board-schematic.mdx new file mode 100644 index 00000000..2baa82d6 --- /dev/null +++ b/docs/tutorials/esp32-wifi-test-board-schematic.mdx @@ -0,0 +1,642 @@ +--- +title: Designing an ESP32 WiFi Test Board +description: >- + Build a schematic-first ESP32-WROOM-32E test board with a real USB-C sink, + correct CC pull-downs, a CP2102N USB-UART bridge, and Espressif's + cross-coupled DTR/RTS auto-program circuit. +--- + +import CircuitPreview from "@site/src/components/CircuitPreview" + +## Overview + +This tutorial builds a schematic-only ESP32 WiFi test board. It is a complete +reference design for bringing up USB power, USB data, UART programming, and the +ESP32 module. The source uses repository-supported tscircuit components and exact +JLCPCB assembly references, but it does not claim a routed PCB or fabrication +release. + +The board is centered on an ESP32-WROOM-32E-N4 module (JLCPCB `C701341`), a +CP2102N-A02-GQFN28R bridge (`C964632`), and a TYPE-C-31-M-12 USB-C receptacle +(`C165948`). Every major component has an explicit JLCPCB part number in the +source so the schematic can be turned into a real prototype without replacing +placeholder parts. + +The live schematic is generated from the same topology as +`codetestingplayground/esp32-wifi-test-board.circuit.tsx`: + + ({ jlcpcb: [part] }) + +const ledPinLabels = { + pin1: ["anode", "pos"], + pin2: ["cathode", "neg"], +} + +const DeterministicTrace = (props: { from: string; to: string }) => ( + +) + +export default () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) +`} /> + +## USB-C power input + +`SmdUsbC` models the C165948 16-pad USB-C receptacle, including the duplicate +VBUS, ground, and USB 2.0 data pads. `VBUS1` and `VBUS2` feed the same 5 V +net, `GND1` and `GND2` feed ground, and `DP1`/`DP2` and `DM1`/`DM2` are each +joined before reaching the CP2102N. + +A USB-C sink must advertise its power capability on both CC lines. R1 and R2 +are independent 5.1 kΩ Rd pull-downs to ground: one from `CC1` and one from +`CC2`. They are not a single resistor across the two pins. The selected +0402 resistor is JLCPCB `C25905`. + +## Power and USB-UART + +The 5 V rail enters the AMS1117-3.3 (`C6186`) through C1. C2 and C3 provide +the regulator output bulk and high-frequency decoupling. The CP2102N's `REGIN` +and `VBUS` pins see 5 V, while `VDD` is supplied from the 3.3 V rail. CP2102N +`TXD` connects to ESP32 `RXD0`, and CP2102N `RXD` connects to ESP32 `TXD0`. + +The USB data pins are connected as a differential pair. The design does not +pretend that a four-pin USB symbol is a USB-C receptacle: the actual connector +component carries all USB-C pads and the CC pins. + +## Espressif auto-program circuit + +The auto-program network follows the cross-coupled two-transistor arrangement +used by Espressif development boards: + +- `DTR` drives Q1's base through R3 and Q2's emitter. +- `RTS` drives Q2's base through R4 and Q1's emitter. +- Q1's collector pulls `EN` low. +- Q2's collector pulls `IO0` low. + +This topology matters. Merely connecting DTR and RTS to the two ESP32 pins does +not provide the same behavior when both modem-control lines are asserted. The +cross-coupled pair produces the useful states: + +| DTR | RTS | EN | IO0 | +| --- | --- | --- | --- | +| 1 | 1 | 1 | 1 | +| 0 | 0 | 1 | 1 | +| 1 | 0 | 0 | 1 | +| 0 | 1 | 1 | 0 | + +R5 and C5 provide the EN pull-up and reset capacitor. R6 and SW1 provide the +IO0 pull-up and BOOT button, while SW2 is the manual reset button. The 1 µF EN +capacitor is intentional: Espressif documents it as necessary for reliable +automatic reset with the transistor network. + +## ESP32 module and indicators + +The ESP32-WROOM-32E-N4 uses the real `jlcpcb:C701341` footprint. Power, +ground, EN, IO0, and UART0 are wired; unused module pins are explicitly marked +no-connect. IO4 drives the green status LED through R7, avoiding a load on the +IO2 strapping pin. The red power LED is driven from 3.3 V through R8. + +The source also gives every passive and button its exact JLCPCB part number and +`jlcpcb:` footprint, and names all USB data nets. The checked-in schematic SVG is +the only generated artifact. + +## Build and snapshot + +From `codetestingplayground`, run: + +```bash +bunx tsci build esp32-wifi-test-board.circuit.tsx +bunx tsci snapshot esp32-wifi-test-board.circuit.tsx +``` + +`tsci snapshot` writes `__snapshots__/esp32-wifi-test-board.circuit-schematic.snap.svg`, +the one generated artifact checked in with this tutorial. The source gives traces +deterministic names and declares logical pin labels so schematic rebuilds stay +comparable. The autorouter and DRC can fail on a schematic-only source, so use +`bunx tsci build --ignore-errors` to skip those non-fatal PCB checks. Before +creating a PCB, route and inspect it, verify the USB-C footprint and antenna +keepout, and confirm the selected JLC parts are currently in stock.