mohan-bee/fitness-band
A 4-layer BLE wearable mainboard with Li-ion charging/protection, 3.3/1.8 V power regulation, motion and battery sensing, plus a folded 2-layer flex sensor board carrying MAX30102 optical and TMP117 temperature sensors.
- Version
- 0.0.2
- License
- unset
- Stars
- 0
scripts/finish-fabrication.py
"""Add controlled assembly details to the independently routed native release.
Does not move components, pads, traces, vias, or change connectivity.
"""
from pathlib import Path
import json,sys
import pcbnew as k
kind=sys.argv[1];root=Path(__file__).resolve().parents[1]
path=root/f'manufacturing/rev-b/{kind}/{kind}.kicad_pcb';b=k.LoadBoard(str(path))
mm=k.FromMM
def rectangle(layer,x0,y0,x1,y1,filled=True):
s=k.PCB_SHAPE(b);s.SetShape(k.SHAPE_T_RECT);s.SetLayer(layer)
s.SetStart(k.VECTOR2I(mm(x0),mm(y0)));s.SetEnd(k.VECTOR2I(mm(x1),mm(y1)))
s.SetFilled(filled);s.SetWidth(0 if filled else mm(.1));b.Add(s)
def text(layer,string,x,y,size=1):
t=k.PCB_TEXT(b);t.SetText(string);t.SetPosition(k.VECTOR2I(mm(x),mm(y)))
t.SetTextSize(k.VECTOR2I(mm(size),mm(size)));t.SetTextThickness(mm(.15));t.SetLayer(layer);b.Add(t)
hand={'J_SWD','J_BAT','J_CHG','J_FLEX','J_TAIL',*[f'TP{i}' for i in range(1,9)]}
openings=[]
for fp in b.GetFootprints():
ref=fp.GetReference();pads=list(fp.Pads())
if ref in hand:
for p in pads:
ls=p.GetLayerSet();ls.RemoveLayer(k.F_Paste);ls.RemoveLayer(k.B_Paste);p.SetLayerSet(ls)
if kind=='flex' and pads:
if ref=='J_TAIL' or ref.startswith('TP'):
for p in pads:p.SetLocalSolderMaskMargin(mm(.1))
else:
# Coverlay cannot retain 0.1 mm webs between fine-pitch pads.
# Use one grouped window per component, with the existing stencil
# apertures controlling the individual solder deposits.
boxes=[p.GetBoundingBox() for p in pads]
x0=min(q.GetLeft() for q in boxes)/1e6-.1;y0=min(q.GetTop() for q in boxes)/1e6-.1
x1=max(q.GetRight() for q in boxes)/1e6+.1;y1=max(q.GetBottom() for q in boxes)/1e6+.1
# Dedicated laser-coverlay artwork. F.Mask remains the per-pad
# CAD reference; it is not supplied as the flex coverlay Gerber.
rectangle(k.F_Adhes,x0,y0,x1,y1)
openings.append({'ref':ref,'rectangle_mm':[x0,y0,x1,y1]})
if ref.startswith('AUX'):fp.Reference().SetVisible(False)
if kind=='flex':
# All stiffeners are on the bottom. Gerber filenames identify material.
rectangle(k.B_Adhes,100,93,110,107)
rectangle(k.B_Adhes,111,93,118,107)
rectangle(k.Eco1_User,82,93,88,107)
text(k.Dwgs_User,'STATIC FOLD R3 - NO VIA / COMPONENT / STIFFENER',94,109,.8)
else:
text(k.B_SilkS,'FITNESS B',109,108,1)
k.SaveBoard(str(path),b)
projectpath=path.with_suffix('.kicad_pro');project=json.loads(projectpath.read_text())
rules=project['board']['design_settings']['rules']
rules['min_copper_edge_clearance']=.3 if kind=='flex' else .2
rules['min_track_width']=.15 if kind=='flex' else .1
projectpath.write_text(json.dumps(project,indent=2)+'\n')
(root/f'validation/{kind}-fabrication-finish.json').write_text(json.dumps({'coverlay_windows':openings,'hand_solder_contacts_no_paste':sorted(hand)},indent=2)+'\n')