imrishabh18/rp2040-motor-controller
An RP2040-based NEMA17 stepper-motor controller with USB-C programming and PD motor-power negotiation, DRV8825 dual H-bridge drive, current/temperature telemetry, protected power filtering, status RGB LED, buzzer alarm, and optional magnetic encoder.
- Version
- 1.0.42
- License
- unset
- Stars
- 3
scripts/resume-freerouting.py
"""Make a resumable DSN with routed session geometry and preserved fixed wiring."""
from freerouting_geometry import *
ses=Path(sys.argv[1]);out=Path(sys.argv[2]);base=Path('work/freerouting/board.dsn').read_text();text=ses.read_text().replace('(string_quote ")','(string_quote DQUOTE)');tokens=re.findall(r'"(?:[^"\\]|\\.)*"|[()]|[^\s()]+',text);stack=[];tree=None
for t in tokens:
if t=='(':
obj=[]
if stack:stack[-1].append(obj)
stack.append(obj)
elif t==')':tree=stack.pop()
else:stack[-1].append(t.strip('"'))
def entries(x,k):return [e for e in x if isinstance(e,list) and e and e[0]==k]
def one(x,k):return next(iter(entries(x,k)),None)
routes=one(tree,'routes');res=one(routes,'resolution');scale={'um':1,'mm':1000}[res[1]]/float(res[2]);nets=one(routes,'network_out');wires=[]
fixed=[]
for e in j:
if e['type']=='pcb_trace' and '_SENSE_' not in st[e['source_trace_id']].get('name',''):
for a,b,l,w in trace_segments(e['route']):fixed.append((enet(e),l,LineString([a,b])))
from shapely.ops import unary_union
fixed_union={(n,l):unary_union([g for nn,ll,g in fixed if nn==n and ll==l]).buffer(.0002) for n,l,g in fixed}
manual=[e for e in j if e['type']=='pcb_via']
for n in entries(nets,'net'):
for w in entries(n,'wire'):
p=one(w,'path');nums=[float(x)*scale for x in p[3:]];coords=[(x/1000,y/1000) for x,y in zip(nums[::2],nums[1::2])];line=LineString(coords);protect=(n[1],p[1]) in fixed_union and fixed_union[(n[1],p[1])].covers(line)
wires.append(f'(wire (path {p[1]} {float(p[2])*scale:.4f} '+ ' '.join(f'{x:.4f}' for x in nums)+f') (net {n[1]}) (type {"protect" if protect else "route"}))')
for v in entries(n,'via'):
x,y=float(v[2])*scale/1000,float(v[3])*scale/1000;orig=next((e for e in manual if math.hypot(e['x']-x,e['y']-y)<.0002),None)
if orig:x,y=orig['x'],orig['y']
wires.append(f'(via {v[1]} {u(x)} {u(y)} (net {n[1]}) (type {"protect" if orig else "route"}))')
# These two fine-pitch networks have 0.1-mm local signal/core escape rules.
base=re.sub(r'(\(class C\d+ source_port_(?:71|62|136) \(circuit \(use_via VIA\)\) \(rule \(width )150\.0',r'\g<1>100.0',base)
out.write_text(base.rsplit('\n(wiring ',1)[0]+'\n(wiring '+'\n'.join(wires).replace(' (type route)','')+')\n)\n');print('Resume wiring',len(wires),'objects; fine rules',base.count('(width 100.0)'))
