gokul/macro-six-usbc
USB-powered ATmega32U4 controller board with protected/switched 5 V power, six tactile keys, rotary encoder, reset/boot/ISP interfaces, power LED, and six daisy-chained SK6812 RGB LEDs driven through MOSFETs.
- Version
- 0.1.6
- License
- MIT
- Stars
- 0
enclosure/check-open-screws.py
"""Conservative fastener clearance check using supplier mesh and passive bounds."""
from pathlib import Path
import json,math
import numpy as np
import trimesh
ROOT=Path(__file__).resolve().parents[1]
j=json.loads((ROOT/'outputs/release/board.circuit.json').read_text())
sources={e['source_component_id']:e for e in j if e['type']=='source_component'}
pcs={e['pcb_component_id']:e for e in j if e['type']=='pcb_component'}
mounts=[(e['x'],e['y']) for e in j if e['type']=='pcb_hole' and e.get('pcb_component_id') is None and e.get('hole_diameter')==3.2]
clashes=[];checks=0
for e in j:
if e['type']!='cad_component':continue
name=sources[e['source_component_id']]['name'];p=pcs[e['pcb_component_id']]
model='SW6' if name in [f'SW{i}' for i in range(1,7)] else 'Q_RGB' if name=='Q_MAIN' else 'SW_BOOT' if name=='SW_RESET' else 'U_RGB6' if name.startswith('U_RGB') else name
path=ROOT/'work/enclosure-models'/(model+'.obj')
if path.exists():
m=trimesh.load(path,force='mesh',process=False);o=e.get('model_origin_position',{})
m.apply_translation([-o.get(k,0) for k in ['x','y','z']]);m.apply_transform(trimesh.transformations.rotation_matrix(math.radians(e['rotation'].get('z',0)),[0,0,1]))
m.apply_translation([e['position']['x'],e['position']['y'],8.6]);lo,hi=m.bounds
else:
lo=np.array([p['center']['x']-p['width']/2,p['center']['y']-p['height']/2,8.6]);hi=lo+np.array([p['width'],p['height'],2])
for x,y in mounts:
for radius,bottom,top in [(1.5,3.6,13.6),(3,13.6,16)]:
low=np.array([x-radius,y-radius,bottom]);high=np.array([x+radius,y+radius,top]);checks+=1
if np.all(np.minimum(hi,high)-np.maximum(lo,low)>1e-5):clashes.append(name)
assert not clashes,clashes
p=ROOT/'enclosure/exports/open-component-fit.json';r=json.loads(p.read_text())
r['fastener_component_bounds_checks']=checks;r['fastener_component_clearance_pass']=True
r['pcb_mounting_hole_diameter_mm']=3.2;r['screw_nominal_shank_diameter_mm']=3
p.write_text(json.dumps(r,indent=2)+'\n')
print('All',checks,'conservative fastener/component clearance checks passed')