Files
florian.berthold d43c7976ad Add panel-to-PCB mounting system with M3 standoffs
Panel alignment:
- PCB offset 10mm from panel top
- Component holes aligned: OLED@25mm, jacks@45mm, button@58mm
- 4x M3 standoff holes at corners (5,5), (35,5), (5,75), (35,75)

Updates:
- Panel SVG and spec aligned with PCB layout
- Mounting holes added to PCB (Edge.Cuts layer)
- Regenerated Gerbers with mounting holes
- Updated autoroute.py to add mounting holes automatically

DRC: 0 unconnected, 7 cosmetic errors (courtyard overlaps)
2026-01-23 08:15:25 +01:00

117 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""
SN-L00 Command-Line Autoroute Pipeline
Run from terminal: python3 scripts/autoroute_cli.py
Requires: kicad-cli or pcbnew Python module available
"""
import subprocess
import os
import sys
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
KICAD_DIR = os.path.dirname(SCRIPT_DIR)
PCB_FILE = os.path.join(KICAD_DIR, "SN-L00.kicad_pcb")
DSN_FILE = os.path.join(KICAD_DIR, "SN-L00.dsn")
SES_FILE = os.path.join(KICAD_DIR, "SN-L00.ses")
FREEROUTING_JAR = "/tmp/freerouting.jar"
FREEROUTING_URL = "https://github.com/freerouting/freerouting/releases/download/v2.0.1/freerouting-2.0.1.jar"
def run(cmd, desc, cwd=None):
"""Run command with description"""
print(f" {desc}...")
result = subprocess.run(cmd, capture_output=True, text=True, cwd=cwd)
if result.returncode != 0:
print(f" ERROR: {result.stderr}")
return False
return True
def main():
print("=" * 50)
print("SN-L00 Command-Line Autoroute Pipeline")
print("=" * 50)
# Check for kicad-cli
kicad_cli = None
for path in ["/usr/bin/kicad-cli", "/usr/local/bin/kicad-cli",
"/Applications/KiCad/KiCad.app/Contents/MacOS/kicad-cli"]:
if os.path.exists(path):
kicad_cli = path
break
if not kicad_cli:
# Try to find in PATH
result = subprocess.run(["which", "kicad-cli"], capture_output=True, text=True)
if result.returncode == 0:
kicad_cli = result.stdout.strip()
if not kicad_cli:
print("ERROR: kicad-cli not found. Please run in KiCad scripting console instead:")
print(" exec(open('scripts/autoroute_full.py').read())")
sys.exit(1)
print(f"Using: {kicad_cli}")
# Step 1: Run placement script in KiCad
print("\n[1/4] Placing components...")
# kicad-cli pcb export dsn also runs any embedded scripts, but we need
# to place first. For now, assume placement was done or use Python API
print(" (Run place_8hp.py in KiCad first, or components should already be placed)")
# Step 2: Export DSN
print("\n[2/4] Exporting DSN...")
if not run([kicad_cli, "pcb", "export", "dsn", "-o", DSN_FILE, PCB_FILE],
"Exporting Specctra DSN"):
sys.exit(1)
print(f" Created: {DSN_FILE}")
# Step 3: Download Freerouting if needed
print("\n[3/4] Running Freerouting...")
if not os.path.exists(FREEROUTING_JAR):
print(" Downloading Freerouting...")
if not run(["curl", "-L", "-o", FREEROUTING_JAR, FREEROUTING_URL],
"Downloading"):
sys.exit(1)
# Run Freerouting
result = subprocess.run(
["java", "-jar", FREEROUTING_JAR,
"-de", DSN_FILE,
"-do", SES_FILE,
"-mp", "200",
"-mt", "1",
"-oit"],
capture_output=True,
text=True,
cwd=KICAD_DIR
)
if result.returncode != 0:
print(f" Freerouting error: {result.stderr}")
sys.exit(1)
# Parse output for timing
for line in result.stdout.split('\n') + result.stderr.split('\n'):
if 'completed' in line.lower():
print(f" {line.split(']')[-1].strip()}")
print(f" Created: {SES_FILE}")
# Step 4: Import SES
print("\n[4/4] Importing routed session...")
if not run([kicad_cli, "pcb", "import", "ses", "-i", SES_FILE, PCB_FILE],
"Importing Specctra session"):
# kicad-cli might not support import, manual step needed
print(" NOTE: Import via kicad-cli may not be supported.")
print(" In KiCad: File → Import → Specctra Session")
else:
print(f" Imported routes into: {PCB_FILE}")
print("\n" + "=" * 50)
print("DONE! Open PCB in KiCad and run DRC to verify.")
print("=" * 50)
if __name__ == "__main__":
main()