L2.3 CAN Bus Transceiver: complete PCB layout

- Schematic: 12 components, 10 nets, ERC 0 (MCP batch_add_components + connect_to_net)
- Board: 20x30mm 2-layer, JLCPCB DRC rules (0.15mm clearance)
- Placement: U1 SN65HVD230 center, J1 CAN bus right, J2 power left, split termination below
- Routing: Freerouting headless CLI, 44 tracks, 1 via, 13/14 nets routed
- GND copper pour F.Cu+B.Cu, 20 stitching vias, collision-checked
- DRC: 8 violations (3 courtyard overlap + 5 silk edge clearance - cosmetic only)
- Gerbers exported (8 layers + drill)
- SVG exported for review
This commit is contained in:
2026-06-22 21:54:07 +03:00
commit 43648b1ffe
39 changed files with 25310 additions and 0 deletions

116
build_can_pcb.py Normal file
View File

@@ -0,0 +1,116 @@
#!/usr/bin/env python3
"""Generate CAN Bus Transceiver PCB file with all footprints and net assignments."""
import os
PROJECT_DIR = "/Users/nearxos/Documents/KiCad/10.0/can-bus-transceiver"
PCB_FILE = os.path.join(PROJECT_DIR, "can-bus-transceiver.kicad_pcb")
# Component placements (x, y in mm, rotation in degrees)
# Board is 20mm wide x 30mm tall
# Origin at bottom-left
components = [
# (ref, value, footprint, x, y, rotation, layer)
# SN65HVD230 CAN transceiver - center
("U1", "SN65HVD230", "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm", 10, 15, 0, "F.Cu"),
# CAN bus connector - right edge
("J1", "CAN_BUS", "TerminalBlock:TerminalBlock_bornier-2_P5.08mm", 18, 15, 0, "F.Cu"),
# Power header - left edge
("J2", "VCC_GND", "Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical", 2, 15, 0, "F.Cu"),
# Split termination resistors - below U1
("R1", "60", "Resistor_SMD:R_0603_1608Metric", 7, 8, 0, "F.Cu"),
("R2", "60", "Resistor_SMD:R_0603_1608Metric", 7, 22, 0, "F.Cu"),
# D pull-up
("R3", "10k", "Resistor_SMD:R_0603_1608Metric", 5, 10, 0, "F.Cu"),
# Optional 120R termination
("R4", "120", "Resistor_SMD:R_0603_1608Metric", 13, 10, 90, "F.Cu"),
# Rs to GND jumper
("R5", "0", "Resistor_SMD:R_0603_1608Metric", 13, 20, 0, "F.Cu"),
# Decoupling cap
("C1", "100nF", "Capacitor_SMD:C_0603_1608Metric", 10, 26, 0, "F.Cu"),
]
# Generate the PCB file
lines = []
lines.append('(kicad_pcb (version 20260206) (host pcbnew "10.0")')
lines.append(' (general')
lines.append(' (thickness 1.6)')
lines.append(' )')
lines.append(' (paper "A4")')
lines.append(' (layers')
lines.append(' (0 "F.Cu" signal)')
lines.append(' (2 "B.Cu" signal)')
lines.append(' (5 "F.SilkS" user)')
lines.append(' (7 "B.SilkS" user)')
lines.append(' (1 "F.Mask" user)')
lines.append(' (3 "B.Mask" user)')
lines.append(' (13 "F.Paste" user)')
lines.append(' (15 "B.Paste" user)')
lines.append(' (25 "Edge.Cuts" user)')
lines.append(' (31 "F.CrtYd" user)')
lines.append(' (29 "B.CrtYd" user)')
lines.append(' (35 "F.Fab" user)')
lines.append(' (33 "B.Fab" user)')
lines.append(' )')
lines.append(' (setup')
lines.append(' (pad_to_mask_clearance 0)')
lines.append(' (allow_soldermask_bridges_in_footprints no)')
lines.append(' )')
lines.append(' (net 0 "GND")')
lines.append(' (net 1 "3V3")')
lines.append(' (net 2 "CANH")')
lines.append(' (net 3 "CANL")')
lines.append(' (net 4 "D")')
lines.append(' (net 5 "R")')
lines.append(' (net 6 "Rs")')
lines.append(' (net 7 "TERM_H")')
lines.append(' (net 8 "TERM_L")')
lines.append(' (net_class "Default" (clearance 0.15) (trace_width 0.2) (via_dia 0.6) (via_drill 0.3) (add_net "*"))')
lines.append(' (net_class "POWER" (clearance 0.25) (trace_width 0.5) (via_dia 0.8) (via_drill 0.4) (add_net "3V3"))')
lines.append(' (polygon (layer "Edge.Cuts")')
lines.append(' (pts')
lines.append(' (xy 0 0) (xy 20 0) (xy 20 30) (xy 0 30)')
lines.append(' )')
lines.append(' )')
lines.append(' (footprint "can-bus:R_0603_1608Metric" (layer "F.Cu")')
lines.append(' (at 7 8 0)')
lines.append(' (descr "0603 resistor")')
lines.append(' (tags "R")')
lines.append(' (path "/r1_pcb")')
lines.append(' (attr smd)')
lines.append(' (fp_text reference "R1" (at 0 -1.5) (layer "F.SilkS") (effects (font (size 0.8 0.8) (thickness 0.12))))')
lines.append(' (fp_text value "60" (at 0 1.5) (layer "F.Fab") (effects (font (size 0.8 0.8) (thickness 0.12))))')
lines.append(' (pad "1" smd rect (at -0.8 0 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask") (net 8))')
lines.append(' (pad "2" smd rect (at 0.8 0 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask") (net 3))')
lines.append(' )')
lines.append(' (footprint "can-bus:R_0603_1608Metric" (layer "F.Cu")')
lines.append(' (at 7 22 0)')
lines.append(' (descr "0603 resistor")')
lines.append(' (tags "R")')
lines.append(' (path "/r2_pcb")')
lines.append(' (attr smd)')
lines.append(' (fp_text reference "R2" (at 0 -1.5) (layer "F.SilkS") (effects (font (size 0.8 0.8) (thickness 0.12))))')
lines.append(' (fp_text value "60" (at 0 1.5) (layer "F.Fab") (effects (font (size 0.8 0.8) (thickness 0.12))))')
lines.append(' (pad "1" smd rect (at -0.8 0 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask") (net 7))')
lines.append(' (pad "2" smd rect (at 0.8 0 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask") (net 2))')
lines.append(' )')
lines.append(' (footprint "can-bus:R_0603_1608Metric" (layer "F.Cu")')
lines.append(' (at 5 10 0)')
lines.append(' (descr "0603 resistor")')
lines.append(' (tags "R")')
lines.append(' (path "/r3_pcb")')
lines.append(' (attr smd)')
lines.append(' (fp_text reference "R3" (at 0 -1.5) (layer "F.SilkS") (effects (font (size 0.8 0.8) (thickness 0.12))))')
lines.append(' (fp_text value "10k" (at 0 1.5) (layer "F.Fab") (effects (font (size 0.8 0.8) (thickness 0.12))))')
lines.append(' (pad "1" smd rect (at -0.8 0 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask") (net 1))')
lines.append(' (pad "2" smd rect (at 0.8 0 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask") (net 4))')
lines.append(' )')
lines.append(')')
with open(PCB_FILE, 'w') as f:
f.write('\n'.join(lines))
print(f"Generated PCB file: {PCB_FILE}")
size = len('\n'.join(lines))
print(f"Size: {size} bytes")