ESP32-S3 Sensor Node L2.1 — schematic ERC 0, PCB outline+placement, README
This commit is contained in:
172
finalize.py
Normal file
172
finalize.py
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate a complete importable KiCad project for ESP32-S3 Sensor Node.
|
||||
Creates netlist, component placement guide, and README.
|
||||
"""
|
||||
import os, json
|
||||
|
||||
PROJ_DIR = os.path.expanduser("~/Documents/KiCad/10.0/esp32-s3-sensor-node")
|
||||
SCH = os.path.join(PROJ_DIR, "esp32-s3-sensor-node.kicad_sch")
|
||||
PRO = os.path.join(PROJ_DIR, "esp32-s3-sensor-node.kicad_pro")
|
||||
|
||||
NETS = ["GND","3V3","VBUS","EN","IO0","IO12",
|
||||
"SDA","SCL","USB_D_P","USB_D_N",
|
||||
"CC1","CC2","IO2_LED","D1_A","RXD0","TXD0"]
|
||||
|
||||
PASSIVES = [
|
||||
("R1", "Resistor_SMD:R_0603_1608Metric", 55, 30, 0, "IO2_LED", "D1_A", "470"),
|
||||
("R2", "Resistor_SMD:R_0603_1608Metric", 27, 32, 0, "EN", "3V3", "10k"),
|
||||
("R3", "Resistor_SMD:R_0603_1608Metric", 16, 7, 0, "IO0", "3V3", "10k"),
|
||||
("R4", "Resistor_SMD:R_0603_1608Metric", 16, 12, 0, "IO12", "GND", "10k"),
|
||||
("R5", "Resistor_SMD:R_0603_1608Metric", 48, 24, 0, "SDA", "3V3", "4.7k"),
|
||||
("R6", "Resistor_SMD:R_0603_1608Metric", 48, 22, 0, "SCL", "3V3", "4.7k"),
|
||||
("R7", "Resistor_SMD:R_0603_1608Metric", 11, 28, 0, "CC1", "GND", "5.1k"),
|
||||
("R8", "Resistor_SMD:R_0603_1608Metric", 11, 25, 0, "CC2", "GND", "5.1k"),
|
||||
("C1", "Capacitor_SMD:C_0603_1608Metric", 30, 28, 0, "3V3", "GND", "100nF"),
|
||||
("C2", "Capacitor_SMD:C_0603_1608Metric", 30, 25, 0, "3V3", "GND", "100nF"),
|
||||
("C3", "Capacitor_SMD:C_0603_1608Metric", 30, 22, 0, "3V3", "GND", "10uF"),
|
||||
("C4", "Capacitor_SMD:C_0603_1608Metric", 26, 35, 0, "EN", "GND", "100nF"),
|
||||
("C5", "Capacitor_SMD:C_0805_2012Metric", 24, 17, 0, "VBUS", "GND", "10uF"),
|
||||
("C6", "Capacitor_SMD:C_0805_2012Metric", 24, 23, 0, "3V3", "GND", "10uF"),
|
||||
]
|
||||
|
||||
ICS = [
|
||||
("J1", "Connector_USB:USB_C_Receptacle_USB2.0_16P",
|
||||
7, 20, 0, "USB-C", [("SH","GND"),("A1","GND"),("A4","VBUS"),
|
||||
("A5","CC1"),("A6","USB_D_P"),("A7","USB_D_N"),("B5","CC2")]),
|
||||
("U2", "Package_TO_SOT_SMD:SOT-223-3Lead_TabPin2",
|
||||
20, 20, 0, "AMS1117-3.3", [("1","GND"),("2","3V3"),("3","VBUS")]),
|
||||
("U1", "RF_Module:ESP32-S3-WROOM-1",
|
||||
38, 20, 0, "ESP32-S3-WROOM-1", [("1","GND"),("2","3V3"),("3","EN"),
|
||||
("4","SDA"),("5","SCL"),("13","USB_D_N"),("14","USB_D_P"),
|
||||
("20","IO12"),("27","IO0"),("36","RXD0"),("37","TXD0"),("38","IO2_LED")]),
|
||||
("J2", "Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical",
|
||||
56, 20, 0, "I2C_Sensor", [("1","3V3"),("2","SDA"),("3","SCL"),("4","GND")]),
|
||||
("J3", "Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical",
|
||||
25, 3, 0, "PROG", [("1","GND"),("2","RXD0"),("3","TXD0"),("4","3V3")]),
|
||||
("D1", "LED_SMD:LED_0603_1608Metric",
|
||||
55, 34, 0, "LED_Green", [("1","GND"),("2","D1_A")]),
|
||||
]
|
||||
|
||||
def create_readme():
|
||||
md = f"""# ESP32-S3 Sensor Node — L2.1 Training Exercise
|
||||
|
||||
## Project Setup
|
||||
|
||||
1. **Open in KiCad 10.0+** — File → Open Project → `{PROJ_DIR}`
|
||||
2. **Schematic** — Already clean (ERC 0). View in Eeschema.
|
||||
3. **PCB Layout** — Needs routing. Create board in Pcbnew.
|
||||
|
||||
## PCB Spec
|
||||
- **Size:** 65 × 40mm, 2-layer
|
||||
- **Stackup:** 1.6mm FR4, 1oz copper, HASL
|
||||
- **Design rules:** trace/space 0.15mm, drill 0.3mm, annular 0.15mm
|
||||
- **Target fab:** JLCPCB / PCBWay standard
|
||||
|
||||
## Component Placement
|
||||
|
||||
```
|
||||
Board: (0,0) bottom-left, (65,40) top-right
|
||||
|
||||
Left edge (x≈5-15):
|
||||
J1 USB-C @ (7, 20) — left edge, USB mating face outward
|
||||
R7 CC1 pull-down @ (11, 28)
|
||||
R8 CC2 pull-down @ (11, 25)
|
||||
|
||||
Lower-left (x≈15-25, y≈3-15):
|
||||
J3 PROG header @ (25, 3) — bottom edge
|
||||
R3 IO0 pull-up @ (16, 7)
|
||||
R4 IO12 pull-down @ (16, 12)
|
||||
|
||||
Center-left (x≈20-30):
|
||||
U2 AMS1117-3.3 @ (20, 20) — regulator
|
||||
C5 10µF input @ (24, 17) — near U2 pin 3 (VI)
|
||||
C6 10µF output @ (24, 23) — near U2 pin 2 (VO)
|
||||
|
||||
Center (x≈27-38):
|
||||
R2 EN pull-up @ (27, 32)
|
||||
C4 EN cap @ (26, 35)
|
||||
C1-C3 decoupling @ (30, 22-28) — near U1 3V3 pins
|
||||
U1 ESP32-S3 @ (38, 20) — main module
|
||||
|
||||
Right side (x≈48-58):
|
||||
R5 SDA pull-up @ (48, 24)
|
||||
R6 SCL pull-up @ (48, 22)
|
||||
J2 I2C connector @ (56, 20) — right edge
|
||||
D1 Status LED @ (55, 34) — top-right edge
|
||||
R1 LED resistor @ (55, 30)
|
||||
```
|
||||
|
||||
## Antenna Keepout
|
||||
- **Zone:** x > 46mm, y > 28mm (top-right corner)
|
||||
- No copper, no traces, no components in this area
|
||||
- The ESP32-S3-WROOM-1 module has its PCB antenna at the top-right corner
|
||||
|
||||
## Routing Order
|
||||
1. **USB differential pair** — USB_D_P / USB_D_N: 90Ω impedance, length-matched
|
||||
- Width: ~0.3mm on 1.6mm FR4 (calc with fab's tool)
|
||||
- Gap: ~0.15mm
|
||||
- Route on top layer, GND reference on bottom
|
||||
2. **3V3 power** — 0.5mm traces from U2 VO to U1 3V3 pin + all 3V3 nodes
|
||||
3. **VBUS power** — 0.5mm from J1 to U2 VI
|
||||
4. **GND** — Copper pours on both layers with stitching vias
|
||||
5. **I2C** — SDA/SCL routed together, away from noisy traces
|
||||
6. **UART** — RXD0/TXD0 to J3
|
||||
7. **Strapping** — EN, IO0, IO12 to pull resistors
|
||||
8. **LED** — IO2_LED through R1 to D1
|
||||
|
||||
## GND Pour Strategy
|
||||
- **B.Cu (bottom):** Full copper pour, entire board area
|
||||
- **F.Cu (top):** Full copper pour EXCEPT antenna keepout zone
|
||||
- **Antenna keepout:** Keepout zone polygon on both layers (no copper)
|
||||
- **Stitching vias:** Perimeter every 5mm, plus around module GND pads
|
||||
|
||||
## Files
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `*.kicad_sch` | Schematic (ERC 0) |
|
||||
| `*.kicad_pcb` | PCB layout (empty, needs routing) |
|
||||
| `*.kicad_pro` | Project file |
|
||||
| `gen_schematic.py` | Python schematic generator |
|
||||
| `gen_pcb.py` | Python PCB generator (outline + placement) |
|
||||
"""
|
||||
path = os.path.join(PROJ_DIR, "README.md")
|
||||
with open(path, 'w') as f:
|
||||
f.write(md)
|
||||
print(f"Written: {path}")
|
||||
|
||||
def create_placement_csv():
|
||||
"""Placement file for reference."""
|
||||
path = os.path.join(PROJ_DIR, "placement.csv")
|
||||
with open(path, 'w') as f:
|
||||
f.write("Ref,Footprint,X(mm),Y(mm),Rotation,Net1,Net2\n")
|
||||
for ref, fp, x, y, rot, n1, n2, val in PASSIVES:
|
||||
f.write(f"{ref},{fp},{x},{y},{rot},{n1},{n2}\n")
|
||||
for ref, fp, x, y, rot, val, pins in ICS:
|
||||
nets = ", ".join(f"{p[0]}={p[1]}" for p in pins)
|
||||
f.write(f"{ref},{fp},{x},{y},{rot},{nets}\n")
|
||||
print(f"Written: {path}")
|
||||
|
||||
def update_project():
|
||||
"""Update .kicad_pro with correct board path."""
|
||||
# Read existing
|
||||
if os.path.exists(PRO):
|
||||
with open(PRO) as f:
|
||||
config = json.load(f)
|
||||
else:
|
||||
config = {"board": {}}
|
||||
|
||||
# Ensure board settings exist
|
||||
config["board"] = config.get("board", {})
|
||||
config["board"]["design_settings"] = config["board"].get("design_settings", {})
|
||||
|
||||
with open(PRO, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
print(f"Updated: {PRO}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_readme()
|
||||
create_placement_csv()
|
||||
update_project()
|
||||
print("\nDone! Open the project in KiCad GUI:")
|
||||
print(f" File → Open Project → {PROJ_DIR}/esp32-s3-sensor-node.kicad_pro")
|
||||
Reference in New Issue
Block a user