v6 T16 script + bump kicad (mounting holes 130 x 90)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJ4eAB6zjQT49RVwpgfKdt
This commit is contained in:
parent
2b03a7ee02
commit
c160ed4aa6
@ -1 +1 @@
|
||||
Subproject commit fdffd441d48a60d02cfbae93ecaae2246808e663
|
||||
Subproject commit 61652ccc3f92403e89a01f0ba88660caeaed6be3
|
||||
79
scripts/2026-09-25_v6_T16_mounting_holes.py
Normal file
79
scripts/2026-09-25_v6_T16_mounting_holes.py
Normal file
@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""v6 T16 — square up the 4 mounting holes and give them unique references.
|
||||
|
||||
Found 25-Sep: the board (140 x 100 mm, Edge.Cuts x 60.19–200.19, y 40.32–140.32) had
|
||||
MH5 (65.2, 45.3) MH6 (65.2, 135.3) <- west pair, same position since v4/v5 (proven)
|
||||
MH6 (195.5, 45.0) MH6 (195.5, 135.5) <- east pair off by 0.3 / 0.2 / 0.5 mm
|
||||
so the pattern was 130.3 x 90.0 on the west and 90.5 on the east, and three holes shared "MH6".
|
||||
|
||||
Fix: keep the proven west pair and mirror it -> a clean 130.0 x 90.0 mm rectangle, every hole
|
||||
~5.0 mm from its two edges, centred on the board:
|
||||
MH5 (65.2, 45.3) MH6 (65.2, 135.3) MH7 (195.2, 45.3) MH8 (195.2, 135.3)
|
||||
|
||||
Only the footprint (at …) line and the Reference value change; the holes keep their UUIDs.
|
||||
|
||||
python3 T16.py hbox-watchdog-v6.kicad_pcb # dry run
|
||||
python3 T16.py hbox-watchdog-v6.kicad_pcb --apply # writes .T16bak
|
||||
"""
|
||||
import re, sys, shutil
|
||||
|
||||
TARGET = [ # (current ref, current x, y) -> (new ref, x, y)
|
||||
(('MH5', 65.2, 45.3), ('MH5', 65.2, 45.3)),
|
||||
(('MH6', 65.2, 135.3), ('MH6', 65.2, 135.3)),
|
||||
(('MH6', 195.5, 45.0), ('MH7', 195.2, 45.3)),
|
||||
(('MH6', 195.5, 135.5), ('MH8', 195.2, 135.3)),
|
||||
]
|
||||
|
||||
def span(s, i):
|
||||
d = 0; instr = False; j = i
|
||||
while True:
|
||||
c = s[j]
|
||||
if c == '"' and s[j-1] != '\\': instr = not instr
|
||||
elif not instr:
|
||||
if c == '(': d += 1
|
||||
elif c == ')':
|
||||
d -= 1
|
||||
if d == 0: return j + 1
|
||||
j += 1
|
||||
|
||||
def holes(s):
|
||||
out = []
|
||||
for m in re.finditer(r'\n\t\(footprint "MountingHole:[^"]*"', s):
|
||||
a = m.start() + 1; e = span(s, a); b = s[a:e]
|
||||
at = re.search(r'\n\t\t\(at (-?[\d.]+) (-?[\d.]+)([^)]*)\)', b)
|
||||
ref = re.search(r'\(property "Reference" "([^"]*)"', b).group(1)
|
||||
out.append(dict(a=a, e=e, ref=ref, x=float(at.group(1)), y=float(at.group(2)), rot=at.group(3)))
|
||||
return out
|
||||
|
||||
def main():
|
||||
path = sys.argv[1]; apply = '--apply' in sys.argv
|
||||
s0 = open(path).read(); s = s0; ch = []
|
||||
hs = holes(s0)
|
||||
assert len(hs) == 4, f'expected 4 mounting holes, found {len(hs)}'
|
||||
edits = []
|
||||
for (r0, x0, y0), (r1, x1, y1) in TARGET:
|
||||
h = [h for h in hs if abs(h['x'] - x1) < 1e-3 and abs(h['y'] - y1) < 1e-3 and h['ref'] == r1]
|
||||
if h: continue # already in place
|
||||
h = [h for h in hs if abs(h['x'] - x0) < 1e-3 and abs(h['y'] - y0) < 1e-3 and h['ref'] == r0]
|
||||
if len(h) != 1: raise SystemExit(f'cannot identify hole {r0} at ({x0},{y0})')
|
||||
edits.append((h[0], r1, x1, y1))
|
||||
for h, r1, x1, y1 in sorted(edits, key=lambda t: -t[0]['a']):
|
||||
b = s[h['a']:h['e']]
|
||||
b = re.sub(r'\n\t\t\(at (-?[\d.]+) (-?[\d.]+)([^)]*)\)', f'\n\t\t(at {x1:g} {y1:g}{h["rot"]})', b, count=1)
|
||||
b = b.replace(f'(property "Reference" "{h["ref"]}"', f'(property "Reference" "{r1}"', 1)
|
||||
s = s[:h['a']] + b + s[h['e']:]
|
||||
ch.append(f'{h["ref"]} ({h["x"]:g},{h["y"]:g}) -> {r1} ({x1:g},{y1:g})')
|
||||
hs1 = holes(s)
|
||||
refs = [h['ref'] for h in hs1]
|
||||
assert sorted(refs) == ['MH5', 'MH6', 'MH7', 'MH8'], refs
|
||||
xs = sorted({h['x'] for h in hs1}); ys = sorted({h['y'] for h in hs1})
|
||||
assert len(xs) == 2 and len(ys) == 2, 'holes not on a rectangle'
|
||||
print('\n'.join(ch) or 'nothing to do (already applied)')
|
||||
print(f'pattern {xs[1]-xs[0]:.2f} x {ys[1]-ys[0]:.2f} mm')
|
||||
if ch and apply:
|
||||
shutil.copy2(path, path + '.T16bak'); open(path, 'w').write(s); print('APPLIED (backup .T16bak)')
|
||||
elif ch:
|
||||
print('DRY RUN — re-run with --apply')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Reference in New Issue
Block a user