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-appearance.py
"""Check the styled references against the existing plate and supplier CAD."""
from pathlib import Path
import hashlib
import json
import cadquery as cq
from appearance import make_appearance
ROOT=Path(__file__).resolve().parents[1]
OUT=ROOT/'enclosure/exports'
j=json.loads((ROOT/'outputs/release/board.circuit.json').read_text())
src={e['source_component_id']:e['name'] for e in j if e['type']=='source_component'}
cad={src[e['source_component_id']]:e for e in j if e['type']=='cad_component'}
keys=[(cad[f'SW{i}']['position']['x'],cad[f'SW{i}']['position']['y']) for i in range(1,7)]
parts=make_appearance(keys,8.6)
plate=cq.importers.importStep(str(OUT/'open-plate.step'))
base=cq.importers.importStep(str(OUT/'bottom.step'))
def supplier(name,filename):
e=cad[name];o=e['model_origin_position']
return (cq.importers.importStep(str(ROOT/'work/enclosure-models'/filename))
.translate(tuple(-o.get(k,0) for k in ['x','y','z']))
.rotate((0,0,0),(0,0,1),e['rotation'].get('z',0))
.translate((e['position']['x'],e['position']['y'],8.6)))
checks=[]
for part in parts:
solid=part['solid']
assert solid.val().isValid(),part['name']
reference=supplier('SW'+part['name'].split('-')[2],'SW6.step') if part['asset']=='keycaps-reference' else supplier('ENC1','ENC1.step')
volume=solid.intersect(reference).val().Volume()
assert volume<1e-5,(part['name'],'supplier interference',volume)
checks.append({'part':part['name'],'supplier_intersection_mm3':round(volume,7)})
for i,(x,y) in enumerate(keys,1):
# The entire 4 mm travel envelope must clear the existing plate and base.
sweep=cq.Workplane('XY').box(18.5,18.5,15,centered=(True,True,False)).translate((x,y,15.1))
for fixed in [plate,base]:assert sweep.intersect(fixed).val().Volume()<1e-5
for part in parts:
if part['asset']!='knob-reference':continue
for fixed in [plate,base]:assert part['solid'].intersect(fixed).val().Volume()<1e-5
for asset in ['keycaps-reference','knob-reference']:
solids=[s for p in parts if p['asset']==asset for s in p['solid'].solids().vals()]
cq.exporters.export(cq.Compound.makeCompound(solids),str(OUT/(asset+'.step')))
report={'supplier_checks':checks,'keycap_travel_mm':4,'travel_clear_of_plate_and_base':True,
'keycap_width_mm':18.5,'knob_diameter_mm':18,'knob_axis_xy_mm':[43,.2499873],
'physical_fit_verified':False,'references_only':True,
'pcb_sha256':hashlib.sha256((ROOT/'outputs/release/board.circuit.json').read_bytes()).hexdigest()}
(OUT/'appearance-checks.json').write_text(json.dumps(report,indent=2)+'\n')
print('Styled keycaps and knob: supplier CAD, plate and travel checks passed',flush=True)