58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import re
|
|
import math
|
|
|
|
import gerbonara.cad.kicad.pcb as pcb
|
|
import gerbonara.cad.primitives as cad_pr
|
|
|
|
|
|
r = 85
|
|
cx, cy = 150, 100
|
|
|
|
|
|
si_prefixes = {'k': 1e3, 'M': 1e6, 'G': 1e9, 'm': 1e-3, 'u': 1e-6, 'µ': 1e-6, 'n': 1e-9, 'p': 1e-12, '.': 1, 'r': 1}
|
|
def parse_si(s, unit=''):
|
|
if not (match := re.fullmatch(f'([0-9]*)(([.pPnNuUµmrRkKMgG])([0-9]*))?([pPnNuUµmrRkKMgG]?)({unit})?', s)):
|
|
raise ValueError(f'{s} is not a valid number with an SI prefix')
|
|
|
|
left, _1, dot, right, prefix, _unit = match.groups()
|
|
prefix = prefix or dot or '.'
|
|
multiplier = si_prefixes.get(prefix, si_prefixes.get(prefix.upper(), si_prefixes.get(prefix.lower())))
|
|
|
|
return float(f'{left}.{right or ""}0') * multiplier
|
|
|
|
|
|
b = pcb.Board.open('self-balancing-test-a.kicad_pcb')
|
|
b.unfill_zones()
|
|
|
|
matches = list(b.find_footprints(name='Package_TO_SOT_SMD:SOT-23', sheetfile='resistor_bank.kicad_sch'))
|
|
|
|
for i, fp in enumerate(sorted(matches, key=lambda fp: fp.parsed_reference[1])):
|
|
alpha = 2*math.pi * i/len(matches)
|
|
fp.at.x, fp.at.y = cx+r, cy
|
|
fp.set_rotation(0)
|
|
|
|
res1, res2 = fp.pads_by_number[3].find_connected(name='Resistor_SMD.*')
|
|
if parse_si(res1.value) > parse_si(res2.value):
|
|
res1, res2 = res2, res1
|
|
|
|
res1.at.x, res1.at.y = cx+r+5, cy+2
|
|
res1.face('right', net='*/V+')
|
|
|
|
res2.at.x, res2.at.y = cx+r+5, cy-2
|
|
res2.face('right', net='*/V+')
|
|
|
|
for tr in [
|
|
cad_pr.Trace(0.5, fp.pad(3), res1.pad(2), orientation=['cw']),
|
|
cad_pr.Trace(0.5, fp.pad(3), res2.pad(2))
|
|
]:
|
|
for obj in b.map_gn_cad(tr):
|
|
obj.rotate(alpha, cx, cy)
|
|
b.add(obj)
|
|
|
|
fp.rotate(alpha, cx, cy)
|
|
res1.rotate(alpha, cx, cy)
|
|
res2.rotate(alpha, cx, cy)
|
|
|
|
b.write('self-balancing-test-a.testout.kicad_pcb')
|