148 lines
5.7 KiB
Python
148 lines
5.7 KiB
Python
#!/usr/bin/env python3
|
|
"""ESP32-S3 Sensor Node — PCB Generator v3. Tabs, like pcbnew."""
|
|
import os
|
|
T = '\t'
|
|
|
|
PCB = os.path.expanduser("~/Documents/KiCad/10.0/esp32-s3-sensor-node.kicad_pcb")
|
|
NETS = ["GND","3V3","VBUS","EN","IO0","IO12","SDA","SCL","USB_D_P","USB_D_N","CC1","CC2","IO2_LED","D1_A","RXD0","TXD0"]
|
|
W,H = 65.0,40.0
|
|
|
|
def ni(n): return NETS.index(n) if n in NETS else -1
|
|
|
|
def smd(n,x,y,w,h,net,rot=0):
|
|
return f'{T*4}(pad "{n}" smd rect (at {x:.3f} {y:.3f} {rot}) (size {w:.3f} {h:.3f}) (layers "F.Cu" "F.Paste" "F.Mask")' + (f' (net {ni(net)})' if ni(net)>=0 else '') + ')'
|
|
|
|
def fp(ref,lib,x,y,rot,pads):
|
|
p = [f'{T*3}(footprint "{lib}"', f'{T*4}(layer "F.Cu")', f'{T*4}(at {x:.3f} {y:.3f} {rot})',
|
|
f'{T*4}(descr "{ref}")',
|
|
f'{T*4}(property "Reference" "{ref}" (at {x:.3f} {y-3:.3f}) (layer "F.SilkS") (effects (font (size 1 1) (thickness 0.15))))',
|
|
f'{T*4}(property "Value" "{ref}" (at {x:.3f} {y+3:.3f}) (layer "F.Fab") (effects (font (size 1 1) (thickness 0.15))))']
|
|
p += [f'{T*4}{x}' for x in pads]
|
|
p.append(f'{T*3})')
|
|
return '\n'.join(p)
|
|
|
|
FR = '"Resistor_SMD:R_0603_1608Metric"'
|
|
FC = '"Capacitor_SMD:C_0603_1608Metric"'
|
|
FC8 = '"Capacitor_SMD:C_0805_2012Metric"'
|
|
FL = '"LED_SMD:LED_0603_1608Metric"'
|
|
FP4 = '"Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical"'
|
|
FU = '"Connector_USB:USB_C_Receptacle_USB2.0_16P"'
|
|
FE = '"RF_Module:ESP32-S3-WROOM-1"'
|
|
FS = '"Package_TO_SOT_SMD:SOT-223-3Lead_TabPin2"'
|
|
|
|
passives = [
|
|
("R1",FR,55,30,0,"IO2_LED","D1_A"), ("R2",FR,27,32,0,"EN","3V3"),
|
|
("R3",FR,16,7,0,"IO0","3V3"), ("R4",FR,16,12,0,"IO12","GND"),
|
|
("R5",FR,48,24,0,"SDA","3V3"), ("R6",FR,48,22,0,"SCL","3V3"),
|
|
("R7",FR,11,28,0,"CC1","GND"), ("R8",FR,11,25,0,"CC2","GND"),
|
|
("C1",FC,30,28,0,"3V3","GND"), ("C2",FC,30,25,0,"3V3","GND"),
|
|
("C3",FC,30,22,0,"3V3","GND"), ("C4",FC,26,35,0,"EN","GND"),
|
|
("C5",FC8,24,17,0,"VBUS","GND"), ("C6",FC8,24,23,0,"3V3","GND"),
|
|
]
|
|
|
|
lines = []
|
|
lines.append('(kicad_pcb')
|
|
lines.append(f'{T}(version 20260206)')
|
|
lines.append(f'{T}(generator "pcbnew")')
|
|
lines.append(f'{T}(generator_version "10.0")')
|
|
lines.append(f'{T}(general')
|
|
lines.append(f'{T*2}(thickness 1.6)')
|
|
lines.append(f'{T*2}(legacy_teardrops no)')
|
|
lines.append(f'{T})')
|
|
lines.append(f'{T}(paper "A4")')
|
|
lines.append(f'{T}(layers')
|
|
for n,c,t in [(0,"F.Cu","signal"),(2,"B.Cu","signal"),(13,"F.Paste","user"),(15,"B.Paste","user"),
|
|
(5,"F.SilkS","user"),(7,"B.SilkS","user"),
|
|
(1,"F.Mask","user"),(3,"B.Mask","user"),
|
|
(25,"Edge.Cuts","user"),(31,"F.CrtYd","user"),(29,"B.CrtYd","user"),
|
|
(35,"F.Fab","user"),(33,"B.Fab","user")]:
|
|
lines.append(f'{T*2}({n} "{c}" {t})')
|
|
lines.append(f'{T})')
|
|
lines.append(f'{T}(setup')
|
|
lines.append(f'{T*2}(pad_to_mask_clearance 0)')
|
|
lines.append(f'{T*2}(allow_soldermask_bridges_in_footprints no)')
|
|
lines.append(f'{T*2}(copper_edge_clearance 0.3)')
|
|
lines.append(f'{T})')
|
|
|
|
# Nets
|
|
lines.append(f'{T}(nets')
|
|
for i,n in enumerate(NETS):
|
|
lines.append(f'{T*2}(net {i} "{n}")')
|
|
lines.append(f'{T})')
|
|
|
|
# Net classes
|
|
lines.append(f'{T}(net_class "Default" (clearance 0.15) (trace_width 0.2) (via_dia 0.6) (via_drill 0.3) (add_net "*"))')
|
|
lines.append(f'{T}(net_class "POWER" (clearance 0.25) (trace_width 0.5) (via_dia 0.8) (via_drill 0.4) (add_net "3V3") (add_net "VBUS"))')
|
|
|
|
# Board outline
|
|
lines.append(f'{T}(polygon (layer "Edge.Cuts")')
|
|
lines.append(f'{T*2}(pts')
|
|
lines.append(f'{T*3}(xy 0 0)')
|
|
lines.append(f'{T*3}(xy {W} 0)')
|
|
lines.append(f'{T*3}(xy {W} {H})')
|
|
lines.append(f'{T*3}(xy 0 {H})')
|
|
lines.append(f'{T*2})')
|
|
lines.append(f'{T})')
|
|
|
|
# Footprints
|
|
# J1 USB-C
|
|
lines.append(fp("J1",FU,7,20,0,[
|
|
smd("SH",-3,0,2,2,"GND"), smd("A1",-2,5,1.5,1.5,"GND"),
|
|
smd("A4",-2,-5,1.5,1.5,"VBUS"), smd("A5",-2,-3,1.5,0.8,"CC1"),
|
|
smd("A6",-2,-1,1.5,0.8,"USB_D_P"), smd("A7",-2,1,1.5,0.8,"USB_D_N"),
|
|
smd("B5",-2,3,1.5,0.8,"CC2"),
|
|
smd("B6",-2,0,1.5,0.8,"USB_D_P"), smd("B7",-2,2,1.5,0.8,"USB_D_N"),
|
|
]))
|
|
# U2 AMS1117
|
|
lines.append(fp("U2",FS,20,20,0,[
|
|
smd("1",-2.3,-3,1.5,1,"GND"), smd("2",0,3,2.5,2.5,"3V3"),
|
|
smd("3",0,-3,2.5,2.5,"VBUS"),
|
|
]))
|
|
# U1 ESP32-S3
|
|
lines.append(fp("U1",FE,38,20,0,[
|
|
smd("1",-8,8,1.5,1.5,"GND"), smd("2",-8,-8,1.5,1.5,"3V3"),
|
|
smd("3",-8,-6,1,1,"EN"), smd("4",-8,-4,1,1,"SDA"),
|
|
smd("5",-8,-2,1,1,"SCL"), smd("13",8,-4,1,1,"USB_D_N"),
|
|
smd("14",8,-2,1,1,"USB_D_P"), smd("20",-8,4,1,1,"IO12"),
|
|
smd("27",-8,0,1,1,"IO0"), smd("36",8,-8,1,1,"RXD0"),
|
|
smd("37",8,-6,1,1,"TXD0"), smd("38",-8,2,1,1,"IO2_LED"),
|
|
]))
|
|
# J2 I2C
|
|
lines.append(fp("J2",FP4,56,20,0,[
|
|
smd("1",0,3.81,1.5,1.5,"3V3"), smd("2",0,1.27,1.5,1.5,"SDA"),
|
|
smd("3",0,-1.27,1.5,1.5,"SCL"), smd("4",0,-3.81,1.5,1.5,"GND"),
|
|
]))
|
|
# J3 PROG
|
|
lines.append(fp("J3",FP4,25,3,0,[
|
|
smd("1",0,-3.81,1.5,1.5,"GND"), smd("2",0,-1.27,1.5,1.5,"RXD0"),
|
|
smd("3",0,1.27,1.5,1.5,"TXD0"), smd("4",0,3.81,1.5,1.5,"3V3"),
|
|
]))
|
|
# D1 LED
|
|
lines.append(fp("D1",FL,55,34,0,[
|
|
smd("1",-0.8,0,0.8,0.8,"GND"), smd("2",0.8,0,0.8,0.8,"D1_A"),
|
|
]))
|
|
# Passives
|
|
for ref,lib,x,y,rot,n1,n2 in passives:
|
|
lines.append(fp(ref,lib,x,y,rot,[
|
|
smd("1",-0.8,0.9,0.8,0.8,n1), smd("2",-0.8,-0.9,0.8,0.8,n2),
|
|
]))
|
|
|
|
# Zones
|
|
for layer in ["F.Cu","B.Cu"]:
|
|
lines.append(f'{T}(zone (net {ni("GND")}) (layer "{layer}")')
|
|
lines.append(f'{T*2}(polygon (pts (xy 0 0)(xy {W} 0)(xy {W} {H})(xy 0 {H})))')
|
|
lines.append(f'{T*2}(fill (mode solid))')
|
|
lines.append(f'{T})')
|
|
# Antenna keepout zones
|
|
for layer in ["F.Cu","B.Cu"]:
|
|
lines.append(f'{T}(zone (net 0) (layer "{layer}") (priority 1)')
|
|
lines.append(f'{T*2}(polygon (pts (xy 46 28)(xy {W} 28)(xy {W} {H})(xy 46 {H})))')
|
|
lines.append(f'{T*2}(fill (mode solid))')
|
|
lines.append(f'{T})')
|
|
|
|
lines.append(')')
|
|
|
|
result = '\n'.join(lines) + '\n'
|
|
open(PCB,'w').write(result)
|
|
print(f"Written {len(result)} bytes")
|