78 行
3.1 KiB
Python
78 行
3.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
u"""下发后逐孔对位置:板上的布线过孔是不是落在缓存给的位置上。
|
||
|
||
/c/Python314/python .claude/r2/via_check.py
|
||
|
||
为什么要查:2026-09-10 发现 USB3 掉头的 USB3_DM 孔在板上比缓存偏了 (−0.127, +0.127) = 正好一格 5 mil,
|
||
原因不明。孔偏了、线端没偏 ⇒ 线和孔之间只剩擦边,`board_check` 按「挨着就算连上」未必报。
|
||
缝合孔(GND、在 `pour_base` 的 4 mm 网格上)不在缓存里,单独计数、不参与对账。
|
||
"""
|
||
import io
|
||
import json
|
||
import math
|
||
import os
|
||
import sys
|
||
|
||
sys.stdout.reconfigure(encoding='utf-8')
|
||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
sys.path.insert(0, os.path.dirname(HERE))
|
||
sys.path.insert(0, HERE)
|
||
from eda import run # noqa: E402
|
||
import pcb_base as B # noqa: E402
|
||
import pour_base as PO # noqa: E402
|
||
|
||
TOL = 0.01
|
||
|
||
JS = u"""
|
||
await eda.dmt_EditorControl.openDocument('%s');
|
||
await new Promise(r=>setTimeout(r,1500));
|
||
return ((await eda.pcb_PrimitiveVia.getAll()) || []).map(v => [v.x / %s, v.y / %s, String(v.net || '')]);
|
||
""" % (B.PCB, B.MIL, B.MIL)
|
||
|
||
|
||
def main():
|
||
r = run(JS, timeout=300)
|
||
if not r.get('success'):
|
||
sys.exit(u'读回过孔失败: ' + json.dumps(r, ensure_ascii=False)[:300])
|
||
board = r['result']
|
||
cache = json.load(io.open(os.path.join(HERE, '_base_routes.json'), encoding='utf-8'))['vias']
|
||
off, pitch = PO.INSET + 2.0, PO.STITCH_PITCH
|
||
|
||
def on_stitch(v):
|
||
return v[2] == 'GND' and all(abs((t - off) / pitch - round((t - off) / pitch)) < 1e-3 for t in v[:2])
|
||
|
||
used = [False] * len(cache)
|
||
moved, extra, n_st = [], [], 0
|
||
for v in board:
|
||
best, bd = None, 1e9
|
||
for i, m in enumerate(cache):
|
||
if m[2] == v[2] and not used[i]:
|
||
d = math.hypot(m[0] - v[0], m[1] - v[1])
|
||
if d < bd:
|
||
best, bd = i, d
|
||
if best is not None and bd < TOL:
|
||
used[best] = True
|
||
elif on_stitch(v):
|
||
n_st += 1
|
||
elif best is not None and bd < 0.5:
|
||
used[best] = True
|
||
moved.append((v, cache[best], bd))
|
||
else:
|
||
extra.append(v)
|
||
missing = [cache[i] for i in range(len(cache)) if not used[i]]
|
||
print(u'板上 %d 孔 = 对上缓存 %d + 缝合 %d + 位置偏了 %d + 缓存里没有 %d;缓存里有、板上没有 %d'
|
||
% (len(board), sum(used) - len(moved), n_st, len(moved), len(extra), len(missing)))
|
||
for v, m, d in moved:
|
||
print(u' 偏了 %-12s 板上 (%.3f, %.3f) 缓存 (%.3f, %.3f) 差 %.3f' % (v[2], v[0], v[1], m[0], m[1], d))
|
||
for v in extra[:20]:
|
||
print(u' 多出 %-12s (%.3f, %.3f)' % (v[2], v[0], v[1]))
|
||
for m in missing[:20]:
|
||
print(u' 缺了 %-12s (%.3f, %.3f)' % (m[2], m[0], m[1]))
|
||
ok = not moved and not extra and not missing
|
||
print(u'[OK] 布线过孔逐个对上' if ok else u'[X] 过孔位置对不上')
|
||
return ok
|
||
|
||
|
||
if __name__ == '__main__':
|
||
sys.exit(0 if main() else 1)
|