imrishabh18/nema-23-stepper-controller
A 57 mm four-layer RP2040 NEMA23 stepper-controller PCB with USB‑C/USB‑PD power input, protected motor rail, DRV8452 dual-winding driver, bidirectional current sensing, temperature/enable interlock, optional magnetic encoder, RGB LED and buzzer status indicators, and motor/test connectors.
- Version
- 1.2.3
- License
- unset
- Stars
- 0
scripts/copper_geometry.py
"""Trace segments matching the pinned circuit-json-to-gerber export semantics."""
from shapely.strtree import STRtree
from shapely.ops import unary_union
def subtract_drills(shapes, metadata, barrels, drills, layer_of):
"""Remove drilled-away copper and keep separated physical pieces separate."""
drill_shapes = [g for g, _ in drills]
tree = STRtree(drill_shapes)
new_shapes, new_metadata, mapping = [], [], {}
for i, (shape, meta) in enumerate(zip(shapes, metadata)):
nearby = [drill_shapes[k] for k in tree.query(shape) if layer_of(meta) in drills[k][1]]
cut = shape.difference(unary_union(nearby)) if nearby else shape
pieces = []
def collect(g):
if g.is_empty:
return
if g.geom_type in ('MultiPolygon', 'GeometryCollection'):
for piece in g.geoms:
collect(piece)
elif g.area > 1e-12:
pieces.append(g)
collect(cut)
mapping[i] = list(range(len(new_shapes), len(new_shapes) + len(pieces)))
new_shapes.extend(pieces)
new_metadata.extend([meta] * len(pieces))
return new_shapes, new_metadata, [[n for i in ids for n in mapping[i]] for ids in barrels]
def trace_segments(route):
for a, b in zip(route, route[1:]):
start = end = layer = width = None
if a['route_type'] == 'wire':
start, layer, width = a, a['layer'], a['width']
if b['route_type'] in ('wire', 'via'):
end = b
elif b['route_type'] == 'through_pad':
end = b['start'] if b['start_layer'] == layer else b['end'] if b['end_layer'] == layer else None
elif b['route_type'] == 'wire':
end, layer, width = b, b['layer'], b['width']
if a['route_type'] == 'via':
start = a
elif a['route_type'] == 'through_pad':
start = a['end'] if a['end_layer'] == layer else a['start'] if a['start_layer'] == layer else None
if start is None or end is None or (start['x'] == end['x'] and start['y'] == end['y']):
continue
yield (start['x'], start['y']), (end['x'], end['y']), layer, width