shibosoftwaredev/f1c100s-linux-nema17-stepper-controller

A four-layer NEMA 17 motor-controller PCB combining an Allwinner F1C100S Linux computer, USB‑PD/buck power system, W5500 Ethernet, STM32 real-time motion control, DRV8825 stepper driver, protection/temperature/current telemetry, USB interfaces, and local LED/buzzer diagnostics.

Version
0.4.56
License
unset
Stars
0

scripts/list-local-drill-sites.py

"""Geometric drill-placement feedback only. Does not create or route tracks."""
from route_geometry import *
from shapely.strtree import STRtree
import sys
c=load_circuit();root=connectivity(c);m=json.loads(Path('routing/net-map.json').read_text())['roots']
ns={e['source_component_id']:e['name'] for e in c if e['type']=='source_component'}
ports={e['pcb_port_id']:e for e in c if e['type']=='pcb_port'}
objects=[];pads=[];holes=[]
for e in c:
    if e['type'] in ['pcb_smtpad','pcb_plated_hole']:
        p=ports.get(e.get('pcb_port_id'));n=m.get(root(p['source_port_id'])) if p else None
        g=geometry(e,'outer_' if e['type']=='pcb_plated_hole' else '')
        objects.append((n,g,'pad'));pads.append(g)
    if e['type']=='pcb_hole':holes.append(geometry(e,'hole_'))
cu=json.loads(Path('routing/physical-copper.json').read_text())
for w in cu['wires']:objects.append((w['net'],LineString(w['points']).buffer(w['width']/2,quad_segs=12),'track'))
via_points=[Point(v['x'],v['y']) for v in cu['vias']]
for v in cu['vias']:objects.append((None,Point(v['x'],v['y']).buffer(.2),'via'))
tree=STRtree([g for n,g,k in objects]);pad_tree=STRtree(pads);h_tree=STRtree(holes)
source=next(e for e in c if e['type']=='source_port' and ns[e['source_component_id']]==sys.argv[1] and e.get('pin_number')==int(sys.argv[2]))
p=next(e for e in ports.values() if e['source_port_id']==source['source_port_id']);net=m[root(source['source_port_id'])]
candidates=sorted((math.hypot(ix/20,iy/20),p['x']+ix/20,p['y']+iy/20) for ix in range(-80,81) for iy in range(-80,81))
selected=[]
for distance,x,y in candidates:
    if max(abs(x),abs(y))>20.725:continue
    q=Point(x,y)
    if any(math.hypot(x-xx,y-yy)<3.075 for xx in [-15.5,15.5] for yy in [-15.5,15.5]):continue
    if any(q.distance(holes[j])<.425-1e-7 for j in h_tree.query(q.buffer(.425))):continue
    # No drilled solder lands, including own-net SMD lands.
    if any(q.distance(pads[j])<.16 for j in pad_tree.query(q.buffer(.16))):continue
    if any(n!=net and q.distance(g)<.35-1e-7 for j in tree.query(q.buffer(.35)) for n,g,k in [objects[j]]):continue
    if any(math.hypot(x-r[0],y-r[1])<.55 for r in selected):continue
    selected.append((round(x,6),round(y,6),round(distance,3)))
    if len(selected)==15:break
print(json.dumps(dict(part=sys.argv[1],pin=int(sys.argv[2]),net=net,sites=selected)))