Files
metabuilder/pcbgenerator/examples/esp32_dev_board.py
2026-01-21 17:18:12 +00:00

163 lines
4.6 KiB
Python

from pathlib import Path
from boardforge import PCB, Layer
BASE_DIR = Path(__file__).resolve().parent
FONT_PATH = BASE_DIR.parent / "fonts" / "RobotoMono.ttf"
OUTPUT_DIR = BASE_DIR.parent / "output"
def build_board():
board = PCB(width=60, height=35)
board.set_layer_stack([
Layer.TOP_COPPER.value,
Layer.BOTTOM_COPPER.value,
Layer.TOP_SILK.value,
Layer.BOTTOM_SILK.value,
])
# Mounting holes
holes = [(3, 3), (57, 3), (3, 32), (57, 32)]
for i, (x, y) in enumerate(holes):
h = board.add_component("MTG", ref=f"H{i+1}", at=(x, y))
h.add_pin("P", dx=0, dy=0)
h.add_pad("P", dx=0, dy=0, w=1.5, h=1.5)
# ESP32 module
esp32 = board.add_component("ESP32", ref="U1", at=(20, 10))
for name, dx, dy in [
("3V3", -2, 2),
("GND", -2, -2),
("EN", 0, 2),
("IO0", 0, -2),
("TX", 2, 2),
("RX", 2, -2),
]:
esp32.add_pin(name, dx=dx, dy=dy)
esp32.add_pad(name, dx=dx, dy=dy, w=1, h=1)
# CH340C USB-UART bridge
ch340 = board.add_component("CH340C", ref="U2", at=(42, 10))
for name, dx, dy in [
("TXD", -2, 1),
("RXD", -2, -1),
("GND", 2, -1),
("VCC", 2, 1),
]:
ch340.add_pin(name, dx=dx, dy=dy)
ch340.add_pad(name, dx=dx, dy=dy, w=1, h=1)
# Voltage regulator
ldo = board.add_component("AMS1117", ref="U3", at=(30, 25))
for name, dx, dy in [
("VIN", -2, 0),
("VOUT", 2, 0),
("GND", 0, 2),
]:
ldo.add_pin(name, dx=dx, dy=dy)
ldo.add_pad(name, dx=dx, dy=dy, w=1, h=1)
# USB-C connector
usb = board.add_component("USB-C", ref="J1", at=(30, 0))
for name, dx, dy in [
("VBUS", 0, 0),
("GND", 5, 0),
("D+", 2, 1),
("D-", 2, -1),
]:
usb.add_pin(name, dx=dx, dy=dy)
usb.add_pad(name, dx=dx, dy=dy, w=1, h=1)
# Decoupling capacitors
for i, x in enumerate([25, 28, 31]):
c = board.add_component("CAP", ref=f"C{i+1}", at=(x, 15))
c.add_pin("1", dx=-0.5, dy=0)
c.add_pin("2", dx=0.5, dy=0)
c.add_pad("1", dx=-0.5, dy=0, w=0.8, h=0.8)
c.add_pad("2", dx=0.5, dy=0, w=0.8, h=0.8)
# Boot and reset buttons
boot = board.add_component("SW", ref="SW_BOOT", at=(10, 20))
boot.add_pin("1", dx=-0.5, dy=0)
boot.add_pin("2", dx=0.5, dy=0)
boot.add_pad("1", dx=-0.5, dy=0, w=1, h=1)
boot.add_pad("2", dx=0.5, dy=0, w=1, h=1)
reset = board.add_component("SW", ref="SW_RESET", at=(10, 25))
reset.add_pin("1", dx=-0.5, dy=0)
reset.add_pin("2", dx=0.5, dy=0)
reset.add_pad("1", dx=-0.5, dy=0, w=1, h=1)
reset.add_pad("2", dx=0.5, dy=0, w=1, h=1)
# Left GPIO header
header_left = board.add_component("HDR", ref="J2", at=(5, 5))
for i, name in enumerate(["IO0", "IO1", "IO2", "IO3", "GND"]):
dy = -4 + i * 2
header_left.add_pin(name, dx=0, dy=dy)
header_left.add_pad(name, dx=0, dy=dy, w=1, h=1)
# Right GPIO header
header_right = board.add_component("HDR", ref="J3", at=(55, 5))
for i, name in enumerate(["3V3", "GND", "TX", "RX", "IO4"]):
dy = -4 + i * 2
header_right.add_pin(name, dx=0, dy=dy)
header_right.add_pad(name, dx=0, dy=dy, w=1, h=1)
# Manual traces with bends
board.trace_path([
usb.pin("VBUS"),
(30, 5),
(30, 20),
ldo.pin("VIN"),
])
board.trace_path([
ldo.pin("VOUT"),
(28, 25),
(20, 15),
esp32.pin("3V3"),
])
board.trace_path([
ch340.pin("TXD"),
(40, 12),
(28, 12),
esp32.pin("RX"),
])
board.trace_path([
ch340.pin("RXD"),
(40, 14),
(28, 14),
esp32.pin("TX"),
])
board.trace_path([
boot.pin("1"),
(12, 20),
(18, 12),
esp32.pin("IO0"),
])
board.trace_path([
reset.pin("1"),
(12, 25),
(18, 13),
esp32.pin("EN"),
])
# GND traces
board.route_trace("SW_BOOT:2", "U1:GND")
board.route_trace("SW_RESET:2", "U1:GND")
board.route_trace("U3:GND", "U1:GND")
board.route_trace("U2:GND", "U1:GND")
board.add_text_ttf("ESP32 Dev Board", font_path=str(FONT_PATH), at=(5, 32), size=1.2, layer=Layer.TOP_SILK.value)
board.add_text_ttf("USB-C", font_path=str(FONT_PATH), at=(28, 2), size=1.0, layer=Layer.TOP_SILK.value)
return board
def main():
board = build_board()
board.save_svg_previews(str(OUTPUT_DIR))
board.export_gerbers(OUTPUT_DIR / "esp32_dev_board.zip")
if __name__ == "__main__":
main()