astra/pd-power-supply
USB-PD Power Supply with RP2040 controller
- Version
- 1.1.6
- License
- unset
- Stars
- 0
scripts/verify-fabrication.py
"""Check that exported manufacturing data agrees with the validated board."""
import csv, io, json, math, re, zipfile
from collections import Counter
from pathlib import Path
circuit=json.loads(Path('dist/board/circuit.json').read_text())
parts=json.loads(Path('parts.json').read_text())
vias=[e for e in circuit if e['type']=='pcb_via']
with zipfile.ZipFile('fabrication/gerbers.zip') as archive:
assert {'F_Cu.gbr','In1_Cu.gbr','In2_Cu.gbr','B_Cu.gbr','drill-L1-L4.drl','drill_npth.drl'} <= set(archive.namelist())
drill=archive.read('drill-L1-L4.drl').decode()
tool=next(t for t,d in re.findall(r'^(T\d+)C([\d.]+)$',drill,re.M) if abs(float(d)-.3)<1e-9)
hits=drill.split('\n'+tool+'\n')[1].split('\nM30')[0]
points=[(float(x),float(y)) for x,y in re.findall(r'^X([-\d.]+)Y([-\d.]+)$',hits,re.M)]
assert len(points)==len(vias)==205
assert Counter((round(x,4),round(y,4)) for x,y in points)==Counter((round(v['x'],4),round(v['y'],4)) for v in vias)
bom=list(csv.DictReader(io.StringIO(archive.read('bom.csv').decode())))
assert {r['Designator']:r['JLCPCB Part #'] for r in bom}==parts
cpl=list(csv.DictReader(io.StringIO(archive.read('pick_and_place.csv').decode())))
assert len(cpl)==80 and {r['Designator'] for r in cpl}==set(parts)
source={e['name']:e['source_component_id'] for e in circuit if e['type']=='source_component'}
placements={e['source_component_id']:e for e in circuit if e['type']=='pcb_component'}
for row in cpl:
component=placements[source[row['Designator']]]
assert math.hypot(float(row['Mid X'])-component['center']['x'],float(row['Mid Y'])-component['center']['y'])<.001
print('PASS: four-layer Gerbers; 205 exported 0.3 mm via drill hits match board positions; 80 exact JLC BOM/CPL references.')