R2:底板 / 刀片布局布线脚本、快照、截图与规划文档更新(含外壳、打印件、布线归档)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
zhou yang
2026-10-04 19:24:45 +08:00
共同撰写人 Claude Opus 5.5
父节点 cd01640c40
当前提交 cf7cc9cf90
共修改 759 个文件,包含 76962 行新增和 5299 行删除
+110
查看文件
@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
u"""下板 PCB1:清掉 `C609` / `C612` 转 180° 之后留下的**接错脚的旧铜**。
/c/Python314/python .claude/pcb1_satflip_fix.py # 只列
/c/Python314/python .claude/pcb1_satflip_fix.py --push # 删 + 存盘 + 回查
## 怎么来的
`pcb1_place.SAT_FLIP` 把 C609 / C612(DAC63204 的 VREF 电容)转了 180°,
好让 VREF 脚朝南正对 U6.16 / U7.16(§26.22 的 A 类唯一几何解)。
转完两个脚**南北互换**,而板上那几段铜还是按旧朝向画的,于是:
| 旧铜 | 现在落在 | 后果 |
|---|---|---|
| GND 扇出短线(从电容南脚往南到 GND 过孔)| 南脚现在是 **`$6N532`/`$6N547`** | **GND 短到 VREF** |
| `$6N532`/`$6N547` 出线(从北脚往北去 U6.16)| 北脚现在是 **GND** | **VREF 短到 GND** |
⚠️ **这两条是真短路,不是 DRC 挑剔** —— 端点直接落在对方焊盘的轮廓里
(DRC 报「距离为 0mil」)。`pcb1_place.py` 里预告过「下发时要删 2 段扇出短线」,
就是这件事。
删完这四段之后:
* `$6N532` / `$6N547` 剩下的那截会变成悬空 → 跑 `pcb1_orphan_cu.py --push` 收掉;
* 两颗电容的 GND 脚没有扇出孔了 → 跑 `pcb_fanout.py --net GND --only C609,C612 --push`;
* VREF 那条 0.8 mm 的短连接交给 `pcb1_route_sig.py`。
"""
import json
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from eda import run
PCB = '7e9415a16a909c51'
MIL = 39.3700787
# (网络, 层, x0, y0, x1, y1, 为什么删)。坐标 mm,两端顺序无关,带 0.005 容差匹配。
DEAD = [
('GND', 1, 78.030, 40.277, 78.030, 39.608,
u'C609 的旧 GND 扇出短线;北端 40.277 落在 C609.2($6N532, y 40.205~40.745) 里 = 短路'),
('$6N532', 1, 78.031, 41.318, 78.031, 41.869,
u'C609 的旧 VREF 出线;南端 41.318 落在 C609.1(GND, y 41.045~41.586) 里 = 短路'),
('GND', 1, 108.021, 36.975, 108.021, 36.306,
u'C612 的旧 GND 扇出短线;北端落在 C612.2($6N547) 里 = 短路'),
('$6N547', 1, 108.022, 38.016, 108.022, 38.566,
u'C612 的旧 VREF 出线;南端落在 C612.1(GND) 里 = 短路'),
]
def call(js, timeout=300):
r = run(js, timeout=timeout)
if not r.get('success'):
raise RuntimeError(json.dumps(r, ensure_ascii=False)[:900])
return r['result']
JS = u"""
await eda.dmt_EditorControl.openDocument('%s');
await new Promise(r => setTimeout(r, 2000));
const MIL = %f, D = %s, PUSH = %s;
const TOL = 0.005;
const near = (a, b) => Math.abs(a - b) < TOL;
const same = (r, a, b, c, d) =>
(near(r[2], a) && near(r[3], b) && near(r[4], c) && near(r[5], d)) ||
(near(r[2], c) && near(r[3], d) && near(r[4], a) && near(r[5], b));
const found = [], ids = [];
for (const l of await eda.pcb_PrimitiveLine.getAll()) {
const net = l.net || '', lay = l.layer;
const a = l.startX/MIL, b = l.startY/MIL, c = l.endX/MIL, d = l.endY/MIL;
for (let k = 0; k < D.length; k++) {
const r = D[k];
if (r[0] === net && r[1] === lay && same(r, a, b, c, d)) {
found.push(k); ids.push(l.getState_PrimitiveId());
}
}
}
let deleted = 0;
if (PUSH) {
for (const id of ids) { await eda.pcb_PrimitiveLine.delete(id); deleted++; }
await eda.pcb_Document.save();
}
return {found, deleted, nLine: (await eda.pcb_PrimitiveLine.getAll()).length};
"""
def main():
push = '--push' in sys.argv
rows = [[d[0], d[1], d[2], d[3], d[4], d[5]] for d in DEAD]
r = call(JS % (PCB, MIL, json.dumps(rows), 'true' if push else 'false'))
hit = set(r['found'])
print(u'板上匹配到 %d / %d 段:' % (len(hit), len(DEAD)))
for k, d in enumerate(DEAD):
print(u' [%s] %-8s L%d (%7.3f,%6.3f)-(%7.3f,%6.3f)'
% ('✔' if k in hit else ' ', d[0], d[1], d[2], d[3], d[4], d[5]))
print(u' %s' % d[6])
if not push:
print(u'\n加 --push 删除并存盘')
return
print(u'\n已删 %d 段,板上还剩 %d 条导线' % (r['deleted'], r['nLine']))
back = call(JS % (PCB, MIL, json.dumps(rows), 'false'))
if back['found']:
sys.exit(u'⛔ 回查还剩 %d 段没删干净' % len(set(back['found'])))
print(u' ✔ 回查:四段全部不在板上了')
print(u'\n接着跑:pcb1_orphan_cu.py --push → '
u'pcb_fanout.py --net GND --only C609,C612 --push → drc_read.py')
if __name__ == '__main__':
main()