52 lines
3.2 KiB
Python
52 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Fertigungsdaten: Gerber+Bohrdaten (zip), Stückliste mit Inventar-Fächern, Schaltplan-PDF, 1:1-Druck, Doku-Bilder."""
|
|
import os, sys, csv, shutil, subprocess, zipfile, collections
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.insert(0, HERE)
|
|
from design import PARTS, PROJECT
|
|
FAB = os.path.join(HERE, 'fab'); G = os.path.join(FAB, 'gerber')
|
|
shutil.rmtree(G, ignore_errors=True); os.makedirs(G)
|
|
pcb = os.path.join(HERE, PROJECT + '.kicad_pcb'); sch = os.path.join(HERE, PROJECT + '.kicad_sch')
|
|
def run(*a):
|
|
subprocess.run(a, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
|
|
run('kicad-cli', 'pcb', 'export', 'gerbers', '-o', G + '/', '--layers',
|
|
'F.Cu,B.Cu,F.Silkscreen,B.Silkscreen,F.Mask,B.Mask,Edge.Cuts', '--subtract-soldermask', pcb)
|
|
run('kicad-cli', 'pcb', 'export', 'drill', '-o', G + '/', '--format', 'excellon', '--excellon-separate-th', pcb)
|
|
zp = os.path.join(FAB, PROJECT + '_gerber.zip')
|
|
with zipfile.ZipFile(zp, 'w', zipfile.ZIP_DEFLATED) as z:
|
|
for f in sorted(os.listdir(G)):
|
|
z.write(os.path.join(G, f), f)
|
|
run('kicad-cli', 'sch', 'export', 'pdf', '-o', os.path.join(FAB, PROJECT + '_schaltplan.pdf'), sch)
|
|
run('kicad-cli', 'pcb', 'export', 'pdf', '--mode-single', '-l', 'F.Silkscreen,F.Fab,Edge.Cuts,F.Courtyard',
|
|
'--include-border-title', '-o', os.path.join(FAB, PROJECT + '_1zu1_druck.pdf'), pcb)
|
|
|
|
# ---------- Stückliste ----------
|
|
INV = { # (Wert, Footprint-Teil) -> Inventar-Fach (Parts_Inventory.xlsx)
|
|
'100': 'E-01-3', '220': 'E-05-3', '330': 'E-07-3', '470': 'E-09-3', '1k': 'E-01-4', '2k2': 'E-05-4',
|
|
'4k7': 'E-09-4', '10k': 'E-01-5', '100n': 'C-07-1', '10u': 'C-10-2 / D-04-3', '470u/10V': 'C-04-3',
|
|
'1000u/10V': 'C-05-3', 'BC546B': 'B-01-4', '1N4007': 'B-02-1', 'LED grün': 'B-07-5', 'LED rot': 'B-08-5',
|
|
'Pull-up 5V': 'A-07-2 + Jumper A-11-3', 'ERWEITERUNG': 'A-07-2',
|
|
'SRD-05VDC-SL-C': 'A-07-1 prüfen (sonst kaufen)', 'T 2A': 'Clips/Halter B-12-2, Sicherung B-11-2',
|
|
'WEMOS D1 mini': 'Buchsenleisten A-06-5 / A-07-3', 'ADS1115 Modul': 'Buchsenleiste A-06-5; Modul ggf. B-11-5',
|
|
'MAX6675 Modul': 'Buchsenleiste A-06-5; Modul ggf. B-11-5',
|
|
}
|
|
BUY = {'ZMCT103C': 'kaufen (Stromwandler 5A/5mA)', 'MAX6675 Modul': 'kaufen inkl. Thermoelement Typ K (Abgasfühler)',
|
|
'ADS1115 Modul': 'kaufen, falls kein Rest von der Umwälzpumpe', 'WEMOS D1 mini': 'vorhanden/kaufen'}
|
|
rows = collections.OrderedDict()
|
|
for p in PARTS:
|
|
if p.get('board') is False or p['ref'].startswith('H'):
|
|
continue
|
|
key = (p['val'], p['fp'].split(':')[-1])
|
|
rows.setdefault(key, []).append(p)
|
|
with open(os.path.join(FAB, PROJECT + '_bom.csv'), 'w', newline='') as f:
|
|
w = csv.writer(f, delimiter=';')
|
|
w.writerow(['Anzahl', 'Referenzen', 'Wert', 'Footprint', 'Inventar-Fach', 'Beschaffung / Hinweis'])
|
|
for (val, fp), ps in rows.items():
|
|
refs = ' '.join(sorted((q['ref'] for q in ps), key=lambda r: (r.rstrip('0123456789'), int(''.join(c for c in r if c.isdigit()) or 0))))
|
|
term = ps[0]['fp'].startswith('Connector_Phoenix')
|
|
inv = '' if term else INV.get(val, '')
|
|
hint = ps[0].get('mpn') or BUY.get(val, '')
|
|
w.writerow([len(ps), refs, val, fp, inv, hint])
|
|
print('fab ok:', sorted(os.listdir(FAB)))
|