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')