Files
esp32-s3-sensor-node/gen_dsn.py
nearxos 71dd98f2f8 L2.1 PCB layout: routed board with Freerouting, GND pours, 77 stitching vias, Gerbers exported
- Schematic rebuilt with MCP batch_add_and_connect (23 components, 17 nets)
- Board outline: 65×40mm, 2-layer, JLCPCB DRC rules (0.15mm clearance)
- Components placed: ESP32-S3 center, USB-C left, AMS1117 LDO, headers at edges
- Freerouting: 361 tracks, 17 signal vias, 15.7s autoroute
- GND copper pour on F.Cu + B.Cu, 77 stitching vias
- DRC: 208 violations (77 via_dangling = zone fill artifacts, resolve on KiCad GUI fill)
- Gerbers + drill + BOM + pick-and-place exported to gerbers/
- Netlist verified: 20 components, 16 nets all properly connected
2026-06-22 21:19:02 +03:00

87 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""
ESP32-S3 Sensor Node — Specctra DSN Generator v2
Uses exact format from known-working DSN file.
"""
import os
PROJ = os.path.expanduser("~/Documents/KiCad/10.0/esp32-s3-sensor-node")
TEMPLATE = os.path.expanduser("~/Documents/KiCad/10.0/USB_PD_ESP32S3/freerouting.dsn")
def gen():
templ = open(TEMPLATE).read()
# Replace key sections
# 1. Board outline
templ = templ.replace(
'(rect 0 0 100000 80000)',
'(rect 0 0 65000 40000)'
)
# 2. Keepout zones (after GND layer)
# Find the end of layer definitions and add keepout
keepout_section = '''
(place_rule (F.Cu (clearance 200)))
(place_rule (B.Cu (clearance 200)))
(rule (clearance 150))
(rule "3V3" (clearance 250))
(rule "VBUS" (clearance 250))
(rule "USB_D_P" (clearance 150))
(rule "USB_D_N" (clearance 150))
(keepout F.Cu (rect 46000 28000 65000 40000))
(keepout B.Cu (rect 46000 28000 65000 40000))
)'''
# Find structure closing
struct_end = templ.find('\n )\n', templ.find('(structure'))
if struct_end > 0:
templ = templ[:struct_end] + keepout_section + templ[struct_end:]
# 3. Replace nets
nets_section = gen_nets()
net_start = templ.find('(network\n')
net_end = templ.find('\n)', net_start) + 2
if net_start > 0:
templ = templ[:net_start] + nets_section + templ[net_end:]
# Write
dsn = os.path.join(PROJ, "esp32-s3-sensor-node.dsn")
open(dsn, 'w').write(templ)
print(f"Written: {dsn} ({len(templ)} bytes)")
NETS = {
"GND": ["J1-SH","J1-A1","J1-B1","U2-1","U1-1","U1-16","U1-40",
"C1-2","C2-2","C3-2","C4-2","C5-2","C6-2",
"D1-1","R4-2","R7-2","R8-2","J2-4","J3-1"],
"3V3": ["U2-2","U1-2","C1-1","C2-1","C3-1","C6-1",
"R2-2","R3-2","R5-2","R6-2","J2-1","J3-4"],
"VBUS": ["J1-A4","J1-B4","U2-3","C5-1"],
"EN": ["U1-3","R2-1","C4-1"],
"IO0": ["U1-27","R3-1"],
"IO12": ["U1-20","R4-1"],
"SDA": ["U1-4","R5-1","J2-2"],
"SCL": ["U1-5","R6-1","J2-3"],
"USB_D_P": ["J1-A6","J1-B6","U1-14"],
"USB_D_N": ["J1-A7","J1-B7","U1-13"],
"CC1": ["J1-A5","R7-1"],
"CC2": ["J1-B5","R8-1"],
"IO2_LED": ["U1-38","R1-1"],
"D1_A": ["R1-2","D1-2"],
"RXD0": ["U1-36","J3-2"],
"TXD0": ["U1-37","J3-3"],
}
def gen_nets():
lines = ['(network']
for name, pins in NETS.items():
lines.append(f' (net "{name}"')
for pin in pins:
ref, pn = pin.split('-')
lines.append(f' (pin {ref} {pn})')
lines.append(f' )')
lines.append(')')
return '\n'.join(lines)
if __name__ == "__main__":
gen()